diff --git a/examples/v1/example.nim b/examples/v1/example.nim index 2fe4f150c..f82e3ebe8 100644 --- a/examples/v1/example.nim +++ b/examples/v1/example.nim @@ -10,7 +10,7 @@ import const clientId = "Waku example v1" -proc run(config: WakuNodeConf, rng: ref BrHmacDrbgContext) = +proc run(config: WakuNodeConf, rng: ref HmacDrbgContext) = # Set up the address according to NAT information. let (ipExt, tcpPortExt, udpPortExt) = setupNat(config.nat, clientId, Port(config.tcpPort + config.portsShift), @@ -33,6 +33,8 @@ proc run(config: WakuNodeConf, rng: ref BrHmacDrbgContext) = nil, # Database, not required for Waku clientId, # Client id string addAllCapabilities = false, # Disable default all RLPx capabilities + bindUdpPort = address.udpPort, # Assume same as external + bindTcpPort = address.tcpPort, # Assume same as external rng = rng) node.addCapability Waku # Enable only the Waku protocol. @@ -57,7 +59,7 @@ proc run(config: WakuNodeConf, rng: ref BrHmacDrbgContext) = # connection occurs, which is why we use a callback to exit on errors instead of # using `await`. # TODO: This looks a bit awkward and the API should perhaps be altered here. - let connectedFut = node.connectToNetwork(@[], + let connectedFut = node.connectToNetwork( true, # Enable listening false # Disable discovery (only discovery v4 is currently supported) ) diff --git a/examples/v2/basic2.nim b/examples/v2/basic2.nim index a6980a85e..bb04e2662 100644 --- a/examples/v2/basic2.nim +++ b/examples/v2/basic2.nim @@ -25,7 +25,7 @@ proc runBackground() {.async.} = Port(uint16(conf.tcpPort) + conf.portsShift), extIp, extTcpPort) await node.start() - node.mountRelay() + await node.mountRelay() # Subscribe to a topic let topic = cast[Topic]("foobar") diff --git a/examples/v2/chat2.nim b/examples/v2/chat2.nim index fe0c4a69c..41e3062fe 100644 --- a/examples/v2/chat2.nim +++ b/examples/v2/chat2.nim @@ -214,9 +214,10 @@ proc publish(c: Chat, line: string) = when PayloadV1: # Use Waku v1 payload encoding/encryption let + rng = keys.newRng() payload = Payload(payload: chat2pb.buffer, symKey: some(c.symKey)) version = 1'u32 - encodedPayload = payload.encode(version, c.node.rng[]) + encodedPayload = payload.encode(version, rng[]) if encodedPayload.isOk(): var message = WakuMessage(payload: encodedPayload.get(), contentTopic: c.contentTopic, version: version, timestamp: getNanosecondTime(time)) @@ -359,7 +360,7 @@ proc readInput(wfd: AsyncFD) {.thread, raises: [Defect, CatchableError].} = discard waitFor transp.write(line & "\r\n") {.pop.} # @TODO confutils.nim(775, 17) Error: can raise an unlisted exception: ref IOError -proc processInput(rfd: AsyncFD, rng: ref BrHmacDrbgContext) {.async.} = +proc processInput(rfd: AsyncFD) {.async.} = let transp = fromPipe(rfd) let @@ -375,10 +376,10 @@ proc processInput(rfd: AsyncFD, rng: ref BrHmacDrbgContext) {.async.} = wssEnabled = conf.websocketSecureSupport) await node.start() - node.mountRelay(conf.topics.split(" "), - relayMessages = conf.relay) # Indicates if node is capable to relay messages + if conf.relay: + await node.mountRelay(conf.topics.split(" ")) - node.mountLibp2pPing() + await node.mountLibp2pPing() let nick = await readNick(transp) echo "Welcome, " & nick & "!" @@ -445,10 +446,10 @@ proc processInput(rfd: AsyncFD, rng: ref BrHmacDrbgContext) {.async.} = echo &"Listening on\n {listenStr}" if conf.swap: - node.mountSwap() + await node.mountSwap() if (conf.storenode != "") or (conf.store == true): - node.mountStore(persistMessages = conf.persistMessages) + await node.mountStore(persistMessages = conf.persistMessages) var storenode: Option[RemotePeerInfo] @@ -477,12 +478,12 @@ proc processInput(rfd: AsyncFD, rng: ref BrHmacDrbgContext) {.async.} = # NOTE Must be mounted after relay if conf.lightpushnode != "": - mountLightPush(node) + await mountLightPush(node) node.wakuLightPush.setPeer(parseRemotePeerInfo(conf.lightpushnode)) if conf.filternode != "": - node.mountFilter() + await node.mountFilter() node.wakuFilter.setPeer(parseRemotePeerInfo(conf.filternode)) @@ -545,7 +546,6 @@ proc processInput(rfd: AsyncFD, rng: ref BrHmacDrbgContext) {.async.} = runForever() proc main() {.async.} = - let rng = crypto.newRng() # Singe random number source for the whole application let (rfd, wfd) = createAsyncPipe() if rfd == asyncInvalidPipe or wfd == asyncInvalidPipe: raise newException(ValueError, "Could not initialize pipe!") @@ -553,7 +553,7 @@ proc main() {.async.} = var thread: Thread[AsyncFD] thread.createThread(readInput, wfd) - await processInput(rfd, rng) + await processInput(rfd) when isMainModule: # isMainModule = true when the module is compiled as the main file waitFor(main()) diff --git a/examples/v2/config_chat2.nim b/examples/v2/config_chat2.nim index 1cd89de6c..97532e79c 100644 --- a/examples/v2/config_chat2.nim +++ b/examples/v2/config_chat2.nim @@ -24,7 +24,7 @@ type nodekey* {. desc: "P2P node private key as 64 char hex string.", - defaultValue: crypto.PrivateKey.random(Secp256k1, keys.newRng()[]).tryGet() + defaultValue: crypto.PrivateKey.random(Secp256k1, crypto.newRng()[]).tryGet() name: "nodekey" }: crypto.PrivateKey listenAddress* {. diff --git a/examples/v2/matterbridge/chat2bridge.nim b/examples/v2/matterbridge/chat2bridge.nim index a80b36386..c4ce040cc 100644 --- a/examples/v2/matterbridge/chat2bridge.nim +++ b/examples/v2/matterbridge/chat2bridge.nim @@ -186,7 +186,7 @@ proc start*(cmb: Chat2MatterBridge) {.async.} = # Always mount relay for bridge # `triggerSelf` is false on a `bridge` to avoid duplicates - cmb.nodev2.mountRelay(triggerSelf = false) + await cmb.nodev2.mountRelay(triggerSelf = false) # Bridging # Handle messages on Waku v2 and bridge to Matterbridge @@ -263,13 +263,13 @@ when isMainModule: # Now load rest of config # Mount configured Waku v2 protocols - mountLibp2pPing(bridge.nodev2) + waitFor mountLibp2pPing(bridge.nodev2) if conf.store: - mountStore(bridge.nodev2) + waitFor mountStore(bridge.nodev2) if conf.filter: - mountFilter(bridge.nodev2) + waitFor mountFilter(bridge.nodev2) if conf.staticnodes.len > 0: waitFor connectToNodes(bridge.nodev2, conf.staticnodes) diff --git a/nimbus-build-system.paths b/nimbus-build-system.paths new file mode 100644 index 000000000..169e78c00 --- /dev/null +++ b/nimbus-build-system.paths @@ -0,0 +1,33 @@ +--noNimblePath +--path:"/home/runner/work/nwaku/nwaku/vendor/dnsclient.nim/src" +--path:"/home/runner/work/nwaku/nwaku/vendor/news/src" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-bearssl" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-chronicles" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-chronos" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-confutils" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-dnsdisc" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-eth" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-faststreams" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-http-utils" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-json-rpc" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-json-serialization" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-libbacktrace" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-libp2p" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-metrics" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-nat-traversal" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-presto" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-secp256k1" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-serialization" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-sqlite3-abi" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-stew" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-stint" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-testutils" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-toml-serialization" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-unittest2" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-web3" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-websock" +--path:"/home/runner/work/nwaku/nwaku/vendor/nim-zlib" +--path:"/home/runner/work/nwaku/nwaku/vendor/nimbus-build-system" +--path:"/home/runner/work/nwaku/nwaku/vendor/nimcrypto" +--path:"/home/runner/work/nwaku/nwaku/vendor/rln/src" +--path:"/home/runner/work/nwaku/nwaku/vendor/zerokit" diff --git a/tests/test_helpers.nim b/tests/test_helpers.nim index 9acb2311f..aa5492ea8 100644 --- a/tests/test_helpers.nim +++ b/tests/test_helpers.nim @@ -1,5 +1,5 @@ import - chronos, bearssl, + chronos, bearssl/rand, eth/[keys, p2p] import libp2p/crypto/crypto @@ -12,22 +12,27 @@ proc localAddress*(port: int): Address = ip: parseIpAddress("127.0.0.1")) proc setupTestNode*( - rng: ref BrHmacDrbgContext, + rng: ref HmacDrbgContext, capabilities: varargs[ProtocolInfo, `protocolInfo`]): EthereumNode = - let keys1 = keys.KeyPair.random(rng[]) - result = newEthereumNode(keys1, localAddress(nextPort), NetworkId(1), nil, - addAllCapabilities = false, rng = rng) + let + keys1 = keys.KeyPair.random(rng[]) + address = localAddress(nextPort) + result = newEthereumNode(keys1, address, NetworkId(1), nil, + addAllCapabilities = false, + bindUdpPort = address.udpPort, # Assume same as external + bindTcpPort = address.tcpPort, # Assume same as external + rng = rng) nextPort.inc for capability in capabilities: result.addCapability capability # Copied from here: https://github.com/status-im/nim-libp2p/blob/d522537b19a532bc4af94fcd146f779c1f23bad0/tests/helpers.nim#L28 type RngWrap = object - rng: ref BrHmacDrbgContext + rng: ref rand.HmacDrbgContext var rngVar: RngWrap -proc getRng(): ref BrHmacDrbgContext = +proc getRng(): ref rand.HmacDrbgContext = # TODO if `rngVar` is a threadvar like it should be, there are random and # spurious compile failures on mac - this is not gcsafe but for the # purpose of the tests, it's ok as long as we only use a single thread @@ -36,5 +41,5 @@ proc getRng(): ref BrHmacDrbgContext = rngVar.rng = crypto.newRng() rngVar.rng -template rng*(): ref BrHmacDrbgContext = +template rng*(): ref rand.HmacDrbgContext = getRng() diff --git a/tests/v1/test_rpc_waku.nim b/tests/v1/test_rpc_waku.nim index 49590ba79..cae2e6021 100644 --- a/tests/v1/test_rpc_waku.nim +++ b/tests/v1/test_rpc_waku.nim @@ -14,14 +14,14 @@ const sigPath = sourceDir / ParDir / ParDir / "waku" / "v1" / "node" / "rpc" / " createRpcSigs(RpcSocketClient, sigPath) proc setupNode(capabilities: varargs[ProtocolInfo, `protocolInfo`], - rng: ref BrHmacDrbgContext, ): EthereumNode = + rng: ref HmacDrbgContext, ): EthereumNode = let keypair = KeyPair.random(rng[]) srvAddress = Address(ip: parseIpAddress("0.0.0.0"), tcpPort: Port(30303), udpPort: Port(30303)) result = newEthereumNode(keypair, srvAddress, NetworkId(1), nil, "waku test rpc", - addAllCapabilities = false, rng = rng) + addAllCapabilities = false, bindUdpPort = srvAddress.udpPort, bindTcpPort = srvAddress.tcpPort, rng = rng) for capability in capabilities: result.addCapability capability diff --git a/tests/v1/test_waku_connect.nim b/tests/v1/test_waku_connect.nim index baeee6b67..7631b9b29 100644 --- a/tests/v1/test_waku_connect.nim +++ b/tests/v1/test_waku_connect.nim @@ -44,11 +44,11 @@ procSuite "Waku connections": n3 = setupTestNode(rng, Waku) n4 = setupTestNode(rng, Waku) - var topics: seq[Topic] + var topics: seq[waku_protocol.Topic] n1.protocolState(Waku).config.topics = some(topics) n2.protocolState(Waku).config.topics = some(topics) - n3.protocolState(Waku).config.topics = none(seq[Topic]) - n4.protocolState(Waku).config.topics = none(seq[Topic]) + n3.protocolState(Waku).config.topics = none(seq[waku_protocol.Topic]) + n4.protocolState(Waku).config.topics = none(seq[waku_protocol.Topic]) n1.startListening() n3.startListening() @@ -499,7 +499,7 @@ procSuite "Waku connections": let bloomFilterUpdatedCondition = proc(): bool = for peer in wakuNode.peerPool.peers: return peer.state(Waku).bloom == bloom and - peer.state(Waku).topics == none(seq[Topic]) + peer.state(Waku).topics == none(seq[waku_protocol.Topic]) let bloomFilterUpdated = await eventually(conditionTimeoutMs, bloomFilterUpdatedCondition) diff --git a/tests/v2/test_jsonrpc_waku.nim b/tests/v2/test_jsonrpc_waku.nim index 31b971ea2..0273ccabb 100644 --- a/tests/v2/test_jsonrpc_waku.nim +++ b/tests/v2/test_jsonrpc_waku.nim @@ -47,7 +47,7 @@ procSuite "Waku v2 JSON-RPC API": asyncTest "Debug API: get node info": waitFor node.start() - node.mountRelay() + await node.mountRelay() # RPC server setup let @@ -74,7 +74,7 @@ procSuite "Waku v2 JSON-RPC API": asyncTest "Relay API: publish and subscribe/unsubscribe": waitFor node.start() - node.mountRelay() + await node.mountRelay() # RPC server setup let @@ -137,13 +137,13 @@ procSuite "Waku v2 JSON-RPC API": message2 = WakuMessage(payload: payload2, contentTopic: contentTopic) await node1.start() - node1.mountRelay(@[pubSubTopic]) + await node1.mountRelay(@[pubSubTopic]) await node2.start() - node2.mountRelay(@[pubSubTopic]) + await node2.mountRelay(@[pubSubTopic]) await node3.start() - node3.mountRelay(@[pubSubTopic]) + await node3.mountRelay(@[pubSubTopic]) await node1.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()]) await node3.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()]) @@ -215,7 +215,7 @@ procSuite "Waku v2 JSON-RPC API": asyncTest "Store API: retrieve historical messages": waitFor node.start() - node.mountRelay() + await node.mountRelay() # RPC server setup let @@ -231,7 +231,7 @@ procSuite "Waku v2 JSON-RPC API": key = wakunode2.PrivateKey.random(ECDSA, rng[]).get() peer = PeerInfo.new(key) - node.mountStore(persistMessages = true) + await node.mountStore(persistMessages = true) var listenSwitch = newStandardSwitch(some(key)) waitFor listenSwitch.start() @@ -273,9 +273,9 @@ procSuite "Waku v2 JSON-RPC API": asyncTest "Filter API: subscribe/unsubscribe": waitFor node.start() - node.mountRelay() + await node.mountRelay() - node.mountFilter() + await node.mountFilter() # RPC server setup let @@ -329,7 +329,7 @@ procSuite "Waku v2 JSON-RPC API": installFilterApiHandlers(node, server, newTable[ContentTopic, seq[WakuMessage]]()) server.start() - node.mountFilter() + await node.mountFilter() let client = newRpcHttpClient() await client.connect("127.0.0.1", rpcPort, false) @@ -412,9 +412,9 @@ procSuite "Waku v2 JSON-RPC API": await allFutures([node1.start(), node2.start(), node3.start()]) - node1.mountRelay() - node2.mountRelay() - node3.mountRelay() + await node1.mountRelay() + await node2.mountRelay() + await node3.mountRelay() # RPC server setup let @@ -469,9 +469,9 @@ procSuite "Waku v2 JSON-RPC API": await allFutures([node1.start(), node2.start(), node3.start()]) - node1.mountRelay() - node2.mountRelay() - node3.mountRelay() + await node1.mountRelay() + await node2.mountRelay() + await node3.mountRelay() # Dial nodes 2 and 3 from node1 await node1.connectToNodes(@[constructMultiaddrStr(peerInfo2)]) @@ -525,9 +525,9 @@ procSuite "Waku v2 JSON-RPC API": let client = newRpcHttpClient() await client.connect("127.0.0.1", rpcPort, false) - node.mountFilter() - node.mountSwap() - node.mountStore(persistMessages = true) + await node.mountFilter() + await node.mountSwap() + await node.mountStore(persistMessages = true) # Create and set some peers let @@ -577,13 +577,13 @@ procSuite "Waku v2 JSON-RPC API": topicCache = newTable[string, seq[WakuMessage]]() await node1.start() - node1.mountRelay(@[pubSubTopic]) + await node1.mountRelay(@[pubSubTopic]) await node2.start() - node2.mountRelay(@[pubSubTopic]) + await node2.mountRelay(@[pubSubTopic]) await node3.start() - node3.mountRelay(@[pubSubTopic]) + await node3.mountRelay(@[pubSubTopic]) await node1.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()]) await node3.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()]) @@ -598,8 +598,8 @@ procSuite "Waku v2 JSON-RPC API": server3 = newRpcHttpServer([ta3]) # Let's connect to nodes 1 and 3 via the API - installPrivateApiHandlers(node1, server1, rng, newTable[string, seq[WakuMessage]]()) - installPrivateApiHandlers(node3, server3, rng, topicCache) + installPrivateApiHandlers(node1, server1, newTable[string, seq[WakuMessage]]()) + installPrivateApiHandlers(node3, server3, topicCache) installRelayApiHandlers(node3, server3, topicCache) server1.start() server3.start() @@ -668,13 +668,13 @@ procSuite "Waku v2 JSON-RPC API": topicCache = newTable[string, seq[WakuMessage]]() await node1.start() - node1.mountRelay(@[pubSubTopic]) + await node1.mountRelay(@[pubSubTopic]) await node2.start() - node2.mountRelay(@[pubSubTopic]) + await node2.mountRelay(@[pubSubTopic]) await node3.start() - node3.mountRelay(@[pubSubTopic]) + await node3.mountRelay(@[pubSubTopic]) await node1.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()]) await node3.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()]) @@ -689,8 +689,8 @@ procSuite "Waku v2 JSON-RPC API": server3 = newRpcHttpServer([ta3]) # Let's connect to nodes 1 and 3 via the API - installPrivateApiHandlers(node1, server1, rng, newTable[string, seq[WakuMessage]]()) - installPrivateApiHandlers(node3, server3, rng, topicCache) + installPrivateApiHandlers(node1, server1, newTable[string, seq[WakuMessage]]()) + installPrivateApiHandlers(node3, server3, topicCache) installRelayApiHandlers(node3, server3, topicCache) server1.start() server3.start() diff --git a/tests/v2/test_peer_exchange.nim b/tests/v2/test_peer_exchange.nim index c434f1b91..456e4d7fc 100644 --- a/tests/v2/test_peer_exchange.nim +++ b/tests/v2/test_peer_exchange.nim @@ -52,9 +52,9 @@ procSuite "Peer Exchange": peerExchangeHandler = handlePeerExchange emptyHandler = ignorePeerExchange - node1.mountRelay(peerExchangeHandler = some(emptyHandler)) - node2.mountRelay(peerExchangeHandler = some(emptyHandler)) - node3.mountRelay(peerExchangeHandler = some(peerExchangeHandler)) + await node1.mountRelay(peerExchangeHandler = some(emptyHandler)) + await node2.mountRelay(peerExchangeHandler = some(emptyHandler)) + await node3.mountRelay(peerExchangeHandler = some(peerExchangeHandler)) # Ensure that node1 prunes all peers after the first connection node1.wakuRelay.parameters.dHigh = 1 diff --git a/tests/v2/test_peer_manager.nim b/tests/v2/test_peer_manager.nim index f0c6ef4cf..a8cb7227d 100644 --- a/tests/v2/test_peer_manager.nim +++ b/tests/v2/test_peer_manager.nim @@ -34,8 +34,8 @@ procSuite "Peer Manager": await allFutures([node1.start(), node2.start()]) - node1.mountRelay() - node2.mountRelay() + await node1.mountRelay() + await node2.mountRelay() # Dial node2 from node1 let conn = (await node1.peerManager.dialPeer(peerInfo2.toRemotePeerInfo(), WakuRelayCodec)).get() @@ -68,8 +68,8 @@ procSuite "Peer Manager": await node1.start() # Purposefully don't start node2 - node1.mountRelay() - node2.mountRelay() + await node1.mountRelay() + await node2.mountRelay() # Dial node2 from node1 let connOpt = await node1.peerManager.dialPeer(peerInfo2.toRemotePeerInfo(), WakuRelayCodec, 2.seconds) @@ -100,9 +100,9 @@ procSuite "Peer Manager": await node.start() - node.mountFilter() - node.mountSwap() - node.mountStore(persistMessages = true) + await node.mountFilter() + await node.mountSwap() + await node.mountStore(persistMessages = true) node.wakuFilter.setPeer(filterPeer.toRemotePeerInfo()) node.wakuSwap.setPeer(swapPeer.toRemotePeerInfo()) @@ -136,8 +136,8 @@ procSuite "Peer Manager": await node1.start() - node1.mountRelay() - node2.mountRelay() + await node1.mountRelay() + await node2.mountRelay() # Test default connectedness for new peers node1.peerManager.addPeer(peerInfo2.toRemotePeerInfo(), WakuRelayCodec) @@ -182,8 +182,8 @@ procSuite "Peer Manager": await node1.start() await node2.start() - node1.mountRelay() - node2.mountRelay() + await node1.mountRelay() + await node2.mountRelay() discard await node1.peerManager.dialPeer(peerInfo2.toRemotePeerInfo(), WakuRelayCodec, 2.seconds) check: @@ -205,7 +205,7 @@ procSuite "Peer Manager": node3.peerManager.peers().anyIt(it.peerId == peerInfo2.peerId) node3.peerManager.connectedness(peerInfo2.peerId) == NotConnected - node3.mountRelay() # This should trigger a reconnect + await node3.mountRelay() # This should trigger a reconnect check: # Reconnected to node2 after "restart" @@ -232,9 +232,9 @@ asyncTest "Peer manager support multiple protocol IDs when reconnecting to peers await node1.start() await node2.start() - node1.mountRelay() + await node1.mountRelay() node1.wakuRelay.codec = betaCodec - node2.mountRelay() + await node2.mountRelay() node2.wakuRelay.codec = betaCodec discard await node1.peerManager.dialPeer(peerInfo2.toRemotePeerInfo(), node2.wakuRelay.codec, 2.seconds) @@ -251,7 +251,7 @@ asyncTest "Peer manager support multiple protocol IDs when reconnecting to peers node3 = WakuNode.new(nodeKey3, ValidIpAddress.init("0.0.0.0"), Port(60004), peerStorage = storage) - node3.mountRelay() + await node3.mountRelay() node3.wakuRelay.codec = stableCodec check: # Node 2 and 3 have differing codecs diff --git a/tests/v2/test_rest_debug_api.nim b/tests/v2/test_rest_debug_api.nim index 3fff36531..de901f37d 100644 --- a/tests/v2/test_rest_debug_api.nim +++ b/tests/v2/test_rest_debug_api.nim @@ -28,7 +28,7 @@ suite "REST API - Debug": # Given let node = testWakuNode() await node.start() - node.mountRelay() + await node.mountRelay() let restPort = Port(8546) let restAddress = ValidIpAddress.init("0.0.0.0") diff --git a/tests/v2/test_rest_relay_api.nim b/tests/v2/test_rest_relay_api.nim index 1db8a6ebd..510054a4b 100644 --- a/tests/v2/test_rest_relay_api.nim +++ b/tests/v2/test_rest_relay_api.nim @@ -39,7 +39,7 @@ suite "REST API - Relay": # Given let node = testWakuNode() await node.start() - node.mountRelay() + await node.mountRelay() let restPort = Port(8546) let restAddress = ValidIpAddress.init("0.0.0.0") @@ -84,7 +84,7 @@ suite "REST API - Relay": # Given let node = testWakuNode() await node.start() - node.mountRelay() + await node.mountRelay() let restPort = Port(8546) let restAddress = ValidIpAddress.init("0.0.0.0") @@ -132,7 +132,7 @@ suite "REST API - Relay": # Given let node = testWakuNode() await node.start() - node.mountRelay() + await node.mountRelay() let restPort = Port(8546) let restAddress = ValidIpAddress.init("0.0.0.0") @@ -183,7 +183,7 @@ suite "REST API - Relay": # Given let node = testWakuNode() await node.start() - node.mountRelay() + await node.mountRelay() # RPC server setup let restPort = Port(8546) diff --git a/tests/v2/test_waku.nim b/tests/v2/test_waku.nim index 9583f969e..c60c1e4c7 100644 --- a/tests/v2/test_waku.nim +++ b/tests/v2/test_waku.nim @@ -85,7 +85,7 @@ procSuite "FloodSub": ) for node in nodes: - node.mountRelay() + await node.mountRelay() await subscribeNodes(nodes) diff --git a/tests/v2/test_waku_bridge.nim b/tests/v2/test_waku_bridge.nim index edf4e37d7..08637aab0 100644 --- a/tests/v2/test_waku_bridge.nim +++ b/tests/v2/test_waku_bridge.nim @@ -31,10 +31,11 @@ procSuite "WakuBridge": let rng = keys.newRng() + cryptoRng = crypto.newRng() # Bridge nodev1Key = keys.KeyPair.random(rng[]) - nodev2Key = crypto.PrivateKey.random(Secp256k1, rng[])[] + nodev2Key = crypto.PrivateKey.random(Secp256k1, cryptoRng[])[] bridge = WakuBridge.new( nodev1Key= nodev1Key, nodev1Address = localAddress(30302), @@ -48,7 +49,7 @@ procSuite "WakuBridge": v1Node = setupTestNode(rng, Waku) # Waku v2 node - v2NodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[] + v2NodeKey = crypto.PrivateKey.random(Secp256k1, cryptoRng[])[] v2Node = WakuNode.new(v2NodeKey, ValidIpAddress.init("0.0.0.0"), Port(60002)) contentTopic = ContentTopic("/waku/1/0x1a2b3c4d/rfc26") @@ -118,7 +119,7 @@ procSuite "WakuBridge": waitFor bridge.start() waitFor v2Node.start() - v2Node.mountRelay(@[DefaultBridgeTopic], triggerSelf = false) + await v2Node.mountRelay(@[DefaultBridgeTopic], triggerSelf = false) discard waitFor v1Node.rlpxConnect(newNode(bridge.nodev1.toENode())) waitFor v2Node.connectToNodes(@[bridge.nodev2.switch.peerInfo.toRemotePeerInfo()]) diff --git a/tests/v2/test_waku_discv5.nim b/tests/v2/test_waku_discv5.nim index 61ccaca2d..a05a41a41 100644 --- a/tests/v2/test_waku_discv5.nim +++ b/tests/v2/test_waku_discv5.nim @@ -84,9 +84,9 @@ procSuite "Waku Discovery v5": node3.rng ) - node1.mountRelay() - node2.mountRelay() - node3.mountRelay() + await node1.mountRelay() + await node2.mountRelay() + await node3.mountRelay() await allFutures([node1.start(), node2.start(), node3.start()]) diff --git a/tests/v2/test_waku_dnsdisc.nim b/tests/v2/test_waku_dnsdisc.nim index 595df70b7..a3d5669ca 100644 --- a/tests/v2/test_waku_dnsdisc.nim +++ b/tests/v2/test_waku_dnsdisc.nim @@ -34,9 +34,9 @@ procSuite "Waku DNS Discovery": node3 = WakuNode.new(nodeKey3, bindIp, Port(60003)) enr3 = node3.enr - node1.mountRelay() - node2.mountRelay() - node3.mountRelay() + await node1.mountRelay() + await node2.mountRelay() + await node3.mountRelay() await allFutures([node1.start(), node2.start(), node3.start()]) # Build and sign tree @@ -44,7 +44,7 @@ procSuite "Waku DNS Discovery": @[enr1, enr2, enr3], # ENR entries @[]).get() # No link entries - let treeKeys = keys.KeyPair.random(rng[]) + let treeKeys = keys.KeyPair.random(keys.newRng()[]) # Sign tree check: @@ -68,7 +68,7 @@ procSuite "Waku DNS Discovery": nodeKey4 = crypto.PrivateKey.random(Secp256k1, rng[])[] node4 = WakuNode.new(nodeKey4, bindIp, Port(60004)) - node4.mountRelay() + await node4.mountRelay() await node4.start() var wakuDnsDisc = WakuDnsDiscovery.init(location, resolver).get() diff --git a/tests/v2/test_waku_filter.nim b/tests/v2/test_waku_filter.nim index 5df24da65..d407cf7c7 100644 --- a/tests/v2/test_waku_filter.nim +++ b/tests/v2/test_waku_filter.nim @@ -45,6 +45,7 @@ procSuite "Waku Filter": let serverPeerManager = PeerManager.new(serverSwitch) serverProto = WakuFilter.init(serverPeerManager, rng, dummyHandler) + await serverProto.start() serverSwitch.mount(serverProto) # Client @@ -55,6 +56,7 @@ procSuite "Waku Filter": let clientPeerManager = PeerManager.new(clientSwitch) clientProto = WakuFilter.init(clientPeerManager, rng, handler) + await clientProto.start() clientSwitch.mount(clientProto) clientProto.setPeer(serverSwitch.peerInfo.toRemotePeerInfo()) @@ -93,6 +95,7 @@ procSuite "Waku Filter": let serverPeerManager = PeerManager.new(serverSwitch) serverProto = WakuFilter.init(serverPeerManager, rng, dummyHandler) + await serverProto.start() serverSwitch.mount(serverProto) # Client @@ -103,6 +106,7 @@ procSuite "Waku Filter": let clientPeerManager = PeerManager.new(clientSwitch) clientProto = WakuFilter.init(clientPeerManager, rng, handler) + await clientProto.start() clientSwitch.mount(clientProto) clientProto.setPeer(serverSwitch.peerInfo.toRemotePeerInfo()) @@ -144,6 +148,7 @@ procSuite "Waku Filter": ## Given let clientProto = WakuFilter.init(PeerManager.new(clientSwitch), crypto.newRng(), dummyHandler) + await clientProto.start() clientSwitch.mount(clientProto) ## When @@ -168,6 +173,7 @@ procSuite "Waku Filter": let serverPeerManager = PeerManager.new(serverSwitch) serverProto = WakuFilter.init(serverPeerManager, rng, dummyHandler, timeout=1.seconds) + await serverProto.start() serverSwitch.mount(serverProto) # Client @@ -178,6 +184,7 @@ procSuite "Waku Filter": let clientPeerManager = PeerManager.new(clientSwitch) clientProto = WakuFilter.init(clientPeerManager, rng, handler) + await clientProto.start() clientSwitch.mount(clientProto) clientProto.setPeer(serverSwitch.peerInfo.toRemotePeerInfo()) @@ -242,6 +249,7 @@ procSuite "Waku Filter": let serverPeerManager = PeerManager.new(serverSwitch) serverProto = WakuFilter.init(serverPeerManager, rng, dummyHandler, timeout=2.seconds) + await serverProto.start() serverSwitch.mount(serverProto) # Client @@ -252,6 +260,7 @@ procSuite "Waku Filter": let clientPeerManager = PeerManager.new(clientSwitch) clientProto = WakuFilter.init(clientPeerManager, rng, handler) + await clientProto.start() clientSwitch.mount(clientProto) clientProto.setPeer(serverSwitch.peerInfo.toRemotePeerInfo()) @@ -289,6 +298,7 @@ procSuite "Waku Filter": # Start switch with same key as before var clientSwitch2 = newTestSwitch(some(clientKey), some(clientAddress)) await clientSwitch2.start() + await clientProto.start() clientSwitch2.mount(clientProto) # If push succeeds after failure, the peer should removed from failed peers list diff --git a/tests/v2/test_waku_keepalive.nim b/tests/v2/test_waku_keepalive.nim index c3c3c3834..ee5b49f6f 100644 --- a/tests/v2/test_waku_keepalive.nim +++ b/tests/v2/test_waku_keepalive.nim @@ -34,12 +34,15 @@ procSuite "Waku Keepalive": completionFut.complete(true) await node1.start() - node1.mountRelay() - node1.mountLibp2pPing() + await node1.mountRelay() + await node1.mountLibp2pPing() await node2.start() - node2.mountRelay() - node2.switch.mount(Ping.new(handler = pingHandler)) + await node2.mountRelay() + + let pingProto = Ping.new(handler = pingHandler) + await pingProto.start() + node2.switch.mount(pingProto) await node1.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()]) diff --git a/tests/v2/test_waku_lightpush.nim b/tests/v2/test_waku_lightpush.nim index 1200a36cc..358fd75d9 100644 --- a/tests/v2/test_waku_lightpush.nim +++ b/tests/v2/test_waku_lightpush.nim @@ -49,6 +49,7 @@ procSuite "Waku Lightpush": proto = WakuLightPush.init(peerManager, rng, requestHandler) proto.setPeer(listenSwitch.peerInfo.toRemotePeerInfo()) + waitFor proto.start() dialSwitch.mount(proto) @@ -63,7 +64,7 @@ procSuite "Waku Lightpush": peerManager2 = PeerManager.new(listenSwitch) rng2 = crypto.newRng() proto2 = WakuLightPush.init(peerManager2, rng2, requestHandler2) - + waitFor proto2.start() listenSwitch.mount(proto2) diff --git a/tests/v2/test_waku_rln_relay.nim b/tests/v2/test_waku_rln_relay.nim index 162188fd4..f3783fc59 100644 --- a/tests/v2/test_waku_rln_relay.nim +++ b/tests/v2/test_waku_rln_relay.nim @@ -44,7 +44,7 @@ procSuite "Waku rln relay": let index = MembershipIndex(5) # -------- mount rln-relay in the off-chain mode - node.mountRelay(@[RLNRELAY_PUBSUB_TOPIC]) + await node.mountRelay(@[RLNRELAY_PUBSUB_TOPIC]) node.mountRlnRelayStatic(group = groupIDCommitments, memKeyPair = groupKeyPairs[index], memIndex = index, diff --git a/tests/v2/test_waku_rln_relay_onchain.nim b/tests/v2/test_waku_rln_relay_onchain.nim index 4b6886f77..7571e4a2f 100644 --- a/tests/v2/test_waku_rln_relay_onchain.nim +++ b/tests/v2/test_waku_rln_relay_onchain.nim @@ -346,7 +346,7 @@ procSuite "Waku-rln-relay": # test ------------------------------ # start rln-relay - node.mountRelay(@[RLNRELAY_PUBSUB_TOPIC]) + await node.mountRelay(@[RLNRELAY_PUBSUB_TOPIC]) node.mountRlnRelayStatic(group = group, memKeyPair = keypair.get(), memIndex = index, @@ -427,7 +427,7 @@ procSuite "Waku-rln-relay": # test ------------------------------ # start rln-relay - node.mountRelay(@[RLNRELAY_PUBSUB_TOPIC]) + await node.mountRelay(@[RLNRELAY_PUBSUB_TOPIC]) discard await node.mountRlnRelayDynamic(ethClientAddr = EthClient, ethAccAddr = ethacc, ethAccountPrivKeyOpt = some(ethPrivKey), @@ -480,7 +480,7 @@ procSuite "Waku-rln-relay": let (ethPrivKey, ethacc) = await createEthAccount() # start rln-relay on the first node, leave rln-relay credentials empty - node.mountRelay(@[RLNRELAY_PUBSUB_TOPIC]) + await node.mountRelay(@[RLNRELAY_PUBSUB_TOPIC]) discard await node.mountRlnRelayDynamic(ethClientAddr = EthClient, ethAccAddr = ethacc, ethAccountPrivKeyOpt = some(ethPrivKey), @@ -493,7 +493,7 @@ procSuite "Waku-rln-relay": # start rln-relay on the second node, leave rln-relay credentials empty - node2.mountRelay(@[RLNRELAY_PUBSUB_TOPIC]) + await node2.mountRelay(@[RLNRELAY_PUBSUB_TOPIC]) discard await node2.mountRlnRelayDynamic(ethClientAddr = EthClient, ethAccAddr = ethacc, ethAccountPrivKeyOpt = some(ethPrivKey), diff --git a/tests/v2/test_waku_store.nim b/tests/v2/test_waku_store.nim index b02ca8b1c..057c1a8a5 100644 --- a/tests/v2/test_waku_store.nim +++ b/tests/v2/test_waku_store.nim @@ -53,6 +53,7 @@ proc newTestWakuStore(switch: Switch): WakuStore = store = WakuMessageStore.init(database).tryGet() proto = WakuStore.init(peerManager, rng, store) + waitFor proto.start() switch.mount(proto) return proto @@ -468,6 +469,7 @@ procSuite "Waku Store - fault tolerant store": let storePeer = peer.get(listenSwitch.peerInfo.toRemotePeerInfo()) proto.setPeer(storePeer) + await proto.start() listenSwitch.mount(proto) return (listenSwitch, dialSwitch, proto) diff --git a/tests/v2/test_waku_swap.nim b/tests/v2/test_waku_swap.nim index 8fbf28049..2385c95c9 100644 --- a/tests/v2/test_waku_swap.nim +++ b/tests/v2/test_waku_swap.nim @@ -62,11 +62,11 @@ procSuite "Waku SWAP Accounting": # Start nodes and mount protocols await node1.start() - node1.mountSwap() - node1.mountStore(persistMessages = true) + await node1.mountSwap() + await node1.mountStore(persistMessages = true) await node2.start() - node2.mountSwap() - node2.mountStore(persistMessages = true) + await node2.mountSwap() + await node2.mountStore(persistMessages = true) await node2.wakuStore.handleMessage("/waku/2/default-waku/proto", message) @@ -112,11 +112,11 @@ procSuite "Waku SWAP Accounting": # Start nodes and mount protocols await node1.start() - node1.mountSwap(swapConfig) - node1.mountStore(persistMessages = true) + await node1.mountSwap(swapConfig) + await node1.mountStore(persistMessages = true) await node2.start() - node2.mountSwap(swapConfig) - node2.mountStore(persistMessages = true) + await node2.mountSwap(swapConfig) + await node2.mountStore(persistMessages = true) await node2.wakuStore.handleMessage("/waku/2/default-waku/proto", message) diff --git a/tests/v2/test_wakunode.nim b/tests/v2/test_wakunode.nim index 73e4d2cd6..321fae02e 100644 --- a/tests/v2/test_wakunode.nim +++ b/tests/v2/test_wakunode.nim @@ -34,7 +34,7 @@ const KEY_PATH = sourceDir / "resources/test_key.pem" const CERT_PATH = sourceDir / "resources/test_cert.pem" procSuite "WakuNode": - let rng = keys.newRng() + let rng = crypto.newRng() asyncTest "Message published with content filter is retrievable": let @@ -67,7 +67,7 @@ procSuite "WakuNode": await node.start() - node.mountRelay() + await node.mountRelay() # Subscribe our node to the pubSubTopic where all chat data go onto. node.subscribe(pubSubTopic, relayHandler) @@ -119,11 +119,11 @@ procSuite "WakuNode": await allFutures([node1.start(), node2.start()]) - node1.mountRelay() - node2.mountRelay() + await node1.mountRelay() + await node2.mountRelay() - node1.mountFilter() - node2.mountFilter() + await node1.mountFilter() + await node2.mountFilter() # Subscribe our node to the pubSubTopic where all chat data go onto. node1.subscribe(pubSubTopic, relayHandler) @@ -166,12 +166,12 @@ procSuite "WakuNode": otherFR = FilterRequest(contentFilters: @[ContentFilter(contentTopic: otherContentTopic)], subscribe: true) await node1.start() - node1.mountRelay() - node1.mountFilter() + await node1.mountRelay() + await node1.mountFilter() await node2.start() - node2.mountRelay() - node2.mountFilter() + await node2.mountRelay() + await node2.mountFilter() node2.wakuFilter.setPeer(node1.switch.peerInfo.toRemotePeerInfo()) var defaultComplete = newFuture[bool]() @@ -237,12 +237,11 @@ procSuite "WakuNode": filterRequest = FilterRequest(contentFilters: @[ContentFilter(contentTopic: contentTopic)], subscribe: true) await node1.start() - node1.mountRelay() - node1.mountFilter() + await node1.mountRelay() + await node1.mountFilter() await node2.start() - node2.mountRelay(relayMessages=false) # Do not start WakuRelay or subscribe to any topics - node2.mountFilter() + await node2.mountFilter() node2.wakuFilter.setPeer(node1.switch.peerInfo.toRemotePeerInfo()) check: @@ -286,9 +285,9 @@ procSuite "WakuNode": var completionFut = newFuture[bool]() await node1.start() - node1.mountStore(persistMessages = true) + await node1.mountStore(persistMessages = true) await node2.start() - node2.mountStore(persistMessages = true) + await node2.mountStore(persistMessages = true) await node2.wakuStore.handleMessage("/waku/2/default-waku/proto", message) @@ -322,9 +321,9 @@ procSuite "WakuNode": var completionFut = newFuture[bool]() await node1.start() - node1.mountFilter() + await node1.mountFilter() await node2.start() - node2.mountFilter() + await node2.mountFilter() node1.wakuFilter.setPeer(node2.switch.peerInfo.toRemotePeerInfo()) @@ -363,12 +362,12 @@ procSuite "WakuNode": storeComplFut = newFuture[bool]() await node1.start() - node1.mountStore(persistMessages = true) - node1.mountFilter() + await node1.mountStore(persistMessages = true) + await node1.mountFilter() await node2.start() - node2.mountStore(persistMessages = true) - node2.mountFilter() + await node2.mountStore(persistMessages = true) + await node2.mountFilter() node2.wakuFilter.setPeer(node1.switch.peerInfo.toRemotePeerInfo()) node1.wakuStore.setPeer(node2.switch.peerInfo.toRemotePeerInfo()) @@ -422,13 +421,13 @@ procSuite "WakuNode": message = WakuMessage(payload: payload, contentTopic: contentTopic) await node1.start() - node1.mountRelay(@[pubSubTopic]) + await node1.mountRelay(@[pubSubTopic]) await node2.start() - node2.mountRelay(@[pubSubTopic]) + await node2.mountRelay(@[pubSubTopic]) await node3.start() - node3.mountRelay(@[pubSubTopic]) + await node3.mountRelay(@[pubSubTopic]) await node1.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()]) await node3.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()]) @@ -472,13 +471,13 @@ procSuite "WakuNode": # Setup node 1 with stable codec "/vac/waku/relay/2.0.0" await node1.start() - node1.mountRelay(@[pubSubTopic]) + await node1.mountRelay(@[pubSubTopic]) node1.wakuRelay.codec = "/vac/waku/relay/2.0.0" # Setup node 2 with beta codec "/vac/waku/relay/2.0.0-beta2" await node2.start() - node2.mountRelay(@[pubSubTopic]) + await node2.mountRelay(@[pubSubTopic]) node2.wakuRelay.codec = "/vac/waku/relay/2.0.0-beta2" check: @@ -528,8 +527,8 @@ procSuite "WakuNode": node2PeerId = $(node2.switch.peerInfo.peerId) node2Dns4Addr = "/dns4/localhost/tcp/60002/p2p/" & node2PeerId - node1.mountRelay() - node2.mountRelay() + await node1.mountRelay() + await node2.mountRelay() await allFutures([node1.start(), node2.start()]) @@ -570,13 +569,13 @@ procSuite "WakuNode": # start all the nodes await node1.start() - node1.mountRelay(@[pubSubTopic]) + await node1.mountRelay(@[pubSubTopic]) await node2.start() - node2.mountRelay(@[pubSubTopic]) + await node2.mountRelay(@[pubSubTopic]) await node3.start() - node3.mountRelay(@[pubSubTopic]) + await node3.mountRelay(@[pubSubTopic]) await node1.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()]) await node3.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()]) @@ -648,7 +647,7 @@ procSuite "WakuNode": await node1.start() - node1.mountRelay() + await node1.mountRelay() check: GossipSub(node1.wakuRelay).heartbeatFut.isNil == false @@ -660,7 +659,7 @@ procSuite "WakuNode": node2 = WakuNode.new(nodeKey2, ValidIpAddress.init("0.0.0.0"), Port(60002)) - node2.mountRelay() + await node2.mountRelay() check: # Relay has not yet started as node has not yet started @@ -692,17 +691,16 @@ procSuite "WakuNode": # Light node, only lightpush await node1.start() - node1.mountRelay(relayMessages=false) # Mount WakuRelay, but do not start or subscribe to any topics - node1.mountLightPush() + await node1.mountLightPush() # Intermediate node await node2.start() - node2.mountRelay(@[pubSubTopic]) - node2.mountLightPush() + await node2.mountRelay(@[pubSubTopic]) + await node2.mountLightPush() # Receiving node await node3.start() - node3.mountRelay(@[pubSubTopic]) + await node3.mountRelay(@[pubSubTopic]) discard await node1.peerManager.dialPeer(node2.switch.peerInfo.toRemotePeerInfo(), WakuLightPushCodec) await sleepAsync(5.seconds) @@ -757,9 +755,9 @@ procSuite "WakuNode": message = WakuMessage(payload: "hello world".toBytes(), contentTopic: contentTopic) await node1.start() - node1.mountStore(persistMessages = true) + await node1.mountStore(persistMessages = true) await node2.start() - node2.mountStore(persistMessages = true) + await node2.mountStore(persistMessages = true) await node2.wakuStore.handleMessage("/waku/2/default-waku/proto", message) @@ -797,9 +795,9 @@ procSuite "WakuNode": var completionFut = newFuture[bool]() await node1.start() - node1.mountStore(persistMessages = true, store = store) + await node1.mountStore(persistMessages = true, store = store) await node2.start() - node2.mountStore(persistMessages = true) + await node2.mountStore(persistMessages = true) await node2.wakuStore.handleMessage(DefaultTopic, msg1) await node2.wakuStore.handleMessage(DefaultTopic, msg2) @@ -852,15 +850,15 @@ procSuite "WakuNode": # Node with connection limit set to 1 await node1.start() - node1.mountRelay() + await node1.mountRelay() # Remote node 1 await node2.start() - node2.mountRelay() + await node2.mountRelay() # Remote node 2 await node3.start() - node3.mountRelay() + await node3.mountRelay() discard await node1.peerManager.dialPeer(node2.switch.peerInfo.toRemotePeerInfo(), WakuRelayCodec) await sleepAsync(3.seconds) @@ -888,10 +886,10 @@ procSuite "WakuNode": message = WakuMessage(payload: payload, contentTopic: contentTopic) await node1.start() - node1.mountRelay(@[pubSubTopic]) + await node1.mountRelay(@[pubSubTopic]) await node2.start() - node2.mountRelay(@[pubSubTopic]) + await node2.mountRelay(@[pubSubTopic]) await node1.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()]) @@ -933,10 +931,10 @@ procSuite "WakuNode": message = WakuMessage(payload: payload, contentTopic: contentTopic) await node1.start() - node1.mountRelay(@[pubSubTopic]) + await node1.mountRelay(@[pubSubTopic]) await node2.start() - node2.mountRelay(@[pubSubTopic]) + await node2.mountRelay(@[pubSubTopic]) await node1.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()]) @@ -977,10 +975,10 @@ procSuite "WakuNode": message = WakuMessage(payload: payload, contentTopic: contentTopic) await node1.start() - node1.mountRelay(@[pubSubTopic]) + await node1.mountRelay(@[pubSubTopic]) await node2.start() - node2.mountRelay(@[pubSubTopic]) + await node2.mountRelay(@[pubSubTopic]) #delete websocket peer address # TODO: a better way to find the index - this is too brittle @@ -1025,10 +1023,10 @@ procSuite "WakuNode": message = WakuMessage(payload: payload, contentTopic: contentTopic) await node1.start() - node1.mountRelay(@[pubSubTopic]) + await node1.mountRelay(@[pubSubTopic]) await node2.start() - node2.mountRelay(@[pubSubTopic]) + await node2.mountRelay(@[pubSubTopic]) await node1.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()]) @@ -1078,10 +1076,10 @@ procSuite "WakuNode": message = WakuMessage(payload: payload, contentTopic: contentTopic) await node1.start() - node1.mountRelay(@[pubSubTopic]) + await node1.mountRelay(@[pubSubTopic]) await node2.start() - node2.mountRelay(@[pubSubTopic]) + await node2.mountRelay(@[pubSubTopic]) await node1.connectToNodes(@[node2.switch.peerInfo.toRemotePeerInfo()]) diff --git a/tests/v2/test_wakunode_rln_relay.nim b/tests/v2/test_wakunode_rln_relay.nim index 8c24ad220..551314881 100644 --- a/tests/v2/test_wakunode_rln_relay.nim +++ b/tests/v2/test_wakunode_rln_relay.nim @@ -47,7 +47,7 @@ procSuite "WakuNode - RLN relay": # set up three nodes # node1 - node1.mountRelay(@[rlnRelayPubSubTopic]) + await node1.mountRelay(@[rlnRelayPubSubTopic]) let (groupOpt1, memKeyPairOpt1, memIndexOpt1) = rlnRelayStaticSetUp(1) # set up rln relay inputs # mount rlnrelay in off-chain mode node1.mountRlnRelayStatic(group = groupOpt1.get(), @@ -58,7 +58,7 @@ procSuite "WakuNode - RLN relay": await node1.start() # node 2 - node2.mountRelay(@[rlnRelayPubSubTopic]) + await node2.mountRelay(@[rlnRelayPubSubTopic]) let (groupOpt2, memKeyPairOpt2, memIndexOpt2) = rlnRelayStaticSetUp(2) # set up rln relay inputs # mount rlnrelay in off-chain mode node2.mountRlnRelayStatic(group = groupOpt2.get(), @@ -69,7 +69,7 @@ procSuite "WakuNode - RLN relay": await node2.start() # node 3 - node3.mountRelay(@[rlnRelayPubSubTopic]) + await node3.mountRelay(@[rlnRelayPubSubTopic]) let (groupOpt3, memKeyPairOpt3, memIndexOpt3) = rlnRelayStaticSetUp(3) # set up rln relay inputs # mount rlnrelay in off-chain mode node3.mountRlnRelayStatic(group = groupOpt3.get(), @@ -133,7 +133,7 @@ procSuite "WakuNode - RLN relay": # set up three nodes # node1 - node1.mountRelay(@[rlnRelayPubSubTopic]) + await node1.mountRelay(@[rlnRelayPubSubTopic]) let (groupOpt1, memKeyPairOpt1, memIndexOpt1) = rlnRelayStaticSetUp(1) # set up rln relay inputs # mount rlnrelay in off-chain mode node1.mountRlnRelayStatic(group = groupOpt1.get(), @@ -144,7 +144,7 @@ procSuite "WakuNode - RLN relay": await node1.start() # node 2 - node2.mountRelay(@[rlnRelayPubSubTopic]) + await node2.mountRelay(@[rlnRelayPubSubTopic]) let (groupOpt2, memKeyPairOpt2, memIndexOpt2) = rlnRelayStaticSetUp(2) # set up rln relay inputs # mount rlnrelay in off-chain mode node2.mountRlnRelayStatic(group = groupOpt2.get(), @@ -155,7 +155,7 @@ procSuite "WakuNode - RLN relay": await node2.start() # node 3 - node3.mountRelay(@[rlnRelayPubSubTopic]) + await node3.mountRelay(@[rlnRelayPubSubTopic]) let (groupOpt3, memKeyPairOpt3, memIndexOpt3) = rlnRelayStaticSetUp(3) # set up rln relay inputs # mount rlnrelay in off-chain mode node3.mountRlnRelayStatic(group = groupOpt3.get(), @@ -237,7 +237,7 @@ procSuite "WakuNode - RLN relay": # set up three nodes # node1 - node1.mountRelay(@[rlnRelayPubSubTopic]) + await node1.mountRelay(@[rlnRelayPubSubTopic]) let (groupOpt1, memKeyPairOpt1, memIndexOpt1) = rlnRelayStaticSetUp(1) # set up rln relay inputs # mount rlnrelay in off-chain mode node1.mountRlnRelayStatic(group = groupOpt1.get(), @@ -248,7 +248,7 @@ procSuite "WakuNode - RLN relay": await node1.start() # node 2 - node2.mountRelay(@[rlnRelayPubSubTopic]) + await node2.mountRelay(@[rlnRelayPubSubTopic]) let (groupOpt2, memKeyPairOpt2, memIndexOpt2) = rlnRelayStaticSetUp(2) # set up rln relay inputs # mount rlnrelay in off-chain mode node2.mountRlnRelayStatic(group = groupOpt2.get(), @@ -259,7 +259,7 @@ procSuite "WakuNode - RLN relay": await node2.start() # node 3 - node3.mountRelay(@[rlnRelayPubSubTopic]) + await node3.mountRelay(@[rlnRelayPubSubTopic]) let (groupOpt3, memKeyPairOpt3, memIndexOpt3) = rlnRelayStaticSetUp(3) # set up rln relay inputs # mount rlnrelay in off-chain mode node3.mountRlnRelayStatic(group = groupOpt3.get(), diff --git a/vendor/news/src/news.nim b/vendor/news/src/news.nim index c5084c310..fca26917a 100644 --- a/vendor/news/src/news.nim +++ b/vendor/news/src/news.nim @@ -1,6 +1,6 @@ -import - strutils, streams, random, base64, uri, strformat, nativesockets, oids, - strtabs, std/sha1, net, httpcore +import std/[ + base64, deques, httpcore, nativesockets, net, oids, random, sha1, streams, + strformat, strtabs, strutils, uri] when not declaredInScope(newsUseChronos): # Currently chronos is second class citizen. To use this library in chronos-based @@ -62,13 +62,60 @@ when newsUseChronos: t.closeWait() else: - import httpcore, asyncdispatch, asyncnet, asynchttpserver + import std/[asyncdispatch, asynchttpserver, asyncnet] type Transport = AsyncSocket const CRLF = "\c\l" const GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" type + Opcode* = enum + ## 4 bits. Defines the interpretation of the "Payload data". + Cont = 0x0 ## denotes a continuation frame + Text = 0x1 ## denotes a text frame + Binary = 0x2 ## denotes a binary frame + # 3-7 are reserved for further non-control frames + Close = 0x8 ## denotes a connection close + Ping = 0x9 ## denotes a ping + Pong = 0xa ## denotes a pong + # B-F are reserved for further control frames + + #[ + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-------+-+-------------+-------------------------------+ + |F|R|R|R| opcode|M| Payload len | Extended payload length | + |I|S|S|S| (4) |A| (7) | (16/64) | + |N|V|V|V| |S| | (if payload len==126/127) | + | |1|2|3| |K| | | + +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + + | Extended payload length continued, if payload len == 127 | + + - - - - - - - - - - - - - - - +-------------------------------+ + | |Masking-key, if MASK set to 1 | + +-------------------------------+-------------------------------+ + | Masking-key (continued) | Payload Data | + +-------------------------------- - - - - - - - - - - - - - - - + + : Payload Data continued ... : + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + | Payload Data continued ... | + +---------------------------------------------------------------+ + ]# + Frame* = tuple + fin: bool ## Indicates that this is the final fragment in a message. + rsv1: bool ## MUST be 0 unless negotiated that defines meanings + rsv2: bool + rsv3: bool + opcode: Opcode ## Defines the interpretation of the "Payload data". + mask: bool ## Defines whether the "Payload data" is masked. + data: string ## Payload data + + Packet* = object + case kind*: Opcode + of Text, Binary: + data*: string + else: + discard + ReadyState* = enum Connecting = 0 # The connection is not yet open. Open = 1 # The connection is open and ready to communicate. @@ -82,6 +129,8 @@ type protocol*: string readyState*: ReadyState maskFrames*: bool + sendFut: Future[void] + sendQueue: Deque[tuple[text: string, opcode: Opcode, fut: Future[void]]] template `[]`(value: uint8, index: int): bool = ## get bits from uint8, uint8[2] gets 2nd bit @@ -143,13 +192,14 @@ proc close*(ws: WebSocket) = if not ws.transp.isClosed: ws.transp.close() -proc closeWait*(ws: WebSocket) {.async.} = - ## close the socket - ws.readyState = Closed - if not ws.transp.isClosed: - await ws.transp.closeWait() +when newsUseChronos: + proc closeWait*(ws: WebSocket) {.async.} = + ## close the socket + ws.readyState = Closed + if not ws.transp.isClosed: + await ws.transp.closeWait() -when not newsUseChronos: +else: proc newWebSocket*(req: Request): Future[WebSocket] {.async.} = ## Creates a new socket from a request var ws = WebSocket() @@ -243,7 +293,7 @@ proc newWebSocket*(url: string, headers: StringTableRef = nil, ws.transp.writer = newAsyncStreamWriter(tr) if uri.scheme == "wss": - let s = newTlsClientAsyncStream(ws.transp.reader, ws.transp.writer, serverName = uri.hostName) + let s = newTLSClientAsyncStream(ws.transp.reader, ws.transp.writer, serverName = uri.hostname) ws.transp.reader = s.reader ws.transp.writer = s.writer @@ -300,54 +350,6 @@ proc newWebSocket*(url: string, headers: StringTableRef = nil, return ws -type - Opcode* = enum - ## 4 bits. Defines the interpretation of the "Payload data". - Cont = 0x0 ## denotes a continuation frame - Text = 0x1 ## denotes a text frame - Binary = 0x2 ## denotes a binary frame - # 3-7 are reserved for further non-control frames - Close = 0x8 ## denotes a connection close - Ping = 0x9 ## denotes a ping - Pong = 0xa ## denotes a pong - # B-F are reserved for further control frames - - #[ - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-------+-+-------------+-------------------------------+ - |F|R|R|R| opcode|M| Payload len | Extended payload length | - |I|S|S|S| (4) |A| (7) | (16/64) | - |N|V|V|V| |S| | (if payload len==126/127) | - | |1|2|3| |K| | | - +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + - | Extended payload length continued, if payload len == 127 | - + - - - - - - - - - - - - - - - +-------------------------------+ - | |Masking-key, if MASK set to 1 | - +-------------------------------+-------------------------------+ - | Masking-key (continued) | Payload Data | - +-------------------------------- - - - - - - - - - - - - - - - + - : Payload Data continued ... : - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - | Payload Data continued ... | - +---------------------------------------------------------------+ - ]# - Frame* = tuple - fin: bool ## Indicates that this is the final fragment in a message. - rsv1: bool ## MUST be 0 unless negotiated that defines meanings - rsv2: bool - rsv3: bool - opcode: Opcode ## Defines the interpretation of the "Payload data". - mask: bool ## Defines whether the "Payload data" is masked. - data: string ## Payload data - - Packet* = object - case kind*: Opcode - of Text, Binary: - data*: string - else: - discard - proc encodeFrame*(f: Frame): string = ## Encodes a frame into a string buffer ## See https://tools.ietf.org/html/rfc6455#section-5.2 @@ -407,8 +409,7 @@ proc encodeFrame*(f: Frame): string = ret.setPosition(0) return ret.readAll() - -proc send*(ws: WebSocket, text: string, opcode = Opcode.Text): Future[void] {.async.} = +proc doSend(ws: WebSocket, text: string, opcode: Opcode): Future[void] {.async.} = try: ## write data to WebSocket var frame = encodeFrame(( @@ -439,6 +440,55 @@ proc send*(ws: WebSocket, text: string, opcode = Opcode.Text): Future[void] {.as raise newException(WebSocketError, &"Could not send packet because of [{e.name}]: {e.msg}") +proc continueSending(ws: WebSocket) = + if ws.sendQueue.len <= 0: + return + + let + task = ws.sendQueue.popFirst() + fut = task.fut + sendFut = ws.doSend(task.text, task.opcode) + ws.sendFut = sendFut + + proc doHandleSent() = + if ws.sendFut.failed: + fut.fail(ws.sendFut.error) + else: + fut.complete() + ws.sendFut = nil + ws.continueSending() + + when newsUseChronos: + proc handleSent(future: pointer) = + doHandleSent() + else: + proc handleSent() = + doHandleSent() + + ws.sendFut.addCallback(handleSent) + +proc send*(ws: WebSocket, text: string, opcode = Opcode.Text): Future[void] = + if ws.sendFut != nil: + let fut = newFuture[void]("send") + ws.sendQueue.addLast (text: text, opcode: opcode, fut: fut) + return fut + + ws.sendFut = ws.doSend(text, opcode) + + proc doHandleSent() = + ws.sendFut = nil + ws.continueSending() + + when newsUseChronos: + proc handleSent(future: pointer) = + doHandleSent() + else: + proc handleSent() = + doHandleSent() + + ws.sendFut.addCallback(handleSent) + ws.sendFut + proc send*(ws: WebSocket, packet: Packet): Future[void] = if packet.kind == Text or packet.kind == Binary: return ws.send(packet.data, packet.kind) diff --git a/vendor/nim-bearssl/.github/workflows/ci.yml b/vendor/nim-bearssl/.github/workflows/ci.yml index dc533f0f8..2e437f18d 100644 --- a/vendor/nim-bearssl/.github/workflows/ci.yml +++ b/vendor/nim-bearssl/.github/workflows/ci.yml @@ -155,12 +155,7 @@ jobs: - name: Run tests shell: bash run: | - if [[ "${{ matrix.target.os }}" == "windows" ]]; then - # https://github.com/status-im/nimbus-eth2/issues/3121 - export NIMFLAGS="-d:nimRawSetjmp" - fi nim --version nimble --version nimble install -y --depsOnly env TEST_LANG="c" nimble test - env TEST_LANG="cpp" nimble test diff --git a/vendor/nim-bearssl/.gitignore b/vendor/nim-bearssl/.gitignore index aea9e1e59..fa19c2689 100644 --- a/vendor/nim-bearssl/.gitignore +++ b/vendor/nim-bearssl/.gitignore @@ -1,2 +1,5 @@ nimcache/ *.exe +gen +nimble.develop +nimble.paths diff --git a/vendor/nim-bearssl/README.md b/vendor/nim-bearssl/README.md index 402d71f60..7823f3dfc 100644 --- a/vendor/nim-bearssl/README.md +++ b/vendor/nim-bearssl/README.md @@ -7,15 +7,56 @@ [![License: Apache](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) ![Github action](https://github.com/status-im/nim-bearssl/workflows/CI/badge.svg) -[BearSSL](https://bearssl.org/) wrapper. +Simple [BearSSL](https://bearssl.org/) wrapper for Nim, fully integrated with the Nim build system. + +Applications using `nim-bearssl` are fully stand-alone, needing no additional DLL or shared library. + +## Usage + +The library is organised into two parts: + +* `bearssl/` (except for `abi`) exposes thin wrappers around the raw ABI making the functions more convenient to use in Nim +* `bearssl/abi` exposes the raw C functions of bearssl + +For each `bearssl` header file, a corresponding Nim file exists - `bearssl_rand.h` ~ `bearssl/rand.nim`. + +```nim +# You can import the whole library +import bearssl + +# ... or simply parts thereof, which can save compilation time +import bearssl/rand +``` + +In general, the mappings follow the conventions of the original BearSSL library closely. The following conventions exist: + +* the `br_` prefix has been dropped throughout +* functions taking a `XxxContext*` use `var` and not `ptr` +* `byte` replaces `unsigned char*` - this type is predominantly used for byte buffers +* `uint` used instead of `csize_t` - these are the same type in Nim, but spelled more conveniently + * Canonical nim code will have to be careful when converting existing `int` lengths, looking out for out-of-range values + +In addition to the raw `C`-like api, convenience functions are added where applicable - these follow a similar set of conventions: + +* named after the function they simplify, but take advantage of types and overload support in Nim +* help turn pointers and bytes into Nim types ## Installation -You can install the developement version of the library through nimble with the following command +You can install the developement version of the library through nimble with the following command: + ``` nimble install bearssl ``` +`BearSSL` itself is compiled as part of your project - there is no need to install any third-party libraries. + +## Developer notes + +When updating the library, `c2nim` is used via `regenerate.sh` to update the RAW ABI files. Manual editing is then needed to make a few adjustments to the mapping, after which the files can be generated. + +When adding new convenience functions, these should be added to `bearssl/` instead of the generated files. + ## License Licensed and distributed under either of diff --git a/vendor/nim-bearssl/bearssl.nim b/vendor/nim-bearssl/bearssl.nim index 1553569da..cf49d1d0e 100644 --- a/vendor/nim-bearssl/bearssl.nim +++ b/vendor/nim-bearssl/bearssl.nim @@ -1,12 +1,32 @@ ## Nim-BearSSL -## Copyright (c) 2018 Status Research & Development GmbH +## Copyright (c) 2018-2022 Status Research & Development GmbH ## Licensed under either of ## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) ## * MIT license ([LICENSE-MIT](LICENSE-MIT)) ## at your option. ## This file may not be copied, modified, or distributed except according to ## those terms. -import bearssl/[decls, errors] -export decls, errors + +when defined(bearsslSplitAbi): + # This will become default in the future - we cannot use it now because there + # are duplicate symbols in `decls.nim` - the new ABI can already be accessed + # using the more specific imports (`import bearssl/ssl`) + import + ./bearssl/[ + aead, blockx, brssl, ec, errors, hash, hmac, kdf, pem, prf, rand, rsa, + ssl, x509], + ./bearssl/abi/[cacert, config] + + export + aead, blockx, brssl, ec, errors, hash, hmac, kdf, pem, prf, rand, rsa, + ssl, x509, + cacert, config + +else: + import + ./bearssl/[cacert, errors, decls] # Deprecated, will be removed in the future + + export cacert, errors, decls + when defined(nimHasUsed): {.used.} diff --git a/vendor/nim-bearssl/bearssl.nimble b/vendor/nim-bearssl/bearssl.nimble index c35e93e9c..39186e83b 100644 --- a/vendor/nim-bearssl/bearssl.nimble +++ b/vendor/nim-bearssl/bearssl.nimble @@ -15,7 +15,7 @@ requires "nim >= 1.2.0", proc test(env, path: string) = # Compilation language is controlled by TEST_LANG exec "nim " & getEnv("TEST_LANG", "c") & " " & getEnv("NIMFLAGS") & " " & env & - " -rf --hints:off --skipParentCfg --styleCheck:usages --styleCheck:error " & path + " -d:bearsslSplitAbi -rf --hints:off --skipParentCfg --styleCheck:usages --styleCheck:error " & path task test, "Run tests": for path in listFiles(thisDir() / "tests"): diff --git a/vendor/nim-bearssl/bearssl/abi/bearssl_aead.nim b/vendor/nim-bearssl/bearssl/abi/bearssl_aead.nim new file mode 100644 index 000000000..3b093ae70 --- /dev/null +++ b/vendor/nim-bearssl/bearssl/abi/bearssl_aead.nim @@ -0,0 +1,176 @@ +import + "."/[bearssl_block, bearssl_hash, csources] + +{.pragma: importcFunc, cdecl, gcsafe, noSideEffect, raises: [].} +{.used.} + +const + bearAeadPath = bearSrcPath & "aead/" + +{.compile: bearAeadPath & "ccm.c".} +{.compile: bearAeadPath & "eax.c".} +{.compile: bearAeadPath & "gcm.c".} + +type + AeadClass* {.importc: "br_aead_class", header: "bearssl_aead.h", bycopy.} = object + tagSize* {.importc: "tag_size".}: uint + reset* {.importc: "reset".}: proc (cc: ptr ptr AeadClass; iv: pointer; len: uint) {. + importcFunc.} + aadInject* {.importc: "aad_inject".}: proc (cc: ptr ptr AeadClass; data: pointer; + len: uint) {.importcFunc.} + flip* {.importc: "flip".}: proc (cc: ptr ptr AeadClass) {.importcFunc.} + run* {.importc: "run".}: proc (cc: ptr ptr AeadClass; encrypt: cint; data: pointer; + len: uint) {.importcFunc.} + getTag* {.importc: "get_tag".}: proc (cc: ptr ptr AeadClass; tag: pointer) {.importcFunc.} + checkTag* {.importc: "check_tag".}: proc (cc: ptr ptr AeadClass; tag: pointer): uint32 {. + importcFunc.} + getTagTrunc* {.importc: "get_tag_trunc".}: proc (cc: ptr ptr AeadClass; + tag: pointer; len: uint) {.importcFunc.} + checkTagTrunc* {.importc: "check_tag_trunc".}: proc (cc: ptr ptr AeadClass; + tag: pointer; len: uint): uint32 {.importcFunc.} + + + +type + GcmContext* {.importc: "br_gcm_context", header: "bearssl_aead.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr AeadClass + bctx* {.importc: "bctx".}: ptr ptr BlockCtrClass + gh* {.importc: "gh".}: Ghash + h* {.importc: "h".}: array[16, byte] + j01* {.importc: "j0_1".}: array[12, byte] + buf* {.importc: "buf".}: array[16, byte] + y* {.importc: "y".}: array[16, byte] + j02* {.importc: "j0_2".}: uint32 + jc* {.importc: "jc".}: uint32 + countAad* {.importc: "count_aad".}: uint64 + countCtr* {.importc: "count_ctr".}: uint64 + + + +proc gcmInit*(ctx: var GcmContext; bctx: ptr ptr BlockCtrClass; gh: Ghash) {.importcFunc, + importc: "br_gcm_init", header: "bearssl_aead.h".} + +proc gcmReset*(ctx: var GcmContext; iv: pointer; len: uint) {.importcFunc, + importc: "br_gcm_reset", header: "bearssl_aead.h".} + +proc gcmAadInject*(ctx: var GcmContext; data: pointer; len: uint) {.importcFunc, + importc: "br_gcm_aad_inject", header: "bearssl_aead.h".} + +proc gcmFlip*(ctx: var GcmContext) {.importcFunc, importc: "br_gcm_flip", + header: "bearssl_aead.h".} + +proc gcmRun*(ctx: var GcmContext; encrypt: cint; data: pointer; len: uint) {.importcFunc, + importc: "br_gcm_run", header: "bearssl_aead.h".} + +proc gcmGetTag*(ctx: var GcmContext; tag: pointer) {.importcFunc, importc: "br_gcm_get_tag", + header: "bearssl_aead.h".} + +proc gcmCheckTag*(ctx: var GcmContext; tag: pointer): uint32 {.importcFunc, + importc: "br_gcm_check_tag", header: "bearssl_aead.h".} + +proc gcmGetTagTrunc*(ctx: var GcmContext; tag: pointer; len: uint) {.importcFunc, + importc: "br_gcm_get_tag_trunc", header: "bearssl_aead.h".} + +proc gcmCheckTagTrunc*(ctx: var GcmContext; tag: pointer; len: uint): uint32 {.importcFunc, + importc: "br_gcm_check_tag_trunc", header: "bearssl_aead.h".} + +var gcmVtable* {.importc: "br_gcm_vtable", header: "bearssl_aead.h".}: AeadClass + + +type + EaxContext* {.importc: "br_eax_context", header: "bearssl_aead.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr AeadClass + bctx* {.importc: "bctx".}: ptr ptr BlockCtrcbcClass + l2* {.importc: "L2".}: array[16, byte] + l4* {.importc: "L4".}: array[16, byte] + nonce* {.importc: "nonce".}: array[16, byte] + head* {.importc: "head".}: array[16, byte] + ctr* {.importc: "ctr".}: array[16, byte] + cbcmac* {.importc: "cbcmac".}: array[16, byte] + buf* {.importc: "buf".}: array[16, byte] + `ptr`* {.importc: "ptr".}: uint + + + +type + EaxState* {.importc: "br_eax_state", header: "bearssl_aead.h", bycopy.} = object + st* {.importc: "st".}: array[3, array[16, byte]] + + + +proc eaxInit*(ctx: var EaxContext; bctx: ptr ptr BlockCtrcbcClass) {.importcFunc, + importc: "br_eax_init", header: "bearssl_aead.h".} + +proc eaxCapture*(ctx: var EaxContext; st: ptr EaxState) {.importcFunc, + importc: "br_eax_capture", header: "bearssl_aead.h".} + +proc eaxReset*(ctx: var EaxContext; nonce: pointer; len: uint) {.importcFunc, + importc: "br_eax_reset", header: "bearssl_aead.h".} + +proc eaxResetPreAad*(ctx: var EaxContext; st: ptr EaxState; nonce: pointer; len: uint) {. + importcFunc, importc: "br_eax_reset_pre_aad", header: "bearssl_aead.h".} + +proc eaxResetPostAad*(ctx: var EaxContext; st: ptr EaxState; nonce: pointer; len: uint) {. + importcFunc, importc: "br_eax_reset_post_aad", header: "bearssl_aead.h".} + +proc eaxAadInject*(ctx: var EaxContext; data: pointer; len: uint) {.importcFunc, + importc: "br_eax_aad_inject", header: "bearssl_aead.h".} + +proc eaxFlip*(ctx: var EaxContext) {.importcFunc, importc: "br_eax_flip", + header: "bearssl_aead.h".} + +proc eaxGetAadMac*(ctx: var EaxContext; st: ptr EaxState) {.inline.} = + copyMem(unsafeAddr st.st[1], unsafeAddr ctx.head, sizeof(ctx.head)) + + +proc eaxRun*(ctx: var EaxContext; encrypt: cint; data: pointer; len: uint) {.importcFunc, + importc: "br_eax_run", header: "bearssl_aead.h".} + +proc eaxGetTag*(ctx: var EaxContext; tag: pointer) {.importcFunc, importc: "br_eax_get_tag", + header: "bearssl_aead.h".} + +proc eaxCheckTag*(ctx: var EaxContext; tag: pointer): uint32 {.importcFunc, + importc: "br_eax_check_tag", header: "bearssl_aead.h".} + +proc eaxGetTagTrunc*(ctx: var EaxContext; tag: pointer; len: uint) {.importcFunc, + importc: "br_eax_get_tag_trunc", header: "bearssl_aead.h".} + +proc eaxCheckTagTrunc*(ctx: var EaxContext; tag: pointer; len: uint): uint32 {.importcFunc, + importc: "br_eax_check_tag_trunc", header: "bearssl_aead.h".} + +var eaxVtable* {.importc: "br_eax_vtable", header: "bearssl_aead.h".}: AeadClass + + +type + CcmContext* {.importc: "br_ccm_context", header: "bearssl_aead.h", bycopy.} = object + bctx* {.importc: "bctx".}: ptr ptr BlockCtrcbcClass + ctr* {.importc: "ctr".}: array[16, byte] + cbcmac* {.importc: "cbcmac".}: array[16, byte] + tagmask* {.importc: "tagmask".}: array[16, byte] + buf* {.importc: "buf".}: array[16, byte] + `ptr`* {.importc: "ptr".}: uint + tagLen* {.importc: "tag_len".}: uint + + + +proc ccmInit*(ctx: var CcmContext; bctx: ptr ptr BlockCtrcbcClass) {.importcFunc, + importc: "br_ccm_init", header: "bearssl_aead.h".} + +proc ccmReset*(ctx: var CcmContext; nonce: pointer; nonceLen: uint; aadLen: uint64; + dataLen: uint64; tagLen: uint): cint {.importcFunc, + importc: "br_ccm_reset", header: "bearssl_aead.h".} + +proc ccmAadInject*(ctx: var CcmContext; data: pointer; len: uint) {.importcFunc, + importc: "br_ccm_aad_inject", header: "bearssl_aead.h".} + +proc ccmFlip*(ctx: var CcmContext) {.importcFunc, importc: "br_ccm_flip", + header: "bearssl_aead.h".} + +proc ccmRun*(ctx: var CcmContext; encrypt: cint; data: pointer; len: uint) {.importcFunc, + importc: "br_ccm_run", header: "bearssl_aead.h".} + +proc ccmGetTag*(ctx: var CcmContext; tag: pointer): uint {.importcFunc, + importc: "br_ccm_get_tag", header: "bearssl_aead.h".} + +proc ccmCheckTag*(ctx: var CcmContext; tag: pointer): uint32 {.importcFunc, + importc: "br_ccm_check_tag", header: "bearssl_aead.h".} diff --git a/vendor/nim-bearssl/bearssl/abi/bearssl_block.nim b/vendor/nim-bearssl/bearssl/abi/bearssl_block.nim new file mode 100644 index 000000000..6eb0b57dd --- /dev/null +++ b/vendor/nim-bearssl/bearssl/abi/bearssl_block.nim @@ -0,0 +1,908 @@ +import + "."/[csources, intx] + +{.pragma: importcFunc, cdecl, gcsafe, noSideEffect, raises: [].} +{.used.} + +const + bearSymcPath = bearSrcPath & "symcipher/" + +{.compile: bearSymcPath & "aes_big_cbcdec.c".} +{.compile: bearSymcPath & "aes_big_cbcenc.c".} +{.compile: bearSymcPath & "aes_big_ctr.c".} +{.compile: bearSymcPath & "aes_big_ctrcbc.c".} +{.compile: bearSymcPath & "aes_big_dec.c".} +{.compile: bearSymcPath & "aes_big_enc.c".} +{.compile: bearSymcPath & "aes_common.c".} +{.compile: bearSymcPath & "aes_ct.c".} +{.compile: bearSymcPath & "aes_ct64.c".} +{.compile: bearSymcPath & "aes_ct64_cbcdec.c".} +{.compile: bearSymcPath & "aes_ct64_cbcenc.c".} +{.compile: bearSymcPath & "aes_ct64_ctr.c".} +{.compile: bearSymcPath & "aes_ct64_ctrcbc.c".} +{.compile: bearSymcPath & "aes_ct64_dec.c".} +{.compile: bearSymcPath & "aes_ct64_enc.c".} +{.compile: bearSymcPath & "aes_ct_cbcdec.c".} +{.compile: bearSymcPath & "aes_ct_cbcenc.c".} +{.compile: bearSymcPath & "aes_ct_ctr.c".} +{.compile: bearSymcPath & "aes_ct_ctrcbc.c".} +{.compile: bearSymcPath & "aes_ct_dec.c".} +{.compile: bearSymcPath & "aes_ct_enc.c".} +{.compile: bearSymcPath & "aes_pwr8.c".} +{.compile: bearSymcPath & "aes_pwr8_cbcdec.c".} +{.compile: bearSymcPath & "aes_pwr8_cbcenc.c".} +{.compile: bearSymcPath & "aes_pwr8_ctr.c".} +{.compile: bearSymcPath & "aes_pwr8_ctrcbc.c".} +{.compile: bearSymcPath & "aes_small_cbcdec.c".} +{.compile: bearSymcPath & "aes_small_cbcenc.c".} +{.compile: bearSymcPath & "aes_small_ctr.c".} +{.compile: bearSymcPath & "aes_small_ctrcbc.c".} +{.compile: bearSymcPath & "aes_small_dec.c".} +{.compile: bearSymcPath & "aes_small_enc.c".} +{.compile: bearSymcPath & "aes_x86ni.c".} +{.compile: bearSymcPath & "aes_x86ni_cbcdec.c".} +{.compile: bearSymcPath & "aes_x86ni_cbcenc.c".} +{.compile: bearSymcPath & "aes_x86ni_ctr.c".} +{.compile: bearSymcPath & "aes_x86ni_ctrcbc.c".} +{.compile: bearSymcPath & "chacha20_ct.c".} +{.compile: bearSymcPath & "chacha20_sse2.c".} +{.compile: bearSymcPath & "des_ct.c".} +{.compile: bearSymcPath & "des_ct_cbcdec.c".} +{.compile: bearSymcPath & "des_ct_cbcenc.c".} +{.compile: bearSymcPath & "des_support.c".} +{.compile: bearSymcPath & "des_tab.c".} +{.compile: bearSymcPath & "des_tab_cbcdec.c".} +{.compile: bearSymcPath & "des_tab_cbcenc.c".} +{.compile: bearSymcPath & "poly1305_ctmul.c".} +{.compile: bearSymcPath & "poly1305_ctmul32.c".} +{.compile: bearSymcPath & "poly1305_ctmulq.c".} +{.compile: bearSymcPath & "poly1305_i15.c".} + +type + BlockCbcencClass* {.importc: "br_block_cbcenc_class", header: "bearssl_block.h", + bycopy.} = object + contextSize* {.importc: "context_size".}: uint + blockSize* {.importc: "block_size".}: cuint + logBlockSize* {.importc: "log_block_size".}: cuint + init* {.importc: "init".}: proc (ctx: ptr ptr BlockCbcencClass; key: pointer; + keyLen: uint) {.importcFunc.} + run* {.importc: "run".}: proc (ctx: ptr ptr BlockCbcencClass; iv: pointer; + data: pointer; len: uint) {.importcFunc.} + + + +type + BlockCbcdecClass* {.importc: "br_block_cbcdec_class", header: "bearssl_block.h", + bycopy.} = object + contextSize* {.importc: "context_size".}: uint + blockSize* {.importc: "block_size".}: cuint + logBlockSize* {.importc: "log_block_size".}: cuint + init* {.importc: "init".}: proc (ctx: ptr ptr BlockCbcdecClass; key: pointer; + keyLen: uint) {.importcFunc.} + run* {.importc: "run".}: proc (ctx: ptr ptr BlockCbcdecClass; iv: pointer; + data: pointer; len: uint) {.importcFunc.} + + + +type + BlockCtrClass* {.importc: "br_block_ctr_class", header: "bearssl_block.h", bycopy.} = object + contextSize* {.importc: "context_size".}: uint + blockSize* {.importc: "block_size".}: cuint + logBlockSize* {.importc: "log_block_size".}: cuint + init* {.importc: "init".}: proc (ctx: ptr ptr BlockCtrClass; key: pointer; + keyLen: uint) {.importcFunc.} + run* {.importc: "run".}: proc (ctx: ptr ptr BlockCtrClass; iv: pointer; cc: uint32; + data: pointer; len: uint): uint32 {.importcFunc.} + + + +type + BlockCtrcbcClass* {.importc: "br_block_ctrcbc_class", header: "bearssl_block.h", + bycopy.} = object + contextSize* {.importc: "context_size".}: uint + blockSize* {.importc: "block_size".}: cuint + logBlockSize* {.importc: "log_block_size".}: cuint + init* {.importc: "init".}: proc (ctx: ptr ptr BlockCtrcbcClass; key: pointer; + keyLen: uint) {.importcFunc.} + encrypt* {.importc: "encrypt".}: proc (ctx: ptr ptr BlockCtrcbcClass; ctr: pointer; + cbcmac: pointer; data: pointer; len: uint) {. + importcFunc.} + decrypt* {.importc: "decrypt".}: proc (ctx: ptr ptr BlockCtrcbcClass; ctr: pointer; + cbcmac: pointer; data: pointer; len: uint) {. + importcFunc.} + ctr* {.importc: "ctr".}: proc (ctx: ptr ptr BlockCtrcbcClass; ctr: pointer; + data: pointer; len: uint) {.importcFunc.} + mac* {.importc: "mac".}: proc (ctx: ptr ptr BlockCtrcbcClass; cbcmac: pointer; + data: pointer; len: uint) {.importcFunc.} + + + +const + aesBigBLOCK_SIZE* = 16 + + +type + AesBigCbcencKeys* {.importc: "br_aes_big_cbcenc_keys", header: "bearssl_block.h", + bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCbcencClass + skey* {.importc: "skey".}: array[60, uint32] + numRounds* {.importc: "num_rounds".}: cuint + + + +type + AesBigCbcdecKeys* {.importc: "br_aes_big_cbcdec_keys", header: "bearssl_block.h", + bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCbcdecClass + skey* {.importc: "skey".}: array[60, uint32] + numRounds* {.importc: "num_rounds".}: cuint + + + +type + AesBigCtrKeys* {.importc: "br_aes_big_ctr_keys", header: "bearssl_block.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCtrClass + skey* {.importc: "skey".}: array[60, uint32] + numRounds* {.importc: "num_rounds".}: cuint + + + +type + AesBigCtrcbcKeys* {.importc: "br_aes_big_ctrcbc_keys", header: "bearssl_block.h", + bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCtrcbcClass + skey* {.importc: "skey".}: array[60, uint32] + numRounds* {.importc: "num_rounds".}: cuint + + +var aesBigCbcencVtable* {.importc: "br_aes_big_cbcenc_vtable", header: "bearssl_block.h".}: BlockCbcencClass + + +var aesBigCbcdecVtable* {.importc: "br_aes_big_cbcdec_vtable", header: "bearssl_block.h".}: BlockCbcdecClass + + +var aesBigCtrVtable* {.importc: "br_aes_big_ctr_vtable", header: "bearssl_block.h".}: BlockCtrClass + + +var aesBigCtrcbcVtable* {.importc: "br_aes_big_ctrcbc_vtable", header: "bearssl_block.h".}: BlockCtrcbcClass + + +proc aesBigCbcencInit*(ctx: var AesBigCbcencKeys; key: pointer; len: uint) {.importcFunc, + importc: "br_aes_big_cbcenc_init", header: "bearssl_block.h".} + +proc aesBigCbcdecInit*(ctx: var AesBigCbcdecKeys; key: pointer; len: uint) {.importcFunc, + importc: "br_aes_big_cbcdec_init", header: "bearssl_block.h".} + +proc aesBigCtrInit*(ctx: var AesBigCtrKeys; key: pointer; len: uint) {.importcFunc, + importc: "br_aes_big_ctr_init", header: "bearssl_block.h".} + +proc aesBigCtrcbcInit*(ctx: var AesBigCtrcbcKeys; key: pointer; len: uint) {.importcFunc, + importc: "br_aes_big_ctrcbc_init", header: "bearssl_block.h".} + +proc aesBigCbcencRun*(ctx: var AesBigCbcencKeys; iv: pointer; data: pointer; + len: uint) {.importcFunc, importc: "br_aes_big_cbcenc_run", + header: "bearssl_block.h".} + +proc aesBigCbcdecRun*(ctx: var AesBigCbcdecKeys; iv: pointer; data: pointer; + len: uint) {.importcFunc, importc: "br_aes_big_cbcdec_run", + header: "bearssl_block.h".} + +proc aesBigCtrRun*(ctx: var AesBigCtrKeys; iv: pointer; cc: uint32; data: pointer; + len: uint): uint32 {.importcFunc, importc: "br_aes_big_ctr_run", + header: "bearssl_block.h".} + +proc aesBigCtrcbcEncrypt*(ctx: var AesBigCtrcbcKeys; ctr: pointer; cbcmac: pointer; + data: pointer; len: uint) {.importcFunc, + importc: "br_aes_big_ctrcbc_encrypt", header: "bearssl_block.h".} + +proc aesBigCtrcbcDecrypt*(ctx: var AesBigCtrcbcKeys; ctr: pointer; cbcmac: pointer; + data: pointer; len: uint) {.importcFunc, + importc: "br_aes_big_ctrcbc_decrypt", header: "bearssl_block.h".} + +proc aesBigCtrcbcCtr*(ctx: var AesBigCtrcbcKeys; ctr: pointer; data: pointer; + len: uint) {.importcFunc, importc: "br_aes_big_ctrcbc_ctr", + header: "bearssl_block.h".} + +proc aesBigCtrcbcMac*(ctx: var AesBigCtrcbcKeys; cbcmac: pointer; data: pointer; + len: uint) {.importcFunc, importc: "br_aes_big_ctrcbc_mac", + header: "bearssl_block.h".} + +const + aesSmallBLOCK_SIZE* = 16 + + +type + AesSmallCbcencKeys* {.importc: "br_aes_small_cbcenc_keys", + header: "bearssl_block.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCbcencClass + skey* {.importc: "skey".}: array[60, uint32] + numRounds* {.importc: "num_rounds".}: cuint + + + +type + AesSmallCbcdecKeys* {.importc: "br_aes_small_cbcdec_keys", + header: "bearssl_block.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCbcdecClass + skey* {.importc: "skey".}: array[60, uint32] + numRounds* {.importc: "num_rounds".}: cuint + + + +type + AesSmallCtrKeys* {.importc: "br_aes_small_ctr_keys", header: "bearssl_block.h", + bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCtrClass + skey* {.importc: "skey".}: array[60, uint32] + numRounds* {.importc: "num_rounds".}: cuint + + + +type + AesSmallCtrcbcKeys* {.importc: "br_aes_small_ctrcbc_keys", + header: "bearssl_block.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCtrcbcClass + skey* {.importc: "skey".}: array[60, uint32] + numRounds* {.importc: "num_rounds".}: cuint + + +var aesSmallCbcencVtable* {.importc: "br_aes_small_cbcenc_vtable", header: "bearssl_block.h".}: BlockCbcencClass + + +var aesSmallCbcdecVtable* {.importc: "br_aes_small_cbcdec_vtable", header: "bearssl_block.h".}: BlockCbcdecClass + + +var aesSmallCtrVtable* {.importc: "br_aes_small_ctr_vtable", header: "bearssl_block.h".}: BlockCtrClass + + +var aesSmallCtrcbcVtable* {.importc: "br_aes_small_ctrcbc_vtable", header: "bearssl_block.h".}: BlockCtrcbcClass + + +proc aesSmallCbcencInit*(ctx: var AesSmallCbcencKeys; key: pointer; len: uint) {. + importcFunc, importc: "br_aes_small_cbcenc_init", header: "bearssl_block.h".} + +proc aesSmallCbcdecInit*(ctx: var AesSmallCbcdecKeys; key: pointer; len: uint) {. + importcFunc, importc: "br_aes_small_cbcdec_init", header: "bearssl_block.h".} + +proc aesSmallCtrInit*(ctx: var AesSmallCtrKeys; key: pointer; len: uint) {.importcFunc, + importc: "br_aes_small_ctr_init", header: "bearssl_block.h".} + +proc aesSmallCtrcbcInit*(ctx: var AesSmallCtrcbcKeys; key: pointer; len: uint) {. + importcFunc, importc: "br_aes_small_ctrcbc_init", header: "bearssl_block.h".} + +proc aesSmallCbcencRun*(ctx: var AesSmallCbcencKeys; iv: pointer; data: pointer; + len: uint) {.importcFunc, importc: "br_aes_small_cbcenc_run", + header: "bearssl_block.h".} + +proc aesSmallCbcdecRun*(ctx: var AesSmallCbcdecKeys; iv: pointer; data: pointer; + len: uint) {.importcFunc, importc: "br_aes_small_cbcdec_run", + header: "bearssl_block.h".} + +proc aesSmallCtrRun*(ctx: var AesSmallCtrKeys; iv: pointer; cc: uint32; data: pointer; + len: uint): uint32 {.importcFunc, importc: "br_aes_small_ctr_run", + header: "bearssl_block.h".} + +proc aesSmallCtrcbcEncrypt*(ctx: var AesSmallCtrcbcKeys; ctr: pointer; + cbcmac: pointer; data: pointer; len: uint) {.importcFunc, + importc: "br_aes_small_ctrcbc_encrypt", header: "bearssl_block.h".} + +proc aesSmallCtrcbcDecrypt*(ctx: var AesSmallCtrcbcKeys; ctr: pointer; + cbcmac: pointer; data: pointer; len: uint) {.importcFunc, + importc: "br_aes_small_ctrcbc_decrypt", header: "bearssl_block.h".} + +proc aesSmallCtrcbcCtr*(ctx: var AesSmallCtrcbcKeys; ctr: pointer; data: pointer; + len: uint) {.importcFunc, importc: "br_aes_small_ctrcbc_ctr", + header: "bearssl_block.h".} + +proc aesSmallCtrcbcMac*(ctx: var AesSmallCtrcbcKeys; cbcmac: pointer; data: pointer; + len: uint) {.importcFunc, importc: "br_aes_small_ctrcbc_mac", + header: "bearssl_block.h".} + +const + aesCtBLOCK_SIZE* = 16 + + +type + AesCtCbcencKeys* {.importc: "br_aes_ct_cbcenc_keys", header: "bearssl_block.h", + bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCbcencClass + skey* {.importc: "skey".}: array[60, uint32] + numRounds* {.importc: "num_rounds".}: cuint + + + +type + AesCtCbcdecKeys* {.importc: "br_aes_ct_cbcdec_keys", header: "bearssl_block.h", + bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCbcdecClass + skey* {.importc: "skey".}: array[60, uint32] + numRounds* {.importc: "num_rounds".}: cuint + + + +type + AesCtCtrKeys* {.importc: "br_aes_ct_ctr_keys", header: "bearssl_block.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCtrClass + skey* {.importc: "skey".}: array[60, uint32] + numRounds* {.importc: "num_rounds".}: cuint + + + +type + AesCtCtrcbcKeys* {.importc: "br_aes_ct_ctrcbc_keys", header: "bearssl_block.h", + bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCtrcbcClass + skey* {.importc: "skey".}: array[60, uint32] + numRounds* {.importc: "num_rounds".}: cuint + + +var aesCtCbcencVtable* {.importc: "br_aes_ct_cbcenc_vtable", header: "bearssl_block.h".}: BlockCbcencClass + + +var aesCtCbcdecVtable* {.importc: "br_aes_ct_cbcdec_vtable", header: "bearssl_block.h".}: BlockCbcdecClass + + +var aesCtCtrVtable* {.importc: "br_aes_ct_ctr_vtable", header: "bearssl_block.h".}: BlockCtrClass + + +var aesCtCtrcbcVtable* {.importc: "br_aes_ct_ctrcbc_vtable", header: "bearssl_block.h".}: BlockCtrcbcClass + + +proc aesCtCbcencInit*(ctx: var AesCtCbcencKeys; key: pointer; len: uint) {.importcFunc, + importc: "br_aes_ct_cbcenc_init", header: "bearssl_block.h".} + +proc aesCtCbcdecInit*(ctx: var AesCtCbcdecKeys; key: pointer; len: uint) {.importcFunc, + importc: "br_aes_ct_cbcdec_init", header: "bearssl_block.h".} + +proc aesCtCtrInit*(ctx: var AesCtCtrKeys; key: pointer; len: uint) {.importcFunc, + importc: "br_aes_ct_ctr_init", header: "bearssl_block.h".} + +proc aesCtCtrcbcInit*(ctx: var AesCtCtrcbcKeys; key: pointer; len: uint) {.importcFunc, + importc: "br_aes_ct_ctrcbc_init", header: "bearssl_block.h".} + +proc aesCtCbcencRun*(ctx: var AesCtCbcencKeys; iv: pointer; data: pointer; len: uint) {. + importcFunc, importc: "br_aes_ct_cbcenc_run", header: "bearssl_block.h".} + +proc aesCtCbcdecRun*(ctx: var AesCtCbcdecKeys; iv: pointer; data: pointer; len: uint) {. + importcFunc, importc: "br_aes_ct_cbcdec_run", header: "bearssl_block.h".} + +proc aesCtCtrRun*(ctx: var AesCtCtrKeys; iv: pointer; cc: uint32; data: pointer; + len: uint): uint32 {.importcFunc, importc: "br_aes_ct_ctr_run", + header: "bearssl_block.h".} + +proc aesCtCtrcbcEncrypt*(ctx: var AesCtCtrcbcKeys; ctr: pointer; cbcmac: pointer; + data: pointer; len: uint) {.importcFunc, + importc: "br_aes_ct_ctrcbc_encrypt", header: "bearssl_block.h".} + +proc aesCtCtrcbcDecrypt*(ctx: var AesCtCtrcbcKeys; ctr: pointer; cbcmac: pointer; + data: pointer; len: uint) {.importcFunc, + importc: "br_aes_ct_ctrcbc_decrypt", header: "bearssl_block.h".} + +proc aesCtCtrcbcCtr*(ctx: var AesCtCtrcbcKeys; ctr: pointer; data: pointer; len: uint) {. + importcFunc, importc: "br_aes_ct_ctrcbc_ctr", header: "bearssl_block.h".} + +proc aesCtCtrcbcMac*(ctx: var AesCtCtrcbcKeys; cbcmac: pointer; data: pointer; + len: uint) {.importcFunc, importc: "br_aes_ct_ctrcbc_mac", + header: "bearssl_block.h".} + +const + aesCt64BLOCK_SIZE* = 16 + + +type + AesCt64CbcencKeys* {.importc: "br_aes_ct64_cbcenc_keys", + header: "bearssl_block.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCbcencClass + skey* {.importc: "skey".}: array[30, uint64] + numRounds* {.importc: "num_rounds".}: cuint + + + +type + AesCt64CbcdecKeys* {.importc: "br_aes_ct64_cbcdec_keys", + header: "bearssl_block.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCbcdecClass + skey* {.importc: "skey".}: array[30, uint64] + numRounds* {.importc: "num_rounds".}: cuint + + + +type + AesCt64CtrKeys* {.importc: "br_aes_ct64_ctr_keys", header: "bearssl_block.h", + bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCtrClass + skey* {.importc: "skey".}: array[30, uint64] + numRounds* {.importc: "num_rounds".}: cuint + + + +type + AesCt64CtrcbcKeys* {.importc: "br_aes_ct64_ctrcbc_keys", + header: "bearssl_block.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCtrcbcClass + skey* {.importc: "skey".}: array[30, uint64] + numRounds* {.importc: "num_rounds".}: cuint + + +var aesCt64CbcencVtable* {.importc: "br_aes_ct64_cbcenc_vtable", header: "bearssl_block.h".}: BlockCbcencClass + + +var aesCt64CbcdecVtable* {.importc: "br_aes_ct64_cbcdec_vtable", header: "bearssl_block.h".}: BlockCbcdecClass + + +var aesCt64CtrVtable* {.importc: "br_aes_ct64_ctr_vtable", header: "bearssl_block.h".}: BlockCtrClass + + +var aesCt64CtrcbcVtable* {.importc: "br_aes_ct64_ctrcbc_vtable", header: "bearssl_block.h".}: BlockCtrcbcClass + + +proc aesCt64CbcencInit*(ctx: var AesCt64CbcencKeys; key: pointer; len: uint) {.importcFunc, + importc: "br_aes_ct64_cbcenc_init", header: "bearssl_block.h".} + +proc aesCt64CbcdecInit*(ctx: var AesCt64CbcdecKeys; key: pointer; len: uint) {.importcFunc, + importc: "br_aes_ct64_cbcdec_init", header: "bearssl_block.h".} + +proc aesCt64CtrInit*(ctx: var AesCt64CtrKeys; key: pointer; len: uint) {.importcFunc, + importc: "br_aes_ct64_ctr_init", header: "bearssl_block.h".} + +proc aesCt64CtrcbcInit*(ctx: var AesCt64CtrcbcKeys; key: pointer; len: uint) {.importcFunc, + importc: "br_aes_ct64_ctrcbc_init", header: "bearssl_block.h".} + +proc aesCt64CbcencRun*(ctx: var AesCt64CbcencKeys; iv: pointer; data: pointer; + len: uint) {.importcFunc, importc: "br_aes_ct64_cbcenc_run", + header: "bearssl_block.h".} + +proc aesCt64CbcdecRun*(ctx: var AesCt64CbcdecKeys; iv: pointer; data: pointer; + len: uint) {.importcFunc, importc: "br_aes_ct64_cbcdec_run", + header: "bearssl_block.h".} + +proc aesCt64CtrRun*(ctx: var AesCt64CtrKeys; iv: pointer; cc: uint32; data: pointer; + len: uint): uint32 {.importcFunc, importc: "br_aes_ct64_ctr_run", + header: "bearssl_block.h".} + +proc aesCt64CtrcbcEncrypt*(ctx: var AesCt64CtrcbcKeys; ctr: pointer; cbcmac: pointer; + data: pointer; len: uint) {.importcFunc, + importc: "br_aes_ct64_ctrcbc_encrypt", header: "bearssl_block.h".} + +proc aesCt64CtrcbcDecrypt*(ctx: var AesCt64CtrcbcKeys; ctr: pointer; cbcmac: pointer; + data: pointer; len: uint) {.importcFunc, + importc: "br_aes_ct64_ctrcbc_decrypt", header: "bearssl_block.h".} + +proc aesCt64CtrcbcCtr*(ctx: var AesCt64CtrcbcKeys; ctr: pointer; data: pointer; + len: uint) {.importcFunc, importc: "br_aes_ct64_ctrcbc_ctr", + header: "bearssl_block.h".} + +proc aesCt64CtrcbcMac*(ctx: var AesCt64CtrcbcKeys; cbcmac: pointer; data: pointer; + len: uint) {.importcFunc, importc: "br_aes_ct64_ctrcbc_mac", + header: "bearssl_block.h".} + +const + aesX86niBLOCK_SIZE* = 16 + + +type + INNER_C_UNION_bearssl_block_1* {.importc: "br_aes_x86ni_cbcenc_keys::no_name", + header: "bearssl_block.h", bycopy, union.} = object + skni* {.importc: "skni".}: array[16 * 15, byte] + + AesX86niCbcencKeys* {.importc: "br_aes_x86ni_cbcenc_keys", + header: "bearssl_block.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCbcencClass + skey* {.importc: "skey".}: INNER_C_UNION_bearssl_block_1 + numRounds* {.importc: "num_rounds".}: cuint + + + +type + INNER_C_UNION_bearssl_block_3* {.importc: "br_aes_x86ni_cbcdec_keys::no_name", + header: "bearssl_block.h", bycopy, union.} = object + skni* {.importc: "skni".}: array[16 * 15, byte] + + AesX86niCbcdecKeys* {.importc: "br_aes_x86ni_cbcdec_keys", + header: "bearssl_block.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCbcdecClass + skey* {.importc: "skey".}: INNER_C_UNION_bearssl_block_3 + numRounds* {.importc: "num_rounds".}: cuint + + + +type + INNER_C_UNION_bearssl_block_5* {.importc: "br_aes_x86ni_ctr_keys::no_name", + header: "bearssl_block.h", bycopy, union.} = object + skni* {.importc: "skni".}: array[16 * 15, byte] + + AesX86niCtrKeys* {.importc: "br_aes_x86ni_ctr_keys", header: "bearssl_block.h", + bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCtrClass + skey* {.importc: "skey".}: INNER_C_UNION_bearssl_block_5 + numRounds* {.importc: "num_rounds".}: cuint + + + +type + INNER_C_UNION_bearssl_block_7* {.importc: "br_aes_x86ni_ctrcbc_keys::no_name", + header: "bearssl_block.h", bycopy, union.} = object + skni* {.importc: "skni".}: array[16 * 15, byte] + + AesX86niCtrcbcKeys* {.importc: "br_aes_x86ni_ctrcbc_keys", + header: "bearssl_block.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCtrcbcClass + skey* {.importc: "skey".}: INNER_C_UNION_bearssl_block_7 + numRounds* {.importc: "num_rounds".}: cuint + + +var aesX86niCbcencVtable* {.importc: "br_aes_x86ni_cbcenc_vtable", header: "bearssl_block.h".}: BlockCbcencClass + + +var aesX86niCbcdecVtable* {.importc: "br_aes_x86ni_cbcdec_vtable", header: "bearssl_block.h".}: BlockCbcdecClass + + +var aesX86niCtrVtable* {.importc: "br_aes_x86ni_ctr_vtable", header: "bearssl_block.h".}: BlockCtrClass + + +var aesX86niCtrcbcVtable* {.importc: "br_aes_x86ni_ctrcbc_vtable", header: "bearssl_block.h".}: BlockCtrcbcClass + + +proc aesX86niCbcencInit*(ctx: var AesX86niCbcencKeys; key: pointer; len: uint) {. + importcFunc, importc: "br_aes_x86ni_cbcenc_init", header: "bearssl_block.h".} + +proc aesX86niCbcdecInit*(ctx: var AesX86niCbcdecKeys; key: pointer; len: uint) {. + importcFunc, importc: "br_aes_x86ni_cbcdec_init", header: "bearssl_block.h".} + +proc aesX86niCtrInit*(ctx: var AesX86niCtrKeys; key: pointer; len: uint) {.importcFunc, + importc: "br_aes_x86ni_ctr_init", header: "bearssl_block.h".} + +proc aesX86niCtrcbcInit*(ctx: var AesX86niCtrcbcKeys; key: pointer; len: uint) {. + importcFunc, importc: "br_aes_x86ni_ctrcbc_init", header: "bearssl_block.h".} + +proc aesX86niCbcencRun*(ctx: var AesX86niCbcencKeys; iv: pointer; data: pointer; + len: uint) {.importcFunc, importc: "br_aes_x86ni_cbcenc_run", + header: "bearssl_block.h".} + +proc aesX86niCbcdecRun*(ctx: var AesX86niCbcdecKeys; iv: pointer; data: pointer; + len: uint) {.importcFunc, importc: "br_aes_x86ni_cbcdec_run", + header: "bearssl_block.h".} + +proc aesX86niCtrRun*(ctx: var AesX86niCtrKeys; iv: pointer; cc: uint32; data: pointer; + len: uint): uint32 {.importcFunc, importc: "br_aes_x86ni_ctr_run", + header: "bearssl_block.h".} + +proc aesX86niCtrcbcEncrypt*(ctx: var AesX86niCtrcbcKeys; ctr: pointer; + cbcmac: pointer; data: pointer; len: uint) {.importcFunc, + importc: "br_aes_x86ni_ctrcbc_encrypt", header: "bearssl_block.h".} + +proc aesX86niCtrcbcDecrypt*(ctx: var AesX86niCtrcbcKeys; ctr: pointer; + cbcmac: pointer; data: pointer; len: uint) {.importcFunc, + importc: "br_aes_x86ni_ctrcbc_decrypt", header: "bearssl_block.h".} + +proc aesX86niCtrcbcCtr*(ctx: var AesX86niCtrcbcKeys; ctr: pointer; data: pointer; + len: uint) {.importcFunc, importc: "br_aes_x86ni_ctrcbc_ctr", + header: "bearssl_block.h".} + +proc aesX86niCtrcbcMac*(ctx: var AesX86niCtrcbcKeys; cbcmac: pointer; data: pointer; + len: uint) {.importcFunc, importc: "br_aes_x86ni_ctrcbc_mac", + header: "bearssl_block.h".} + +proc aesX86niCbcencGetVtable*(): ptr BlockCbcencClass {.importcFunc, + importc: "br_aes_x86ni_cbcenc_get_vtable", header: "bearssl_block.h".} + +proc aesX86niCbcdecGetVtable*(): ptr BlockCbcdecClass {.importcFunc, + importc: "br_aes_x86ni_cbcdec_get_vtable", header: "bearssl_block.h".} + +proc aesX86niCtrGetVtable*(): ptr BlockCtrClass {.importcFunc, + importc: "br_aes_x86ni_ctr_get_vtable", header: "bearssl_block.h".} + +proc aesX86niCtrcbcGetVtable*(): ptr BlockCtrcbcClass {.importcFunc, + importc: "br_aes_x86ni_ctrcbc_get_vtable", header: "bearssl_block.h".} + +const + aesPwr8BLOCK_SIZE* = 16 + + +type + INNER_C_UNION_bearssl_block_9* {.importc: "br_aes_pwr8_cbcenc_keys::no_name", + header: "bearssl_block.h", bycopy, union.} = object + skni* {.importc: "skni".}: array[16 * 15, byte] + + AesPwr8CbcencKeys* {.importc: "br_aes_pwr8_cbcenc_keys", + header: "bearssl_block.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCbcencClass + skey* {.importc: "skey".}: INNER_C_UNION_bearssl_block_9 + numRounds* {.importc: "num_rounds".}: cuint + + + +type + INNER_C_UNION_bearssl_block_11* {.importc: "br_aes_pwr8_cbcdec_keys::no_name", + header: "bearssl_block.h", bycopy, union.} = object + skni* {.importc: "skni".}: array[16 * 15, byte] + + AesPwr8CbcdecKeys* {.importc: "br_aes_pwr8_cbcdec_keys", + header: "bearssl_block.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCbcdecClass + skey* {.importc: "skey".}: INNER_C_UNION_bearssl_block_11 + numRounds* {.importc: "num_rounds".}: cuint + + + +type + INNER_C_UNION_bearssl_block_13* {.importc: "br_aes_pwr8_ctr_keys::no_name", + header: "bearssl_block.h", bycopy, union.} = object + skni* {.importc: "skni".}: array[16 * 15, byte] + + AesPwr8CtrKeys* {.importc: "br_aes_pwr8_ctr_keys", header: "bearssl_block.h", + bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCtrClass + skey* {.importc: "skey".}: INNER_C_UNION_bearssl_block_13 + numRounds* {.importc: "num_rounds".}: cuint + + + +type + INNER_C_UNION_bearssl_block_15* {.importc: "br_aes_pwr8_ctrcbc_keys::no_name", + header: "bearssl_block.h", bycopy, union.} = object + skni* {.importc: "skni".}: array[16 * 15, byte] + + AesPwr8CtrcbcKeys* {.importc: "br_aes_pwr8_ctrcbc_keys", + header: "bearssl_block.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCtrcbcClass + skey* {.importc: "skey".}: INNER_C_UNION_bearssl_block_15 + numRounds* {.importc: "num_rounds".}: cuint + + +var aesPwr8CbcencVtable* {.importc: "br_aes_pwr8_cbcenc_vtable", header: "bearssl_block.h".}: BlockCbcencClass + + +var aesPwr8CbcdecVtable* {.importc: "br_aes_pwr8_cbcdec_vtable", header: "bearssl_block.h".}: BlockCbcdecClass + + +var aesPwr8CtrVtable* {.importc: "br_aes_pwr8_ctr_vtable", header: "bearssl_block.h".}: BlockCtrClass + + +var aesPwr8CtrcbcVtable* {.importc: "br_aes_pwr8_ctrcbc_vtable", header: "bearssl_block.h".}: BlockCtrcbcClass + + +proc aesPwr8CbcencInit*(ctx: var AesPwr8CbcencKeys; key: pointer; len: uint) {.importcFunc, + importc: "br_aes_pwr8_cbcenc_init", header: "bearssl_block.h".} + +proc aesPwr8CbcdecInit*(ctx: var AesPwr8CbcdecKeys; key: pointer; len: uint) {.importcFunc, + importc: "br_aes_pwr8_cbcdec_init", header: "bearssl_block.h".} + +proc aesPwr8CtrInit*(ctx: var AesPwr8CtrKeys; key: pointer; len: uint) {.importcFunc, + importc: "br_aes_pwr8_ctr_init", header: "bearssl_block.h".} + +proc aesPwr8CtrcbcInit*(ctx: var AesPwr8CtrcbcKeys; key: pointer; len: uint) {.importcFunc, + importc: "br_aes_pwr8_ctrcbc_init", header: "bearssl_block.h".} + +proc aesPwr8CbcencRun*(ctx: var AesPwr8CbcencKeys; iv: pointer; data: pointer; + len: uint) {.importcFunc, importc: "br_aes_pwr8_cbcenc_run", + header: "bearssl_block.h".} + +proc aesPwr8CbcdecRun*(ctx: var AesPwr8CbcdecKeys; iv: pointer; data: pointer; + len: uint) {.importcFunc, importc: "br_aes_pwr8_cbcdec_run", + header: "bearssl_block.h".} + +proc aesPwr8CtrRun*(ctx: var AesPwr8CtrKeys; iv: pointer; cc: uint32; data: pointer; + len: uint): uint32 {.importcFunc, importc: "br_aes_pwr8_ctr_run", + header: "bearssl_block.h".} + +proc aesPwr8CtrcbcEncrypt*(ctx: var AesPwr8CtrcbcKeys; ctr: pointer; cbcmac: pointer; + data: pointer; len: uint) {.importcFunc, + importc: "br_aes_pwr8_ctrcbc_encrypt", header: "bearssl_block.h".} + +proc aesPwr8CtrcbcDecrypt*(ctx: var AesPwr8CtrcbcKeys; ctr: pointer; cbcmac: pointer; + data: pointer; len: uint) {.importcFunc, + importc: "br_aes_pwr8_ctrcbc_decrypt", header: "bearssl_block.h".} + +proc aesPwr8CtrcbcCtr*(ctx: var AesPwr8CtrcbcKeys; ctr: pointer; data: pointer; + len: uint) {.importcFunc, importc: "br_aes_pwr8_ctrcbc_ctr", + header: "bearssl_block.h".} + +proc aesPwr8CtrcbcMac*(ctx: var AesPwr8CtrcbcKeys; cbcmac: pointer; data: pointer; + len: uint) {.importcFunc, importc: "br_aes_pwr8_ctrcbc_mac", + header: "bearssl_block.h".} + +proc aesPwr8CbcencGetVtable*(): ptr BlockCbcencClass {.importcFunc, + importc: "br_aes_pwr8_cbcenc_get_vtable", header: "bearssl_block.h".} + +proc aesPwr8CbcdecGetVtable*(): ptr BlockCbcdecClass {.importcFunc, + importc: "br_aes_pwr8_cbcdec_get_vtable", header: "bearssl_block.h".} + +proc aesPwr8CtrGetVtable*(): ptr BlockCtrClass {.importcFunc, + importc: "br_aes_pwr8_ctr_get_vtable", header: "bearssl_block.h".} + +proc aesPwr8CtrcbcGetVtable*(): ptr BlockCtrcbcClass {.importcFunc, + importc: "br_aes_pwr8_ctrcbc_get_vtable", header: "bearssl_block.h".} + +type + AesGenCbcencKeys* {.importc: "br_aes_gen_cbcenc_keys", header: "bearssl_block.h", + bycopy, union.} = object + vtable* {.importc: "vtable".}: ptr BlockCbcencClass + cBig* {.importc: "c_big".}: AesBigCbcencKeys + cSmall* {.importc: "c_small".}: AesSmallCbcencKeys + cCt* {.importc: "c_ct".}: AesCtCbcencKeys + cCt64* {.importc: "c_ct64".}: AesCt64CbcencKeys + cX86ni* {.importc: "c_x86ni".}: AesX86niCbcencKeys + cPwr8* {.importc: "c_pwr8".}: AesPwr8CbcencKeys + + + +type + AesGenCbcdecKeys* {.importc: "br_aes_gen_cbcdec_keys", header: "bearssl_block.h", + bycopy, union.} = object + vtable* {.importc: "vtable".}: ptr BlockCbcdecClass + cBig* {.importc: "c_big".}: AesBigCbcdecKeys + cSmall* {.importc: "c_small".}: AesSmallCbcdecKeys + cCt* {.importc: "c_ct".}: AesCtCbcdecKeys + cCt64* {.importc: "c_ct64".}: AesCt64CbcdecKeys + cX86ni* {.importc: "c_x86ni".}: AesX86niCbcdecKeys + cPwr8* {.importc: "c_pwr8".}: AesPwr8CbcdecKeys + + + +type + AesGenCtrKeys* {.importc: "br_aes_gen_ctr_keys", header: "bearssl_block.h", bycopy, + union.} = object + vtable* {.importc: "vtable".}: ptr BlockCtrClass + cBig* {.importc: "c_big".}: AesBigCtrKeys + cSmall* {.importc: "c_small".}: AesSmallCtrKeys + cCt* {.importc: "c_ct".}: AesCtCtrKeys + cCt64* {.importc: "c_ct64".}: AesCt64CtrKeys + cX86ni* {.importc: "c_x86ni".}: AesX86niCtrKeys + cPwr8* {.importc: "c_pwr8".}: AesPwr8CtrKeys + + + +type + AesGenCtrcbcKeys* {.importc: "br_aes_gen_ctrcbc_keys", header: "bearssl_block.h", + bycopy, union.} = object + vtable* {.importc: "vtable".}: ptr BlockCtrcbcClass + cBig* {.importc: "c_big".}: AesBigCtrcbcKeys + cSmall* {.importc: "c_small".}: AesSmallCtrcbcKeys + cCt* {.importc: "c_ct".}: AesCtCtrcbcKeys + cCt64* {.importc: "c_ct64".}: AesCt64CtrcbcKeys + cX86ni* {.importc: "c_x86ni".}: AesX86niCtrcbcKeys + cPwr8* {.importc: "c_pwr8".}: AesPwr8CtrcbcKeys + + + +const + desTabBLOCK_SIZE* = 8 + + +type + DesTabCbcencKeys* {.importc: "br_des_tab_cbcenc_keys", header: "bearssl_block.h", + bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCbcencClass + skey* {.importc: "skey".}: array[96, uint32] + numRounds* {.importc: "num_rounds".}: cuint + + + +type + DesTabCbcdecKeys* {.importc: "br_des_tab_cbcdec_keys", header: "bearssl_block.h", + bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCbcdecClass + skey* {.importc: "skey".}: array[96, uint32] + numRounds* {.importc: "num_rounds".}: cuint + + +var desTabCbcencVtable* {.importc: "br_des_tab_cbcenc_vtable", header: "bearssl_block.h".}: BlockCbcencClass + + +var desTabCbcdecVtable* {.importc: "br_des_tab_cbcdec_vtable", header: "bearssl_block.h".}: BlockCbcdecClass + + +proc desTabCbcencInit*(ctx: var DesTabCbcencKeys; key: pointer; len: uint) {.importcFunc, + importc: "br_des_tab_cbcenc_init", header: "bearssl_block.h".} + +proc desTabCbcdecInit*(ctx: var DesTabCbcdecKeys; key: pointer; len: uint) {.importcFunc, + importc: "br_des_tab_cbcdec_init", header: "bearssl_block.h".} + +proc desTabCbcencRun*(ctx: var DesTabCbcencKeys; iv: pointer; data: pointer; + len: uint) {.importcFunc, importc: "br_des_tab_cbcenc_run", + header: "bearssl_block.h".} + +proc desTabCbcdecRun*(ctx: var DesTabCbcdecKeys; iv: pointer; data: pointer; + len: uint) {.importcFunc, importc: "br_des_tab_cbcdec_run", + header: "bearssl_block.h".} + +const + desCtBLOCK_SIZE* = 8 + + +type + DesCtCbcencKeys* {.importc: "br_des_ct_cbcenc_keys", header: "bearssl_block.h", + bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCbcencClass + skey* {.importc: "skey".}: array[96, uint32] + numRounds* {.importc: "num_rounds".}: cuint + + + +type + DesCtCbcdecKeys* {.importc: "br_des_ct_cbcdec_keys", header: "bearssl_block.h", + bycopy.} = object + vtable* {.importc: "vtable".}: ptr BlockCbcdecClass + skey* {.importc: "skey".}: array[96, uint32] + numRounds* {.importc: "num_rounds".}: cuint + + +var desCtCbcencVtable* {.importc: "br_des_ct_cbcenc_vtable", header: "bearssl_block.h".}: BlockCbcencClass + + +var desCtCbcdecVtable* {.importc: "br_des_ct_cbcdec_vtable", header: "bearssl_block.h".}: BlockCbcdecClass + + +proc desCtCbcencInit*(ctx: var DesCtCbcencKeys; key: pointer; len: uint) {.importcFunc, + importc: "br_des_ct_cbcenc_init", header: "bearssl_block.h".} + +proc desCtCbcdecInit*(ctx: var DesCtCbcdecKeys; key: pointer; len: uint) {.importcFunc, + importc: "br_des_ct_cbcdec_init", header: "bearssl_block.h".} + +proc desCtCbcencRun*(ctx: var DesCtCbcencKeys; iv: pointer; data: pointer; len: uint) {. + importcFunc, importc: "br_des_ct_cbcenc_run", header: "bearssl_block.h".} + +proc desCtCbcdecRun*(ctx: var DesCtCbcdecKeys; iv: pointer; data: pointer; len: uint) {. + importcFunc, importc: "br_des_ct_cbcdec_run", header: "bearssl_block.h".} + +type + DesGenCbcencKeys* {.importc: "br_des_gen_cbcenc_keys", header: "bearssl_block.h", + bycopy, union.} = object + vtable* {.importc: "vtable".}: ptr BlockCbcencClass + tab* {.importc: "tab".}: DesTabCbcencKeys + ct* {.importc: "ct".}: DesCtCbcencKeys + + + +type + DesGenCbcdecKeys* {.importc: "br_des_gen_cbcdec_keys", header: "bearssl_block.h", + bycopy, union.} = object + vtable* {.importc: "vtable".}: ptr BlockCbcdecClass + cTab* {.importc: "c_tab".}: DesTabCbcdecKeys + cCt* {.importc: "c_ct".}: DesCtCbcdecKeys + + + +type + Chacha20Run* {.importc: "br_chacha20_run".} = proc (key: pointer; iv: pointer; cc: uint32; data: pointer; len: uint): uint32 {. + importcFunc.} + + +proc chacha20CtRun*(key: pointer; iv: pointer; cc: uint32; data: pointer; len: uint): uint32 {. + importcFunc, importc: "br_chacha20_ct_run", header: "bearssl_block.h".} + +proc chacha20Sse2Run*(key: pointer; iv: pointer; cc: uint32; data: pointer; len: uint): uint32 {. + importcFunc, importc: "br_chacha20_sse2_run", header: "bearssl_block.h".} + +proc chacha20Sse2Get*(): Chacha20Run {.importcFunc, importc: "br_chacha20_sse2_get", + header: "bearssl_block.h".} + +type + Poly1305Run* {.importc: "br_poly1305_run".} = proc (key: pointer; iv: pointer; data: pointer; len: uint; + aad: pointer; aadLen: uint; tag: pointer; ichacha: Chacha20Run; + encrypt: cint) {.importcFunc.} + + +proc poly1305CtmulRun*(key: pointer; iv: pointer; data: pointer; len: uint; + aad: pointer; aadLen: uint; tag: pointer; + ichacha: Chacha20Run; encrypt: cint) {.importcFunc, + importc: "br_poly1305_ctmul_run", header: "bearssl_block.h".} + +proc poly1305Ctmul32Run*(key: pointer; iv: pointer; data: pointer; len: uint; + aad: pointer; aadLen: uint; tag: pointer; + ichacha: Chacha20Run; encrypt: cint) {.importcFunc, + importc: "br_poly1305_ctmul32_run", header: "bearssl_block.h".} + +proc poly1305I15Run*(key: pointer; iv: pointer; data: pointer; len: uint; + aad: pointer; aadLen: uint; tag: pointer; ichacha: Chacha20Run; + encrypt: cint) {.importcFunc, importc: "br_poly1305_i15_run", + header: "bearssl_block.h".} + +proc poly1305CtmulqRun*(key: pointer; iv: pointer; data: pointer; len: uint; + aad: pointer; aadLen: uint; tag: pointer; + ichacha: Chacha20Run; encrypt: cint) {.importcFunc, + importc: "br_poly1305_ctmulq_run", header: "bearssl_block.h".} + +proc poly1305CtmulqGet*(): Poly1305Run {.importcFunc, importc: "br_poly1305_ctmulq_get", + header: "bearssl_block.h".} diff --git a/vendor/nim-bearssl/bearssl/abi/bearssl_ec.nim b/vendor/nim-bearssl/bearssl/abi/bearssl_ec.nim new file mode 100644 index 000000000..add5aedb5 --- /dev/null +++ b/vendor/nim-bearssl/bearssl/abi/bearssl_ec.nim @@ -0,0 +1,334 @@ +import + "."/[bearssl_hash, bearssl_rand, csources, intx] + +{.pragma: importcFunc, cdecl, gcsafe, noSideEffect, raises: [].} +{.used.} + +const + bearEcPath = bearSrcPath & "ec/" + +{.compile: bearEcPath & "ecdsa_atr.c".} +{.compile: bearEcPath & "ecdsa_default_sign_asn1.c".} +{.compile: bearEcPath & "ecdsa_default_sign_raw.c".} +{.compile: bearEcPath & "ecdsa_default_vrfy_asn1.c".} +{.compile: bearEcPath & "ecdsa_default_vrfy_raw.c".} +{.compile: bearEcPath & "ecdsa_i15_bits.c".} +{.compile: bearEcPath & "ecdsa_i15_sign_asn1.c".} +{.compile: bearEcPath & "ecdsa_i15_sign_raw.c".} +{.compile: bearEcPath & "ecdsa_i15_vrfy_asn1.c".} +{.compile: bearEcPath & "ecdsa_i15_vrfy_raw.c".} +{.compile: bearEcPath & "ecdsa_i31_bits.c".} +{.compile: bearEcPath & "ecdsa_i31_sign_asn1.c".} +{.compile: bearEcPath & "ecdsa_i31_sign_raw.c".} +{.compile: bearEcPath & "ecdsa_i31_vrfy_asn1.c".} +{.compile: bearEcPath & "ecdsa_i31_vrfy_raw.c".} +{.compile: bearEcPath & "ecdsa_rta.c".} +{.compile: bearEcPath & "ec_all_m15.c".} +{.compile: bearEcPath & "ec_all_m31.c".} +{.compile: bearEcPath & "ec_c25519_i15.c".} +{.compile: bearEcPath & "ec_c25519_i31.c".} +{.compile: bearEcPath & "ec_c25519_m15.c".} +{.compile: bearEcPath & "ec_c25519_m31.c".} +{.compile: bearEcPath & "ec_c25519_m62.c".} +{.compile: bearEcPath & "ec_c25519_m64.c".} +{.compile: bearEcPath & "ec_curve25519.c".} +{.compile: bearEcPath & "ec_default.c".} +{.compile: bearEcPath & "ec_keygen.c".} +{.compile: bearEcPath & "ec_p256_m15.c".} +{.compile: bearEcPath & "ec_p256_m31.c".} +{.compile: bearEcPath & "ec_p256_m62.c".} +{.compile: bearEcPath & "ec_p256_m64.c".} +{.compile: bearEcPath & "ec_prime_i15.c".} +{.compile: bearEcPath & "ec_prime_i31.c".} +{.compile: bearEcPath & "ec_pubkey.c".} +{.compile: bearEcPath & "ec_secp256r1.c".} +{.compile: bearEcPath & "ec_secp384r1.c".} +{.compile: bearEcPath & "ec_secp521r1.c".} + + +const + EC_sect163k1* = 1 + + +const + EC_sect163r1* = 2 + + +const + EC_sect163r2* = 3 + + +const + EC_sect193r1* = 4 + + +const + EC_sect193r2* = 5 + + +const + EC_sect233k1* = 6 + + +const + EC_sect233r1* = 7 + + +const + EC_sect239k1* = 8 + + +const + EC_sect283k1* = 9 + + +const + EC_sect283r1* = 10 + + +const + EC_sect409k1* = 11 + + +const + EC_sect409r1* = 12 + + +const + EC_sect571k1* = 13 + + +const + EC_sect571r1* = 14 + + +const + EC_secp160k1* = 15 + + +const + EC_secp160r1* = 16 + + +const + EC_secp160r2* = 17 + + +const + EC_secp192k1* = 18 + + +const + EC_secp192r1* = 19 + + +const + EC_secp224k1* = 20 + + +const + EC_secp224r1* = 21 + + +const + EC_secp256k1* = 22 + + +const + EC_secp256r1* = 23 + + +const + EC_secp384r1* = 24 + + +const + EC_secp521r1* = 25 + + +const + EC_brainpoolP256r1* = 26 + + +const + EC_brainpoolP384r1* = 27 + + +const + EC_brainpoolP512r1* = 28 + + +const + EC_curve25519* = 29 + + +const + EC_curve448* = 30 + + +type + EcPublicKey* {.importc: "br_ec_public_key", header: "bearssl_ec.h", bycopy.} = object + curve* {.importc: "curve".}: cint + q* {.importc: "q".}: ptr byte + qlen* {.importc: "qlen".}: uint + + + +type + EcPrivateKey* {.importc: "br_ec_private_key", header: "bearssl_ec.h", bycopy.} = object + curve* {.importc: "curve".}: cint + x* {.importc: "x".}: ptr byte + xlen* {.importc: "xlen".}: uint + + + +type + EcImpl* {.importc: "br_ec_impl", header: "bearssl_ec.h", bycopy.} = object + supportedCurves* {.importc: "supported_curves".}: uint32 + generator* {.importc: "generator".}: proc (curve: cint; len: var uint): ptr byte {. + importcFunc.} + order* {.importc: "order".}: proc (curve: cint; len: var uint): ptr byte {.importcFunc.} + xoff* {.importc: "xoff".}: proc (curve: cint; len: var uint): uint {.importcFunc.} + mul* {.importc: "mul".}: proc (g: ptr byte; glen: uint; x: ptr byte; + xlen: uint; curve: cint): uint32 {.importcFunc.} + mulgen* {.importc: "mulgen".}: proc (r: ptr byte; x: ptr byte; xlen: uint; + curve: cint): uint {.importcFunc.} + muladd* {.importc: "muladd".}: proc (a: ptr byte; b: ptr byte; len: uint; + x: ptr byte; xlen: uint; y: ptr byte; + ylen: uint; curve: cint): uint32 {.importcFunc.} + + +var ecPrimeI31* {.importc: "br_ec_prime_i31", header: "bearssl_ec.h".}: EcImpl + + +var ecPrimeI15* {.importc: "br_ec_prime_i15", header: "bearssl_ec.h".}: EcImpl + + +var ecP256M15* {.importc: "br_ec_p256_m15", header: "bearssl_ec.h".}: EcImpl + + +var ecP256M31* {.importc: "br_ec_p256_m31", header: "bearssl_ec.h".}: EcImpl + + +var ecP256M62* {.importc: "br_ec_p256_m62", header: "bearssl_ec.h".}: EcImpl + + +proc ecP256M62Get*(): ptr EcImpl {.importcFunc, importc: "br_ec_p256_m62_get", + header: "bearssl_ec.h".} + +var ecP256M64* {.importc: "br_ec_p256_m64", header: "bearssl_ec.h".}: EcImpl + + +proc ecP256M64Get*(): ptr EcImpl {.importcFunc, importc: "br_ec_p256_m64_get", + header: "bearssl_ec.h".} + + +var ecC25519I15* {.importc: "br_ec_c25519_i15", header: "bearssl_ec.h".}: EcImpl + + +var ecC25519I31* {.importc: "br_ec_c25519_i31", header: "bearssl_ec.h".}: EcImpl + + +var ecC25519M15* {.importc: "br_ec_c25519_m15", header: "bearssl_ec.h".}: EcImpl + + +var ecC25519M31* {.importc: "br_ec_c25519_m31", header: "bearssl_ec.h".}: EcImpl + + +var ecC25519M62* {.importc: "br_ec_c25519_m62", header: "bearssl_ec.h".}: EcImpl + + +proc ecC25519M62Get*(): ptr EcImpl {.importcFunc, importc: "br_ec_c25519_m62_get", + header: "bearssl_ec.h".} + +var ecC25519M64* {.importc: "br_ec_c25519_m64", header: "bearssl_ec.h".}: EcImpl + + +proc ecC25519M64Get*(): ptr EcImpl {.importcFunc, importc: "br_ec_c25519_m64_get", + header: "bearssl_ec.h".} + + +var ecAllM15* {.importc: "br_ec_all_m15", header: "bearssl_ec.h".}: EcImpl + + +var ecAllM31* {.importc: "br_ec_all_m31", header: "bearssl_ec.h".}: EcImpl + + +proc ecGetDefault*(): ptr EcImpl {.importcFunc, importc: "br_ec_get_default", + header: "bearssl_ec.h".} + +proc ecdsaRawToAsn1*(sig: pointer; sigLen: uint): uint {.importcFunc, + importc: "br_ecdsa_raw_to_asn1", header: "bearssl_ec.h".} + +proc ecdsaAsn1ToRaw*(sig: pointer; sigLen: uint): uint {.importcFunc, + importc: "br_ecdsa_asn1_to_raw", header: "bearssl_ec.h".} + +type + EcdsaSign* {.importc: "br_ecdsa_sign".} = proc (impl: ptr EcImpl; hf: ptr HashClass; hashValue: pointer; + sk: ptr EcPrivateKey; sig: pointer): uint {.importcFunc.} + + +type + EcdsaVrfy* {.importc: "br_ecdsa_vrfy".} = proc (impl: ptr EcImpl; hash: pointer; hashLen: uint; + pk: ptr EcPublicKey; sig: pointer; sigLen: uint): uint32 {.importcFunc.} + + +proc ecdsaI31SignAsn1*(impl: ptr EcImpl; hf: ptr HashClass; hashValue: pointer; + sk: ptr EcPrivateKey; sig: pointer): uint {.importcFunc, + importc: "br_ecdsa_i31_sign_asn1", header: "bearssl_ec.h".} + +proc ecdsaI31SignRaw*(impl: ptr EcImpl; hf: ptr HashClass; hashValue: pointer; + sk: ptr EcPrivateKey; sig: pointer): uint {.importcFunc, + importc: "br_ecdsa_i31_sign_raw", header: "bearssl_ec.h".} + +proc ecdsaI31VrfyAsn1*(impl: ptr EcImpl; hash: pointer; hashLen: uint; + pk: ptr EcPublicKey; sig: pointer; sigLen: uint): uint32 {. + importcFunc, importc: "br_ecdsa_i31_vrfy_asn1", header: "bearssl_ec.h".} + +proc ecdsaI31VrfyRaw*(impl: ptr EcImpl; hash: pointer; hashLen: uint; + pk: ptr EcPublicKey; sig: pointer; sigLen: uint): uint32 {. + importcFunc, importc: "br_ecdsa_i31_vrfy_raw", header: "bearssl_ec.h".} + +proc ecdsaI15SignAsn1*(impl: ptr EcImpl; hf: ptr HashClass; hashValue: pointer; + sk: ptr EcPrivateKey; sig: pointer): uint {.importcFunc, + importc: "br_ecdsa_i15_sign_asn1", header: "bearssl_ec.h".} + +proc ecdsaI15SignRaw*(impl: ptr EcImpl; hf: ptr HashClass; hashValue: pointer; + sk: ptr EcPrivateKey; sig: pointer): uint {.importcFunc, + importc: "br_ecdsa_i15_sign_raw", header: "bearssl_ec.h".} + +proc ecdsaI15VrfyAsn1*(impl: ptr EcImpl; hash: pointer; hashLen: uint; + pk: ptr EcPublicKey; sig: pointer; sigLen: uint): uint32 {. + importcFunc, importc: "br_ecdsa_i15_vrfy_asn1", header: "bearssl_ec.h".} + +proc ecdsaI15VrfyRaw*(impl: ptr EcImpl; hash: pointer; hashLen: uint; + pk: ptr EcPublicKey; sig: pointer; sigLen: uint): uint32 {. + importcFunc, importc: "br_ecdsa_i15_vrfy_raw", header: "bearssl_ec.h".} + +proc ecdsaSignAsn1GetDefault*(): EcdsaSign {.importcFunc, + importc: "br_ecdsa_sign_asn1_get_default", header: "bearssl_ec.h".} + +proc ecdsaSignRawGetDefault*(): EcdsaSign {.importcFunc, + importc: "br_ecdsa_sign_raw_get_default", header: "bearssl_ec.h".} + +proc ecdsaVrfyAsn1GetDefault*(): EcdsaVrfy {.importcFunc, + importc: "br_ecdsa_vrfy_asn1_get_default", header: "bearssl_ec.h".} + +proc ecdsaVrfyRawGetDefault*(): EcdsaVrfy {.importcFunc, + importc: "br_ecdsa_vrfy_raw_get_default", header: "bearssl_ec.h".} + +const + EC_KBUF_PRIV_MAX_SIZE* = 72 + + +const + EC_KBUF_PUB_MAX_SIZE* = 145 + + +proc ecKeygen*(rngCtx: ptr ptr PrngClass; impl: ptr EcImpl; sk: ptr EcPrivateKey; + kbuf: pointer; curve: cint): uint {.importcFunc, importc: "br_ec_keygen", + header: "bearssl_ec.h".} + +proc ecComputePub*(impl: ptr EcImpl; pk: ptr EcPublicKey; kbuf: pointer; + sk: ptr EcPrivateKey): uint {.importcFunc, + importc: "br_ec_compute_pub", header: "bearssl_ec.h".} diff --git a/vendor/nim-bearssl/bearssl/abi/bearssl_hash.nim b/vendor/nim-bearssl/bearssl/abi/bearssl_hash.nim new file mode 100644 index 000000000..ba2affbe5 --- /dev/null +++ b/vendor/nim-bearssl/bearssl/abi/bearssl_hash.nim @@ -0,0 +1,368 @@ +import + "."/[csources, inner] + +{.pragma: importcFunc, cdecl, gcsafe, noSideEffect, raises: [].} +{.used.} + +const + bearHashPath = bearSrcPath & "hash/" + +{.compile: bearHashPath & "dig_oid.c".} +{.compile: bearHashPath & "dig_size.c".} +{.compile: bearHashPath & "ghash_ctmul.c".} +{.compile: bearHashPath & "ghash_ctmul32.c".} +{.compile: bearHashPath & "ghash_ctmul64.c".} +{.compile: bearHashPath & "ghash_pclmul.c".} +{.compile: bearHashPath & "ghash_pwr8.c".} +{.compile: bearHashPath & "md5.c".} +{.compile: bearHashPath & "md5sha1.c".} +{.compile: bearHashPath & "mgf1.c".} +{.compile: bearHashPath & "multihash.c".} +{.compile: bearHashPath & "sha1.c".} +{.compile: bearHashPath & "sha2big.c".} +{.compile: bearHashPath & "sha2small.c".} + +type + HashClass* {.importc: "br_hash_class", header: "bearssl_hash.h", bycopy.} = object + contextSize* {.importc: "context_size".}: uint + desc* {.importc: "desc".}: uint32 + init* {.importc: "init".}: proc (ctx: ptr ptr HashClass) {.importcFunc.} + update* {.importc: "update".}: proc (ctx: ptr ptr HashClass; data: pointer; + len: uint) {.importcFunc.} + `out`* {.importc: "out".}: proc (ctx: ptr ptr HashClass; dst: pointer) {.importcFunc.} + state* {.importc: "state".}: proc (ctx: ptr ptr HashClass; dst: pointer): uint64 {. + importcFunc.} + setState* {.importc: "set_state".}: proc (ctx: ptr ptr HashClass; stb: pointer; + count: uint64) {.importcFunc.} + + +template hashdesc_Id*(id: untyped): untyped = + ((uint32)(id) shl hashdesc_Id_Off) + +const + HASHDESC_ID_OFF* = 0 + HASHDESC_ID_MASK* = 0xFF + +template hashdesc_Out*(size: untyped): untyped = + ((uint32)(size) shl hashdesc_Out_Off) + +const + HASHDESC_OUT_OFF* = 8 + HASHDESC_OUT_MASK* = 0x7F + +template hashdesc_State*(size: untyped): untyped = + ((uint32)(size) shl hashdesc_State_Off) + +const + HASHDESC_STATE_OFF* = 15 + HASHDESC_STATE_MASK* = 0xFF + +template hashdesc_Lblen*(ls: untyped): untyped = + ((uint32)(ls) shl hashdesc_Lblen_Off) + +const + HASHDESC_LBLEN_OFF* = 23 + HASHDESC_LBLEN_MASK* = 0x0F + HASHDESC_MD_PADDING* = (1'u32 shl 28) + HASHDESC_MD_PADDING_128* = (1'u32 shl 29) + HASHDESC_MD_PADDING_BE* = (1'u32 shl 30) + + +const + md5ID* = 1 + + +const + md5SIZE* = 16 + + +var md5Vtable* {.importc: "br_md5_vtable", header: "bearssl_hash.h".}: HashClass + + +type + Md5Context* {.importc: "br_md5_context", header: "bearssl_hash.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr HashClass + buf* {.importc: "buf".}: array[64, byte] + count* {.importc: "count".}: uint64 + val* {.importc: "val".}: array[4, uint32] + + + +proc md5Init*(ctx: var Md5Context) {.importcFunc, importc: "br_md5_init", + header: "bearssl_hash.h".} + +proc md5Update*(ctx: var Md5Context; data: pointer; len: uint) {.importcFunc, + importc: "br_md5_update", header: "bearssl_hash.h".} + +proc md5Out*(ctx: var Md5Context; `out`: pointer) {.importcFunc, importc: "br_md5_out", + header: "bearssl_hash.h".} + +proc md5State*(ctx: var Md5Context; `out`: pointer): uint64 {.importcFunc, + importc: "br_md5_state", header: "bearssl_hash.h".} + +proc md5SetState*(ctx: var Md5Context; stb: pointer; count: uint64) {.importcFunc, + importc: "br_md5_set_state", header: "bearssl_hash.h".} + +const + sha1ID* = 2 + + +const + sha1SIZE* = 20 + + +var sha1Vtable* {.importc: "br_sha1_vtable", header: "bearssl_hash.h".}: HashClass + + +type + Sha1Context* {.importc: "br_sha1_context", header: "bearssl_hash.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr HashClass + buf* {.importc: "buf".}: array[64, byte] + count* {.importc: "count".}: uint64 + val* {.importc: "val".}: array[5, uint32] + + + +proc sha1Init*(ctx: var Sha1Context) {.importcFunc, importc: "br_sha1_init", + header: "bearssl_hash.h".} + +proc sha1Update*(ctx: var Sha1Context; data: pointer; len: uint) {.importcFunc, + importc: "br_sha1_update", header: "bearssl_hash.h".} + +proc sha1Out*(ctx: var Sha1Context; `out`: pointer) {.importcFunc, importc: "br_sha1_out", + header: "bearssl_hash.h".} + +proc sha1State*(ctx: var Sha1Context; `out`: pointer): uint64 {.importcFunc, + importc: "br_sha1_state", header: "bearssl_hash.h".} + +proc sha1SetState*(ctx: var Sha1Context; stb: pointer; count: uint64) {.importcFunc, + importc: "br_sha1_set_state", header: "bearssl_hash.h".} + +const + sha224ID* = 3 + + +const + sha224SIZE* = 28 + + +var sha224Vtable* {.importc: "br_sha224_vtable", header: "bearssl_hash.h".}: HashClass + + +type + Sha224Context* {.importc: "br_sha224_context", header: "bearssl_hash.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr HashClass + buf* {.importc: "buf".}: array[64, byte] + count* {.importc: "count".}: uint64 + val* {.importc: "val".}: array[8, uint32] + + + +proc sha224Init*(ctx: var Sha224Context) {.importcFunc, importc: "br_sha224_init", + header: "bearssl_hash.h".} + +proc sha224Update*(ctx: var Sha224Context; data: pointer; len: uint) {.importcFunc, + importc: "br_sha224_update", header: "bearssl_hash.h".} + +proc sha224Out*(ctx: var Sha224Context; `out`: pointer) {.importcFunc, + importc: "br_sha224_out", header: "bearssl_hash.h".} + +proc sha224State*(ctx: var Sha224Context; `out`: pointer): uint64 {.importcFunc, + importc: "br_sha224_state", header: "bearssl_hash.h".} + +proc sha224SetState*(ctx: var Sha224Context; stb: pointer; count: uint64) {.importcFunc, + importc: "br_sha224_set_state", header: "bearssl_hash.h".} + +const + sha256ID* = 4 + + +const + sha256SIZE* = 32 + + +var sha256Vtable* {.importc: "br_sha256_vtable", header: "bearssl_hash.h".}: HashClass + +type + Sha256Context* = Sha224Context + + +proc sha256Init*(ctx: var Sha256Context) {.importcFunc, importc: "br_sha256_init", + header: "bearssl_hash.h".} + +template sha256Update*(ctx: var Sha256Context; data: pointer; len: int) = + sha224Update(ctx, data, len) + +proc sha256Out*(ctx: var Sha256Context; `out`: pointer) {.importcFunc, + importc: "br_sha256_out", header: "bearssl_hash.h".} + +template sha256State*(ctx: var Sha256Context; `out`: pointer): uint64 = + sha224State(ctx, `out`) + +template sha256SetState*(ctx: var Sha256Context; stb: pointer; count: uint64) = + sha224SetState(ctx, stb, count) + +const + sha384ID* = 5 + + +const + sha384SIZE* = 48 + + +var sha384Vtable* {.importc: "br_sha384_vtable", header: "bearssl_hash.h".}: HashClass + + +type + Sha384Context* {.importc: "br_sha384_context", header: "bearssl_hash.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr HashClass + buf* {.importc: "buf".}: array[128, byte] + count* {.importc: "count".}: uint64 + val* {.importc: "val".}: array[8, uint64] + + + +proc sha384Init*(ctx: var Sha384Context) {.importcFunc, importc: "br_sha384_init", + header: "bearssl_hash.h".} + +proc sha384Update*(ctx: var Sha384Context; data: pointer; len: uint) {.importcFunc, + importc: "br_sha384_update", header: "bearssl_hash.h".} + +proc sha384Out*(ctx: var Sha384Context; `out`: pointer) {.importcFunc, + importc: "br_sha384_out", header: "bearssl_hash.h".} + +proc sha384State*(ctx: var Sha384Context; `out`: pointer): uint64 {.importcFunc, + importc: "br_sha384_state", header: "bearssl_hash.h".} + +proc sha384SetState*(ctx: var Sha384Context; stb: pointer; count: uint64) {.importcFunc, + importc: "br_sha384_set_state", header: "bearssl_hash.h".} + +const + sha512ID* = 6 + + +const + sha512SIZE* = 64 + + +var sha512Vtable* {.importc: "br_sha512_vtable", header: "bearssl_hash.h".}: HashClass + +type + Sha512Context* = Sha384Context + + +proc sha512Init*(ctx: var Sha512Context) {.importcFunc, importc: "br_sha512_init", + header: "bearssl_hash.h".} +const + sha512Update* = sha384Update + + +proc sha512Out*(ctx: var Sha512Context; `out`: pointer) {.importcFunc, + importc: "br_sha512_out", header: "bearssl_hash.h".} + +const + md5sha1ID* = 0 + + +const + md5sha1SIZE* = 36 + + +var md5sha1Vtable* {.importc: "br_md5sha1_vtable", header: "bearssl_hash.h".}: HashClass + + +type + Md5sha1Context* {.importc: "br_md5sha1_context", header: "bearssl_hash.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr HashClass + buf* {.importc: "buf".}: array[64, byte] + count* {.importc: "count".}: uint64 + valMd5* {.importc: "val_md5".}: array[4, uint32] + valSha1* {.importc: "val_sha1".}: array[5, uint32] + + + +proc md5sha1Init*(ctx: var Md5sha1Context) {.importcFunc, importc: "br_md5sha1_init", + header: "bearssl_hash.h".} + +proc md5sha1Update*(ctx: var Md5sha1Context; data: pointer; len: uint) {.importcFunc, + importc: "br_md5sha1_update", header: "bearssl_hash.h".} + +proc md5sha1Out*(ctx: var Md5sha1Context; `out`: pointer) {.importcFunc, + importc: "br_md5sha1_out", header: "bearssl_hash.h".} + +proc md5sha1State*(ctx: var Md5sha1Context; `out`: pointer): uint64 {.importcFunc, + importc: "br_md5sha1_state", header: "bearssl_hash.h".} + +proc md5sha1SetState*(ctx: var Md5sha1Context; stb: pointer; count: uint64) {.importcFunc, + importc: "br_md5sha1_set_state", header: "bearssl_hash.h".} + +type + HashCompatContext* {.importc: "br_hash_compat_context", header: "bearssl_hash.h", + bycopy, union.} = object + vtable* {.importc: "vtable".}: ptr HashClass + md5* {.importc: "md5".}: Md5Context + sha1* {.importc: "sha1".}: Sha1Context + sha224* {.importc: "sha224".}: Sha224Context + sha256* {.importc: "sha256".}: Sha256Context + sha384* {.importc: "sha384".}: Sha384Context + sha512* {.importc: "sha512".}: Sha512Context + md5sha1* {.importc: "md5sha1".}: Md5sha1Context + + + +type + MultihashContext* {.importc: "br_multihash_context", header: "bearssl_hash.h", + bycopy.} = object + buf* {.importc: "buf".}: array[128, byte] + count* {.importc: "count".}: uint64 + val32* {.importc: "val_32".}: array[25, uint32] + val64* {.importc: "val_64".}: array[16, uint64] + impl* {.importc: "impl".}: array[6, ptr HashClass] + + + +proc multihashZero*(ctx: var MultihashContext) {.importcFunc, importc: "br_multihash_zero", + header: "bearssl_hash.h".} + +proc multihashSetimpl*(ctx: var MultihashContext; id: cint; impl: ptr HashClass) {. + inline.} = + ctx.impl[id - 1] = impl + + +proc multihashGetimpl*(ctx: var MultihashContext; id: cint): ptr HashClass {.inline.} = + return ctx.impl[id - 1] + + +proc multihashInit*(ctx: var MultihashContext) {.importcFunc, importc: "br_multihash_init", + header: "bearssl_hash.h".} + +proc multihashUpdate*(ctx: var MultihashContext; data: pointer; len: uint) {.importcFunc, + importc: "br_multihash_update", header: "bearssl_hash.h".} + +proc multihashOut*(ctx: var MultihashContext; id: cint; dst: pointer): uint {.importcFunc, + importc: "br_multihash_out", header: "bearssl_hash.h".} + +type + Ghash* {.importc: "br_ghash".} = proc (y: pointer; h: pointer; data: pointer; len: uint) {.importcFunc.} + + +proc ghashCtmul*(y: pointer; h: pointer; data: pointer; len: uint) {.importcFunc, + importc: "br_ghash_ctmul", header: "bearssl_hash.h".} + +proc ghashCtmul32*(y: pointer; h: pointer; data: pointer; len: uint) {.importcFunc, + importc: "br_ghash_ctmul32", header: "bearssl_hash.h".} + +proc ghashCtmul64*(y: pointer; h: pointer; data: pointer; len: uint) {.importcFunc, + importc: "br_ghash_ctmul64", header: "bearssl_hash.h".} + +proc ghashPclmul*(y: pointer; h: pointer; data: pointer; len: uint) {.importcFunc, + importc: "br_ghash_pclmul", header: "bearssl_hash.h".} + +proc ghashPclmulGet*(): Ghash {.importcFunc, importc: "br_ghash_pclmul_get", + header: "bearssl_hash.h".} + +proc ghashPwr8*(y: pointer; h: pointer; data: pointer; len: uint) {.importcFunc, + importc: "br_ghash_pwr8", header: "bearssl_hash.h".} + +proc ghashPwr8Get*(): Ghash {.importcFunc, importc: "br_ghash_pwr8_get", + header: "bearssl_hash.h".} diff --git a/vendor/nim-bearssl/bearssl/abi/bearssl_hmac.nim b/vendor/nim-bearssl/bearssl/abi/bearssl_hmac.nim new file mode 100644 index 000000000..d820836a7 --- /dev/null +++ b/vendor/nim-bearssl/bearssl/abi/bearssl_hmac.nim @@ -0,0 +1,56 @@ +import + "."/[bearssl_hash, csources, inner] + +{.pragma: importcFunc, cdecl, gcsafe, noSideEffect, raises: [].} +{.used.} + +const + bearMacPath = bearSrcPath & "mac/" + +{.compile: bearMacPath & "hmac.c".} +{.compile: bearMacPath & "hmac_ct.c".} + +type + HmacKeyContext* {.importc: "br_hmac_key_context", header: "bearssl_hmac.h", bycopy.} = object + digVtable* {.importc: "dig_vtable".}: ptr HashClass + ksi* {.importc: "ksi".}: array[64, byte] + kso* {.importc: "kso".}: array[64, byte] + + + +proc hmacKeyInit*(kc: var HmacKeyContext; digestVtable: ptr HashClass; key: pointer; + keyLen: uint) {.importcFunc, importc: "br_hmac_key_init", + header: "bearssl_hmac.h".} + +proc hmacKeyGetDigest*(kc: var HmacKeyContext): ptr HashClass {.inline.} = + return kc.digVtable + + +type + HmacContext* {.importc: "br_hmac_context", header: "bearssl_hmac.h", bycopy.} = object + dig* {.importc: "dig".}: HashCompatContext + kso* {.importc: "kso".}: array[64, byte] + outLen* {.importc: "out_len".}: uint + + + +proc hmacInit*(ctx: var HmacContext; kc: var HmacKeyContext; outLen: uint) {.importcFunc, + importc: "br_hmac_init", header: "bearssl_hmac.h".} + +proc hmacSize*(ctx: var HmacContext): uint {.inline, importcFunc, importc: "br_hmac_size".} = + return ctx.outLen + + +proc hmacGetDigest*(hc: var HmacContext): ptr HashClass {.inline.} = + return hc.dig.vtable + + +proc hmacUpdate*(ctx: var HmacContext; data: pointer; len: uint) {.importcFunc, + importc: "br_hmac_update", header: "bearssl_hmac.h".} + +proc hmacOut*(ctx: var HmacContext; `out`: pointer): uint {.importcFunc, + importc: "br_hmac_out", header: "bearssl_hmac.h".} + +proc hmacOutCT*(ctx: var HmacContext; data: pointer; len: uint; minLen: uint; + maxLen: uint; `out`: pointer): uint {.importcFunc, + importc: "br_hmac_outCT", header: "bearssl_hmac.h".} diff --git a/vendor/nim-bearssl/bearssl/abi/bearssl_kdf.nim b/vendor/nim-bearssl/bearssl/abi/bearssl_kdf.nim new file mode 100644 index 000000000..b38143ec4 --- /dev/null +++ b/vendor/nim-bearssl/bearssl/abi/bearssl_kdf.nim @@ -0,0 +1,65 @@ +import + "."/[bearssl_hash, bearssl_hmac, csources] + +{.pragma: importcFunc, cdecl, gcsafe, noSideEffect, raises: [].} +{.used.} + +const + bearKdfPath = bearSrcPath & "kdf/" + +{.compile: bearKdfPath & "hkdf.c".} +{.compile: bearKdfPath & "shake.c".} + +type + INNER_C_UNION_bearssl_kdf_1* {.importc: "br_hkdf_context::no_name", + header: "bearssl_kdf.h", bycopy, union.} = object + hmacCtx* {.importc: "hmac_ctx".}: HmacContext + prkCtx* {.importc: "prk_ctx".}: HmacKeyContext + + HkdfContext* {.importc: "br_hkdf_context", header: "bearssl_kdf.h", bycopy.} = object + u* {.importc: "u".}: INNER_C_UNION_bearssl_kdf_1 + buf* {.importc: "buf".}: array[64, byte] + `ptr`* {.importc: "ptr".}: uint + digLen* {.importc: "dig_len".}: uint + chunkNum* {.importc: "chunk_num".}: cuint + + + +proc hkdfInit*(hc: var HkdfContext; digestVtable: ptr HashClass; salt: pointer; + saltLen: uint) {.importcFunc, importc: "br_hkdf_init", + header: "bearssl_kdf.h".} + + +var hkdfNoSalt* {.importc: "br_hkdf_no_salt", header: "bearssl_kdf.h".}: byte + + +proc hkdfInject*(hc: var HkdfContext; ikm: pointer; ikmLen: uint) {.importcFunc, + importc: "br_hkdf_inject", header: "bearssl_kdf.h".} + +proc hkdfFlip*(hc: var HkdfContext) {.importcFunc, importc: "br_hkdf_flip", + header: "bearssl_kdf.h".} + +proc hkdfProduce*(hc: var HkdfContext; info: pointer; infoLen: uint; `out`: pointer; + outLen: uint): uint {.importcFunc, importc: "br_hkdf_produce", + header: "bearssl_kdf.h".} + +type + ShakeContext* {.importc: "br_shake_context", header: "bearssl_kdf.h", bycopy.} = object + dbuf* {.importc: "dbuf".}: array[200, byte] + dptr* {.importc: "dptr".}: uint + rate* {.importc: "rate".}: uint + a* {.importc: "A".}: array[25, uint64] + + + +proc shakeInit*(sc: var ShakeContext; securityLevel: cint) {.importcFunc, + importc: "br_shake_init", header: "bearssl_kdf.h".} + +proc shakeInject*(sc: var ShakeContext; data: pointer; len: uint) {.importcFunc, + importc: "br_shake_inject", header: "bearssl_kdf.h".} + +proc shakeFlip*(hc: var ShakeContext) {.importcFunc, importc: "br_shake_flip", + header: "bearssl_kdf.h".} + +proc shakeProduce*(sc: var ShakeContext; `out`: pointer; len: uint) {.importcFunc, + importc: "br_shake_produce", header: "bearssl_kdf.h".} diff --git a/vendor/nim-bearssl/bearssl/abi/bearssl_pem.nim b/vendor/nim-bearssl/bearssl/abi/bearssl_pem.nim new file mode 100644 index 000000000..6f3f82989 --- /dev/null +++ b/vendor/nim-bearssl/bearssl/abi/bearssl_pem.nim @@ -0,0 +1,76 @@ +import + "."/[csources] + +{.pragma: importcFunc, cdecl, gcsafe, noSideEffect, raises: [].} +{.used.} + +const + bearCodecPath = bearSrcPath & "codec/" + +{.compile: bearCodecPath & "pemdec.c".} +{.compile: bearCodecPath & "pemenc.c".} + +type + INNER_C_STRUCT_bearssl_pem_1* {.importc: "br_pem_decoder_context::no_name", + header: "bearssl_pem.h", bycopy.} = object + dp* {.importc: "dp".}: ptr uint32 + rp* {.importc: "rp".}: ptr uint32 + ip* {.importc: "ip".}: ptr byte + + PemDecoderContext* {.importc: "br_pem_decoder_context", header: "bearssl_pem.h", + bycopy.} = object + cpu* {.importc: "cpu".}: INNER_C_STRUCT_bearssl_pem_1 + dpStack* {.importc: "dp_stack".}: array[32, uint32] + rpStack* {.importc: "rp_stack".}: array[32, uint32] + err* {.importc: "err".}: cint + hbuf* {.importc: "hbuf".}: ptr byte + hlen* {.importc: "hlen".}: uint + dest* {.importc: "dest".}: proc (destCtx: pointer; src: pointer; len: uint) {.importcFunc.} + destCtx* {.importc: "dest_ctx".}: pointer + event* {.importc: "event".}: byte + name* {.importc: "name".}: array[128, char] + buf* {.importc: "buf".}: array[255, byte] + `ptr`* {.importc: "ptr".}: uint + + + +proc pemDecoderInit*(ctx: var PemDecoderContext) {.importcFunc, + importc: "br_pem_decoder_init", header: "bearssl_pem.h".} + +proc pemDecoderPush*(ctx: var PemDecoderContext; data: pointer; len: uint): uint {. + importcFunc, importc: "br_pem_decoder_push", header: "bearssl_pem.h".} + +proc pemDecoderSetdest*(ctx: var PemDecoderContext; dest: proc (destCtx: pointer; + src: pointer; len: uint) {.importcFunc.}; destCtx: pointer) {.inline.} = + ctx.dest = dest + ctx.destCtx = destCtx + + +proc pemDecoderEvent*(ctx: var PemDecoderContext): cint {.importcFunc, + importc: "br_pem_decoder_event", header: "bearssl_pem.h".} + +const + PEM_BEGIN_OBJ* = 1 + + +const + PEM_END_OBJ* = 2 + + +const + PEM_ERROR* = 3 + + +proc pemDecoderName*(ctx: var PemDecoderContext): cstring {.inline.} = + return addr ctx.name + + +proc pemEncode*(dest: pointer; data: pointer; len: uint; banner: cstring; flags: cuint): uint {. + importcFunc, importc: "br_pem_encode", header: "bearssl_pem.h".} + +const + PEM_LINE64* = 0x0001 + + +const + PEM_CRLF* = 0x0002 diff --git a/vendor/nim-bearssl/bearssl/abi/bearssl_prf.nim b/vendor/nim-bearssl/bearssl/abi/bearssl_prf.nim new file mode 100644 index 000000000..362fffe26 --- /dev/null +++ b/vendor/nim-bearssl/bearssl/abi/bearssl_prf.nim @@ -0,0 +1,37 @@ +import + "."/[csources] + +{.pragma: importcFunc, cdecl, gcsafe, noSideEffect, raises: [].} +{.used.} + +const + bearSslPath = bearSrcPath & "ssl/" + +{.compile: bearSslPath & "prf.c".} +{.compile: bearSslPath & "prf_md5sha1.c".} +{.compile: bearSslPath & "prf_sha256.c".} +{.compile: bearSslPath & "prf_sha384.c".} + +type + TlsPrfSeedChunk* {.importc: "br_tls_prf_seed_chunk", header: "bearssl_prf.h", + bycopy.} = object + data* {.importc: "data".}: pointer + len* {.importc: "len".}: uint + + + +proc tls10Prf*(dst: pointer; len: uint; secret: pointer; secretLen: uint; + label: cstring; seedNum: uint; seed: ptr TlsPrfSeedChunk) {.importcFunc, + importc: "br_tls10_prf", header: "bearssl_prf.h".} + +proc tls12Sha256Prf*(dst: pointer; len: uint; secret: pointer; secretLen: uint; + label: cstring; seedNum: uint; seed: ptr TlsPrfSeedChunk) {. + importcFunc, importc: "br_tls12_sha256_prf", header: "bearssl_prf.h".} + +proc tls12Sha384Prf*(dst: pointer; len: uint; secret: pointer; secretLen: uint; + label: cstring; seedNum: uint; seed: ptr TlsPrfSeedChunk) {. + importcFunc, importc: "br_tls12_sha384_prf", header: "bearssl_prf.h".} + +type + TlsPrfImpl* {.importc: "br_tls_prf_impl".} = proc (dst: pointer; len: uint; secret: pointer; secretLen: uint; + label: cstring; seedNum: uint; seed: ptr TlsPrfSeedChunk) {.importcFunc.} diff --git a/vendor/nim-bearssl/bearssl/abi/bearssl_rand.nim b/vendor/nim-bearssl/bearssl/abi/bearssl_rand.nim new file mode 100644 index 000000000..177519b7f --- /dev/null +++ b/vendor/nim-bearssl/bearssl/abi/bearssl_rand.nim @@ -0,0 +1,80 @@ +import + "."/[bearssl_hash, bearssl_hmac, csources] + +{.pragma: importcFunc, cdecl, gcsafe, noSideEffect, raises: [].} +{.used.} + +const + bearRandPath = bearSrcPath & "rand/" + +# {.compile: bearRandPath & "aesctr_drbg.c".} +{.compile: bearRandPath & "hmac_drbg.c".} +{.compile: bearRandPath & "sysrng.c".} + +type + PrngClass* {.importc: "br_prng_class", header: "bearssl_rand.h", bycopy.} = object + contextSize* {.importc: "context_size".}: uint + init* {.importc: "init".}: proc (ctx: ptr ptr PrngClass; params: pointer; + seed: pointer; seedLen: uint) {.importcFunc.} + generate* {.importc: "generate".}: proc (ctx: ptr ptr PrngClass; `out`: pointer; + len: uint) {.importcFunc.} + update* {.importc: "update".}: proc (ctx: ptr ptr PrngClass; seed: pointer; + seedLen: uint) {.importcFunc.} + + + +type + HmacDrbgContext* {.importc: "br_hmac_drbg_context", header: "bearssl_rand.h", + bycopy.} = object + vtable* {.importc: "vtable".}: ptr PrngClass + k* {.importc: "K".}: array[64, byte] + v* {.importc: "V".}: array[64, byte] + digestClass* {.importc: "digest_class".}: ptr HashClass + + + +var hmacDrbgVtable* {.importc: "br_hmac_drbg_vtable", header: "bearssl_rand.h".}: PrngClass + + +proc hmacDrbgInit*(ctx: var HmacDrbgContext; digestClass: ptr HashClass; seed: pointer; + seedLen: uint) {.importcFunc, importc: "br_hmac_drbg_init", + header: "bearssl_rand.h".} + +proc hmacDrbgGenerate*(ctx: var HmacDrbgContext; `out`: pointer; len: uint) {.importcFunc, + importc: "br_hmac_drbg_generate", header: "bearssl_rand.h".} + +proc hmacDrbgUpdate*(ctx: var HmacDrbgContext; seed: pointer; seedLen: uint) {.importcFunc, + importc: "br_hmac_drbg_update", header: "bearssl_rand.h".} + +proc hmacDrbgGetHash*(ctx: var HmacDrbgContext): ptr HashClass {.inline.} = + return ctx.digestClass + + +type + PrngSeeder* {.importc: "br_prng_seeder".} = proc (ctx: ptr ptr PrngClass): cint {.importcFunc.} + + +proc prngSeederSystem*(name: cstringArray): PrngSeeder {.importcFunc, + importc: "br_prng_seeder_system", header: "bearssl_rand.h".} + +# type +# AesctrDrbgContext* {.importc: "br_aesctr_drbg_context", header: "bearssl_rand.h", +# bycopy.} = object +# vtable* {.importc: "vtable".}: ptr PrngClass +# sk* {.importc: "sk".}: AesGenCtrKeys +# cc* {.importc: "cc".}: uint32 + + + +# var aesctrDrbgVtable* {.importc: "br_aesctr_drbg_vtable", header: "bearssl_rand.h".}: PrngClass + + +# proc aesctrDrbgInit*(ctx: var AesctrDrbgContext; aesctr: ptr BlockCtrClass; +# seed: pointer; seedLen: uint) {.importcFunc, +# importc: "br_aesctr_drbg_init", header: "bearssl_rand.h".} + +# proc aesctrDrbgGenerate*(ctx: var AesctrDrbgContext; `out`: pointer; len: uint) {. +# importcFunc, importc: "br_aesctr_drbg_generate", header: "bearssl_rand.h".} + +# proc aesctrDrbgUpdate*(ctx: var AesctrDrbgContext; seed: pointer; seedLen: uint) {. +# importcFunc, importc: "br_aesctr_drbg_update", header: "bearssl_rand.h".} diff --git a/vendor/nim-bearssl/bearssl/abi/bearssl_rsa.nim b/vendor/nim-bearssl/bearssl/abi/bearssl_rsa.nim new file mode 100644 index 000000000..6c8df5276 --- /dev/null +++ b/vendor/nim-bearssl/bearssl/abi/bearssl_rsa.nim @@ -0,0 +1,422 @@ +import + "."/[bearssl_hash, bearssl_rand, csources, intx] + +{.pragma: importcFunc, cdecl, gcsafe, noSideEffect, raises: [].} +{.used.} + +const + bearRsaPath = bearSrcPath & "rsa/" + +{.compile: bearRsaPath & "rsa_default_keygen.c".} +{.compile: bearRsaPath & "rsa_default_modulus.c".} +{.compile: bearRsaPath & "rsa_default_oaep_decrypt.c".} +{.compile: bearRsaPath & "rsa_default_oaep_encrypt.c".} +{.compile: bearRsaPath & "rsa_default_pkcs1_sign.c".} +{.compile: bearRsaPath & "rsa_default_pkcs1_vrfy.c".} +{.compile: bearRsaPath & "rsa_default_priv.c".} +{.compile: bearRsaPath & "rsa_default_privexp.c".} +{.compile: bearRsaPath & "rsa_default_pss_sign.c".} +{.compile: bearRsaPath & "rsa_default_pss_vrfy.c".} +{.compile: bearRsaPath & "rsa_default_pub.c".} +{.compile: bearRsaPath & "rsa_default_pubexp.c".} +{.compile: bearRsaPath & "rsa_i15_keygen.c".} +{.compile: bearRsaPath & "rsa_i15_modulus.c".} +{.compile: bearRsaPath & "rsa_i15_oaep_decrypt.c".} +{.compile: bearRsaPath & "rsa_i15_oaep_encrypt.c".} +{.compile: bearRsaPath & "rsa_i15_pkcs1_sign.c".} +{.compile: bearRsaPath & "rsa_i15_pkcs1_vrfy.c".} +{.compile: bearRsaPath & "rsa_i15_priv.c".} +{.compile: bearRsaPath & "rsa_i15_privexp.c".} +{.compile: bearRsaPath & "rsa_i15_pss_sign.c".} +{.compile: bearRsaPath & "rsa_i15_pss_vrfy.c".} +{.compile: bearRsaPath & "rsa_i15_pub.c".} +{.compile: bearRsaPath & "rsa_i15_pubexp.c".} +{.compile: bearRsaPath & "rsa_i31_keygen.c".} +{.compile: bearRsaPath & "rsa_i31_keygen_inner.c".} +{.compile: bearRsaPath & "rsa_i31_modulus.c".} +{.compile: bearRsaPath & "rsa_i31_oaep_decrypt.c".} +{.compile: bearRsaPath & "rsa_i31_oaep_encrypt.c".} +{.compile: bearRsaPath & "rsa_i31_pkcs1_sign.c".} +{.compile: bearRsaPath & "rsa_i31_pkcs1_vrfy.c".} +{.compile: bearRsaPath & "rsa_i31_priv.c".} +{.compile: bearRsaPath & "rsa_i31_privexp.c".} +{.compile: bearRsaPath & "rsa_i31_pss_sign.c".} +{.compile: bearRsaPath & "rsa_i31_pss_vrfy.c".} +{.compile: bearRsaPath & "rsa_i31_pub.c".} +{.compile: bearRsaPath & "rsa_i31_pubexp.c".} +{.compile: bearRsaPath & "rsa_i32_oaep_decrypt.c".} +{.compile: bearRsaPath & "rsa_i32_oaep_encrypt.c".} +{.compile: bearRsaPath & "rsa_i32_pkcs1_sign.c".} +{.compile: bearRsaPath & "rsa_i32_pkcs1_vrfy.c".} +{.compile: bearRsaPath & "rsa_i32_priv.c".} +{.compile: bearRsaPath & "rsa_i32_pss_sign.c".} +{.compile: bearRsaPath & "rsa_i32_pss_vrfy.c".} +{.compile: bearRsaPath & "rsa_i32_pub.c".} +{.compile: bearRsaPath & "rsa_i62_keygen.c".} +{.compile: bearRsaPath & "rsa_i62_oaep_decrypt.c".} +{.compile: bearRsaPath & "rsa_i62_oaep_encrypt.c".} +{.compile: bearRsaPath & "rsa_i62_pkcs1_sign.c".} +{.compile: bearRsaPath & "rsa_i62_pkcs1_vrfy.c".} +{.compile: bearRsaPath & "rsa_i62_priv.c".} +{.compile: bearRsaPath & "rsa_i62_pss_sign.c".} +{.compile: bearRsaPath & "rsa_i62_pss_vrfy.c".} +{.compile: bearRsaPath & "rsa_i62_pub.c".} +{.compile: bearRsaPath & "rsa_oaep_pad.c".} +{.compile: bearRsaPath & "rsa_oaep_unpad.c".} +{.compile: bearRsaPath & "rsa_pkcs1_sig_pad.c".} +{.compile: bearRsaPath & "rsa_pkcs1_sig_unpad.c".} +{.compile: bearRsaPath & "rsa_pss_sig_pad.c".} +{.compile: bearRsaPath & "rsa_pss_sig_unpad.c".} +{.compile: bearRsaPath & "rsa_ssl_decrypt.c".} + +type + RsaPublicKey* {.importc: "br_rsa_public_key", header: "bearssl_rsa.h", bycopy.} = object + n* {.importc: "n".}: ptr byte + nlen* {.importc: "nlen".}: uint + e* {.importc: "e".}: ptr byte + elen* {.importc: "elen".}: uint + + + +type + RsaPrivateKey* {.importc: "br_rsa_private_key", header: "bearssl_rsa.h", bycopy.} = object + nBitlen* {.importc: "n_bitlen".}: uint32 + p* {.importc: "p".}: ptr byte + plen* {.importc: "plen".}: uint + q* {.importc: "q".}: ptr byte + qlen* {.importc: "qlen".}: uint + dp* {.importc: "dp".}: ptr byte + dplen* {.importc: "dplen".}: uint + dq* {.importc: "dq".}: ptr byte + dqlen* {.importc: "dqlen".}: uint + iq* {.importc: "iq".}: ptr byte + iqlen* {.importc: "iqlen".}: uint + + + +type + RsaPublic* {.importc: "br_rsa_public".} = proc (x: ptr byte; xlen: uint; pk: ptr RsaPublicKey): uint32 {.importcFunc.} + + +type + RsaPkcs1Vrfy* {.importc: "br_rsa_pkcs1_vrfy".} = proc (x: ptr byte; xlen: uint; hashOid: ptr byte; + hashLen: uint; pk: ptr RsaPublicKey; hashOut: ptr byte): uint32 {. + importcFunc.} + + +type + RsaPssVrfy* {.importc: "br_rsa_pss_vrfy".} = proc (x: ptr byte; xlen: uint; hfData: ptr HashClass; + hfMgf1: ptr HashClass; hash: pointer; saltLen: uint; + pk: ptr RsaPublicKey): uint32 {.importcFunc.} + + +type + RsaOaepEncrypt* {.importc: "br_rsa_oaep_encrypt".} = proc (rnd: ptr ptr PrngClass; dig: ptr HashClass; label: pointer; + labelLen: uint; pk: ptr RsaPublicKey; dst: pointer; + dstMaxLen: uint; src: pointer; srcLen: uint): uint {. + importcFunc.} + + +type + RsaPrivate* {.importc: "br_rsa_private".} = proc (x: ptr byte; sk: ptr RsaPrivateKey): uint32 {.importcFunc.} + + +type + RsaPkcs1Sign* {.importc: "br_rsa_pkcs1_sign".} = proc (hashOid: ptr byte; hash: ptr byte; hashLen: uint; + sk: ptr RsaPrivateKey; x: ptr byte): uint32 {.importcFunc.} + + +type + RsaPssSign* {.importc: "br_rsa_pss_sign".} = proc (rng: ptr ptr PrngClass; hfData: ptr HashClass; + hfMgf1: ptr HashClass; hashValue: ptr byte; saltLen: uint; + sk: ptr RsaPrivateKey; x: ptr byte): uint32 {.importcFunc.} + + +const + HASH_OID_SHA1* = (("\x05+\x0E\x03\x02\x1A")) + + +const + HASH_OID_SHA224* = (("\t`\x86H\x01e\x03\x04\x02\x04")) + + +const + HASH_OID_SHA256* = (("\t`\x86H\x01e\x03\x04\x02\x01")) + + +const + HASH_OID_SHA384* = (("\t`\x86H\x01e\x03\x04\x02\x02")) + + +const + HASH_OID_SHA512* = (("\t`\x86H\x01e\x03\x04\x02\x03")) + + +type + RsaOaepDecrypt* {.importc: "br_rsa_oaep_decrypt".} = proc (dig: ptr HashClass; label: pointer; labelLen: uint; + sk: ptr RsaPrivateKey; data: pointer; len: var uint): uint32 {. + importcFunc.} + + +proc rsaI32Public*(x: ptr byte; xlen: uint; pk: ptr RsaPublicKey): uint32 {.importcFunc, + importc: "br_rsa_i32_public", header: "bearssl_rsa.h".} + +proc rsaI32Pkcs1Vrfy*(x: ptr byte; xlen: uint; hashOid: ptr byte; + hashLen: uint; pk: ptr RsaPublicKey; hashOut: ptr byte): uint32 {. + importcFunc, importc: "br_rsa_i32_pkcs1_vrfy", header: "bearssl_rsa.h".} + +proc rsaI32PssVrfy*(x: ptr byte; xlen: uint; hfData: ptr HashClass; + hfMgf1: ptr HashClass; hash: pointer; saltLen: uint; + pk: ptr RsaPublicKey): uint32 {.importcFunc, + importc: "br_rsa_i32_pss_vrfy", header: "bearssl_rsa.h".} + +proc rsaI32Private*(x: ptr byte; sk: ptr RsaPrivateKey): uint32 {.importcFunc, + importc: "br_rsa_i32_private", header: "bearssl_rsa.h".} + +proc rsaI32Pkcs1Sign*(hashOid: ptr byte; hash: ptr byte; hashLen: uint; + sk: ptr RsaPrivateKey; x: ptr byte): uint32 {.importcFunc, + importc: "br_rsa_i32_pkcs1_sign", header: "bearssl_rsa.h".} + +proc rsaI32PssSign*(rng: ptr ptr PrngClass; hfData: ptr HashClass; + hfMgf1: ptr HashClass; hashValue: ptr byte; saltLen: uint; + sk: ptr RsaPrivateKey; x: ptr byte): uint32 {.importcFunc, + importc: "br_rsa_i32_pss_sign", header: "bearssl_rsa.h".} + +proc rsaI31Public*(x: ptr byte; xlen: uint; pk: ptr RsaPublicKey): uint32 {.importcFunc, + importc: "br_rsa_i31_public", header: "bearssl_rsa.h".} + +proc rsaI31Pkcs1Vrfy*(x: ptr byte; xlen: uint; hashOid: ptr byte; + hashLen: uint; pk: ptr RsaPublicKey; hashOut: ptr byte): uint32 {. + importcFunc, importc: "br_rsa_i31_pkcs1_vrfy", header: "bearssl_rsa.h".} + +proc rsaI31PssVrfy*(x: ptr byte; xlen: uint; hfData: ptr HashClass; + hfMgf1: ptr HashClass; hash: pointer; saltLen: uint; + pk: ptr RsaPublicKey): uint32 {.importcFunc, + importc: "br_rsa_i31_pss_vrfy", header: "bearssl_rsa.h".} + +proc rsaI31Private*(x: ptr byte; sk: ptr RsaPrivateKey): uint32 {.importcFunc, + importc: "br_rsa_i31_private", header: "bearssl_rsa.h".} + +proc rsaI31Pkcs1Sign*(hashOid: ptr byte; hash: ptr byte; hashLen: uint; + sk: ptr RsaPrivateKey; x: ptr byte): uint32 {.importcFunc, + importc: "br_rsa_i31_pkcs1_sign", header: "bearssl_rsa.h".} + +proc rsaI31PssSign*(rng: ptr ptr PrngClass; hfData: ptr HashClass; + hfMgf1: ptr HashClass; hashValue: ptr byte; saltLen: uint; + sk: ptr RsaPrivateKey; x: ptr byte): uint32 {.importcFunc, + importc: "br_rsa_i31_pss_sign", header: "bearssl_rsa.h".} + +proc rsaI62Public*(x: ptr byte; xlen: uint; pk: ptr RsaPublicKey): uint32 {.importcFunc, + importc: "br_rsa_i62_public", header: "bearssl_rsa.h".} + +proc rsaI62Pkcs1Vrfy*(x: ptr byte; xlen: uint; hashOid: ptr byte; + hashLen: uint; pk: ptr RsaPublicKey; hashOut: ptr byte): uint32 {. + importcFunc, importc: "br_rsa_i62_pkcs1_vrfy", header: "bearssl_rsa.h".} + +proc rsaI62PssVrfy*(x: ptr byte; xlen: uint; hfData: ptr HashClass; + hfMgf1: ptr HashClass; hash: pointer; saltLen: uint; + pk: ptr RsaPublicKey): uint32 {.importcFunc, + importc: "br_rsa_i62_pss_vrfy", header: "bearssl_rsa.h".} + +proc rsaI62Private*(x: ptr byte; sk: ptr RsaPrivateKey): uint32 {.importcFunc, + importc: "br_rsa_i62_private", header: "bearssl_rsa.h".} + +proc rsaI62Pkcs1Sign*(hashOid: ptr byte; hash: ptr byte; hashLen: uint; + sk: ptr RsaPrivateKey; x: ptr byte): uint32 {.importcFunc, + importc: "br_rsa_i62_pkcs1_sign", header: "bearssl_rsa.h".} + +proc rsaI62PssSign*(rng: ptr ptr PrngClass; hfData: ptr HashClass; + hfMgf1: ptr HashClass; hashValue: ptr byte; saltLen: uint; + sk: ptr RsaPrivateKey; x: ptr byte): uint32 {.importcFunc, + importc: "br_rsa_i62_pss_sign", header: "bearssl_rsa.h".} + +proc rsaI62PublicGet*(): RsaPublic {.importcFunc, importc: "br_rsa_i62_public_get", + header: "bearssl_rsa.h".} + +proc rsaI62Pkcs1VrfyGet*(): RsaPkcs1Vrfy {.importcFunc, + importc: "br_rsa_i62_pkcs1_vrfy_get", + header: "bearssl_rsa.h".} + +proc rsaI62PssVrfyGet*(): RsaPssVrfy {.importcFunc, importc: "br_rsa_i62_pss_vrfy_get", + header: "bearssl_rsa.h".} + +proc rsaI62PrivateGet*(): RsaPrivate {.importcFunc, importc: "br_rsa_i62_private_get", + header: "bearssl_rsa.h".} + +proc rsaI62Pkcs1SignGet*(): RsaPkcs1Sign {.importcFunc, + importc: "br_rsa_i62_pkcs1_sign_get", + header: "bearssl_rsa.h".} + +proc rsaI62PssSignGet*(): RsaPssSign {.importcFunc, importc: "br_rsa_i62_pss_sign_get", + header: "bearssl_rsa.h".} + +proc rsaI62OaepEncryptGet*(): RsaOaepEncrypt {.importcFunc, + importc: "br_rsa_i62_oaep_encrypt_get", header: "bearssl_rsa.h".} + +proc rsaI62OaepDecryptGet*(): RsaOaepDecrypt {.importcFunc, + importc: "br_rsa_i62_oaep_decrypt_get", header: "bearssl_rsa.h".} + +proc rsaI15Public*(x: ptr byte; xlen: uint; pk: ptr RsaPublicKey): uint32 {.importcFunc, + importc: "br_rsa_i15_public", header: "bearssl_rsa.h".} + +proc rsaI15Pkcs1Vrfy*(x: ptr byte; xlen: uint; hashOid: ptr byte; + hashLen: uint; pk: ptr RsaPublicKey; hashOut: ptr byte): uint32 {. + importcFunc, importc: "br_rsa_i15_pkcs1_vrfy", header: "bearssl_rsa.h".} + +proc rsaI15PssVrfy*(x: ptr byte; xlen: uint; hfData: ptr HashClass; + hfMgf1: ptr HashClass; hash: pointer; saltLen: uint; + pk: ptr RsaPublicKey): uint32 {.importcFunc, + importc: "br_rsa_i15_pss_vrfy", header: "bearssl_rsa.h".} + +proc rsaI15Private*(x: ptr byte; sk: ptr RsaPrivateKey): uint32 {.importcFunc, + importc: "br_rsa_i15_private", header: "bearssl_rsa.h".} + +proc rsaI15Pkcs1Sign*(hashOid: ptr byte; hash: ptr byte; hashLen: uint; + sk: ptr RsaPrivateKey; x: ptr byte): uint32 {.importcFunc, + importc: "br_rsa_i15_pkcs1_sign", header: "bearssl_rsa.h".} + +proc rsaI15PssSign*(rng: ptr ptr PrngClass; hfData: ptr HashClass; + hfMgf1: ptr HashClass; hashValue: ptr byte; saltLen: uint; + sk: ptr RsaPrivateKey; x: ptr byte): uint32 {.importcFunc, + importc: "br_rsa_i15_pss_sign", header: "bearssl_rsa.h".} + +proc rsaPublicGetDefault*(): RsaPublic {.importcFunc, + importc: "br_rsa_public_get_default", + header: "bearssl_rsa.h".} + +proc rsaPrivateGetDefault*(): RsaPrivate {.importcFunc, + importc: "br_rsa_private_get_default", + header: "bearssl_rsa.h".} + +proc rsaPkcs1VrfyGetDefault*(): RsaPkcs1Vrfy {.importcFunc, + importc: "br_rsa_pkcs1_vrfy_get_default", header: "bearssl_rsa.h".} + +proc rsaPssVrfyGetDefault*(): RsaPssVrfy {.importcFunc, + importc: "br_rsa_pss_vrfy_get_default", + header: "bearssl_rsa.h".} + +proc rsaPkcs1SignGetDefault*(): RsaPkcs1Sign {.importcFunc, + importc: "br_rsa_pkcs1_sign_get_default", header: "bearssl_rsa.h".} + +proc rsaPssSignGetDefault*(): RsaPssSign {.importcFunc, + importc: "br_rsa_pss_sign_get_default", + header: "bearssl_rsa.h".} + +proc rsaOaepEncryptGetDefault*(): RsaOaepEncrypt {.importcFunc, + importc: "br_rsa_oaep_encrypt_get_default", header: "bearssl_rsa.h".} + +proc rsaOaepDecryptGetDefault*(): RsaOaepDecrypt {.importcFunc, + importc: "br_rsa_oaep_decrypt_get_default", header: "bearssl_rsa.h".} + +proc rsaSslDecrypt*(core: RsaPrivate; sk: ptr RsaPrivateKey; data: ptr byte; + len: uint): uint32 {.importcFunc, importc: "br_rsa_ssl_decrypt", + header: "bearssl_rsa.h".} + +proc rsaI15OaepEncrypt*(rnd: ptr ptr PrngClass; dig: ptr HashClass; label: pointer; + labelLen: uint; pk: ptr RsaPublicKey; dst: pointer; + dstMaxLen: uint; src: pointer; srcLen: uint): uint {. + importcFunc, importc: "br_rsa_i15_oaep_encrypt", header: "bearssl_rsa.h".} + +proc rsaI15OaepDecrypt*(dig: ptr HashClass; label: pointer; labelLen: uint; + sk: ptr RsaPrivateKey; data: pointer; len: var uint): uint32 {. + importcFunc, importc: "br_rsa_i15_oaep_decrypt", header: "bearssl_rsa.h".} + +proc rsaI31OaepEncrypt*(rnd: ptr ptr PrngClass; dig: ptr HashClass; label: pointer; + labelLen: uint; pk: ptr RsaPublicKey; dst: pointer; + dstMaxLen: uint; src: pointer; srcLen: uint): uint {. + importcFunc, importc: "br_rsa_i31_oaep_encrypt", header: "bearssl_rsa.h".} + +proc rsaI31OaepDecrypt*(dig: ptr HashClass; label: pointer; labelLen: uint; + sk: ptr RsaPrivateKey; data: pointer; len: var uint): uint32 {. + importcFunc, importc: "br_rsa_i31_oaep_decrypt", header: "bearssl_rsa.h".} + +proc rsaI32OaepEncrypt*(rnd: ptr ptr PrngClass; dig: ptr HashClass; label: pointer; + labelLen: uint; pk: ptr RsaPublicKey; dst: pointer; + dstMaxLen: uint; src: pointer; srcLen: uint): uint {. + importcFunc, importc: "br_rsa_i32_oaep_encrypt", header: "bearssl_rsa.h".} + +proc rsaI32OaepDecrypt*(dig: ptr HashClass; label: pointer; labelLen: uint; + sk: ptr RsaPrivateKey; data: pointer; len: var uint): uint32 {. + importcFunc, importc: "br_rsa_i32_oaep_decrypt", header: "bearssl_rsa.h".} + +proc rsaI62OaepEncrypt*(rnd: ptr ptr PrngClass; dig: ptr HashClass; label: pointer; + labelLen: uint; pk: ptr RsaPublicKey; dst: pointer; + dstMaxLen: uint; src: pointer; srcLen: uint): uint {. + importcFunc, importc: "br_rsa_i62_oaep_encrypt", header: "bearssl_rsa.h".} + +proc rsaI62OaepDecrypt*(dig: ptr HashClass; label: pointer; labelLen: uint; + sk: ptr RsaPrivateKey; data: pointer; len: var uint): uint32 {. + importcFunc, importc: "br_rsa_i62_oaep_decrypt", header: "bearssl_rsa.h".} + +template rsaKbufPrivSize*(size: untyped): untyped = + (5 * (((size) + 15) shr 4)) + + +template rsaKbufPubSize*(size: untyped): untyped = + (4 + (((size) + 7) shr 3)) + + +type + RsaKeygen* {.importc: "br_rsa_keygen".} = proc (rngCtx: ptr ptr PrngClass; sk: ptr RsaPrivateKey; kbufPriv: pointer; + pk: ptr RsaPublicKey; kbufPub: pointer; size: cuint; pubexp: uint32): uint32 {. + importcFunc.} + + +proc rsaI15Keygen*(rngCtx: ptr ptr PrngClass; sk: ptr RsaPrivateKey; kbufPriv: pointer; + pk: ptr RsaPublicKey; kbufPub: pointer; size: cuint; pubexp: uint32): uint32 {. + importcFunc, importc: "br_rsa_i15_keygen", header: "bearssl_rsa.h".} + +proc rsaI31Keygen*(rngCtx: ptr ptr PrngClass; sk: ptr RsaPrivateKey; kbufPriv: pointer; + pk: ptr RsaPublicKey; kbufPub: pointer; size: cuint; pubexp: uint32): uint32 {. + importcFunc, importc: "br_rsa_i31_keygen", header: "bearssl_rsa.h".} + +proc rsaI62Keygen*(rngCtx: ptr ptr PrngClass; sk: ptr RsaPrivateKey; kbufPriv: pointer; + pk: ptr RsaPublicKey; kbufPub: pointer; size: cuint; pubexp: uint32): uint32 {. + importcFunc, importc: "br_rsa_i62_keygen", header: "bearssl_rsa.h".} + +proc rsaI62KeygenGet*(): RsaKeygen {.importcFunc, importc: "br_rsa_i62_keygen_get", + header: "bearssl_rsa.h".} + +proc rsaKeygenGetDefault*(): RsaKeygen {.importcFunc, + importc: "br_rsa_keygen_get_default", + header: "bearssl_rsa.h".} + +type + RsaComputeModulus* {.importc: "br_rsa_compute_modulus".} = proc (n: pointer; sk: ptr RsaPrivateKey): uint {.importcFunc.} + + +proc rsaI15ComputeModulus*(n: pointer; sk: ptr RsaPrivateKey): uint {.importcFunc, + importc: "br_rsa_i15_compute_modulus", header: "bearssl_rsa.h".} + +proc rsaI31ComputeModulus*(n: pointer; sk: ptr RsaPrivateKey): uint {.importcFunc, + importc: "br_rsa_i31_compute_modulus", header: "bearssl_rsa.h".} + +proc rsaComputeModulusGetDefault*(): RsaComputeModulus {.importcFunc, + importc: "br_rsa_compute_modulus_get_default", header: "bearssl_rsa.h".} + +type + RsaComputePubexp* = proc (sk: ptr RsaPrivateKey): uint32 {.importcFunc.} + + +proc rsaI15ComputePubexp*(sk: ptr RsaPrivateKey): uint32 {.importcFunc, + importc: "br_rsa_i15_compute_pubexp", header: "bearssl_rsa.h".} + +proc rsaI31ComputePubexp*(sk: ptr RsaPrivateKey): uint32 {.importcFunc, + importc: "br_rsa_i31_compute_pubexp", header: "bearssl_rsa.h".} + +proc rsaComputePubexpGetDefault*(): RsaComputePubexp {.importcFunc, + importc: "br_rsa_compute_pubexp_get_default", header: "bearssl_rsa.h".} + +type + RsaComputePrivexp* {.importc: "br_rsa_compute_privexp".} = proc (d: pointer; sk: ptr RsaPrivateKey; pubexp: uint32): uint {. + importcFunc.} + + +proc rsaI15ComputePrivexp*(d: pointer; sk: ptr RsaPrivateKey; pubexp: uint32): uint {. + importcFunc, importc: "br_rsa_i15_compute_privexp", header: "bearssl_rsa.h".} + +proc rsaI31ComputePrivexp*(d: pointer; sk: ptr RsaPrivateKey; pubexp: uint32): uint {. + importcFunc, importc: "br_rsa_i31_compute_privexp", header: "bearssl_rsa.h".} + +proc rsaComputePrivexpGetDefault*(): RsaComputePrivexp {.importcFunc, + importc: "br_rsa_compute_privexp_get_default", header: "bearssl_rsa.h".} diff --git a/vendor/nim-bearssl/bearssl/abi/bearssl_ssl.nim b/vendor/nim-bearssl/bearssl/abi/bearssl_ssl.nim new file mode 100644 index 000000000..4bb57b32b --- /dev/null +++ b/vendor/nim-bearssl/bearssl/abi/bearssl_ssl.nim @@ -0,0 +1,1425 @@ +import + "."/[ + bearssl_aead, bearssl_block, bearssl_ec, bearssl_hash, bearssl_hmac, + bearssl_prf, bearssl_rand, bearssl_rsa, bearssl_x509, csources] + +{.pragma: importcFunc, cdecl, gcsafe, noSideEffect, raises: [].} +{.used.} + +const + bearSslPath = bearSrcPath & "ssl/" + +{.compile: bearSslPath & "ssl_ccert_single_ec.c".} +{.compile: bearSslPath & "ssl_ccert_single_rsa.c".} +{.compile: bearSslPath & "ssl_client.c".} +{.compile: bearSslPath & "ssl_client_default_rsapub.c".} +{.compile: bearSslPath & "ssl_client_full.c".} +{.compile: bearSslPath & "ssl_engine.c".} +{.compile: bearSslPath & "ssl_engine_default_aescbc.c".} +{.compile: bearSslPath & "ssl_engine_default_aesccm.c".} +{.compile: bearSslPath & "ssl_engine_default_aesgcm.c".} +{.compile: bearSslPath & "ssl_engine_default_chapol.c".} +{.compile: bearSslPath & "ssl_engine_default_descbc.c".} +{.compile: bearSslPath & "ssl_engine_default_ec.c".} +{.compile: bearSslPath & "ssl_engine_default_ecdsa.c".} +{.compile: bearSslPath & "ssl_engine_default_rsavrfy.c".} +{.compile: bearSslPath & "ssl_hashes.c".} +{.compile: bearSslPath & "ssl_hs_client.c".} +{.compile: bearSslPath & "ssl_hs_server.c".} +{.compile: bearSslPath & "ssl_io.c".} +{.compile: bearSslPath & "ssl_keyexport.c".} +{.compile: bearSslPath & "ssl_lru.c".} +{.compile: bearSslPath & "ssl_rec_cbc.c".} +{.compile: bearSslPath & "ssl_rec_ccm.c".} +{.compile: bearSslPath & "ssl_rec_chapol.c".} +{.compile: bearSslPath & "ssl_rec_gcm.c".} +{.compile: bearSslPath & "ssl_scert_single_ec.c".} +{.compile: bearSslPath & "ssl_scert_single_rsa.c".} +{.compile: bearSslPath & "ssl_server.c".} +{.compile: bearSslPath & "ssl_server_full_ec.c".} +{.compile: bearSslPath & "ssl_server_full_rsa.c".} +{.compile: bearSslPath & "ssl_server_mine2c.c".} +{.compile: bearSslPath & "ssl_server_mine2g.c".} +{.compile: bearSslPath & "ssl_server_minf2c.c".} +{.compile: bearSslPath & "ssl_server_minf2g.c".} +{.compile: bearSslPath & "ssl_server_minr2g.c".} +{.compile: bearSslPath & "ssl_server_minu2g.c".} +{.compile: bearSslPath & "ssl_server_minv2g.c".} + +const + SSL_BUFSIZE_INPUT* = (16384 + 325) + + +const + SSL_BUFSIZE_OUTPUT* = (16384 + 85) + + +const + SSL_BUFSIZE_MONO* = SSL_BUFSIZE_INPUT + +const + SSL_BUFSIZE_BIDI* = (SSL_BUFSIZE_INPUT + SSL_BUFSIZE_OUTPUT) + +const + SSL30* = 0x0300 + + +const + TLS10* = 0x0301 + + +const + TLS11* = 0x0302 + + +const + TLS12* = 0x0303 + + +const + ERR_OK* = 0 + + +const + ERR_BAD_PARAM* = 1 + + +const + ERR_BAD_STATE* = 2 + + +const + ERR_UNSUPPORTED_VERSION* = 3 + + +const + ERR_BAD_VERSION* = 4 + + +const + ERR_BAD_LENGTH* = 5 + + +const + ERR_TOO_LARGE* = 6 + + +const + ERR_BAD_MAC* = 7 + + +const + ERR_NO_RANDOM* = 8 + + +const + ERR_UNKNOWN_TYPE* = 9 + + +const + ERR_UNEXPECTED* = 10 + + +const + ERR_BAD_CCS* = 12 + + +const + ERR_BAD_ALERT* = 13 + + +const + ERR_BAD_HANDSHAKE* = 14 + + +const + ERR_OVERSIZED_ID* = 15 + + +const + ERR_BAD_CIPHER_SUITE* = 16 + + +const + ERR_BAD_COMPRESSION* = 17 + + +const + ERR_BAD_FRAGLEN* = 18 + + +const + ERR_BAD_SECRENEG* = 19 + + +const + ERR_EXTRA_EXTENSION* = 20 + + +const + ERR_BAD_SNI* = 21 + + +const + ERR_BAD_HELLO_DONE* = 22 + + +const + ERR_LIMIT_EXCEEDED* = 23 + + +const + ERR_BAD_FINISHED* = 24 + + +const + ERR_RESUME_MISMATCH* = 25 + + +const + ERR_INVALID_ALGORITHM* = 26 + + +const + ERR_BAD_SIGNATURE* = 27 + + +const + ERR_WRONG_KEY_USAGE* = 28 + + +const + ERR_NO_CLIENT_AUTH* = 29 + + +const + ERR_IO* = 31 + + +const + ERR_RECV_FATAL_ALERT* = 256 + + +const + ERR_SEND_FATAL_ALERT* = 512 + + +type + SslrecInClass* {.importc: "br_sslrec_in_class", header: "bearssl_ssl.h", bycopy.} = object + contextSize* {.importc: "context_size".}: uint + checkLength* {.importc: "check_length".}: proc (ctx: ptr ptr SslrecInClass; + recordLen: uint): cint {.importcFunc.} + decrypt* {.importc: "decrypt".}: proc (ctx: ptr ptr SslrecInClass; recordType: cint; + version: cuint; payload: pointer; + len: var uint): ptr byte {.importcFunc.} + + + +type + SslrecOutClass* {.importc: "br_sslrec_out_class", header: "bearssl_ssl.h", bycopy.} = object + contextSize* {.importc: "context_size".}: uint + maxPlaintext* {.importc: "max_plaintext".}: proc (ctx: ptr ptr SslrecOutClass; + start: ptr uint; `end`: ptr uint) {.importcFunc.} + encrypt* {.importc: "encrypt".}: proc (ctx: ptr ptr SslrecOutClass; + recordType: cint; version: cuint; + plaintext: pointer; len: var uint): ptr byte {. + importcFunc.} + + + +type + SslrecOutClearContext* {.importc: "br_sslrec_out_clear_context", + header: "bearssl_ssl.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr SslrecOutClass + + + +var sslrecOutClearVtable* {.importc: "br_sslrec_out_clear_vtable", header: "bearssl_ssl.h".}: SslrecOutClass + + +type + SslrecInCbcClass* {.importc: "br_sslrec_in_cbc_class", header: "bearssl_ssl.h", + bycopy.} = object + inner* {.importc: "inner".}: SslrecInClass + init* {.importc: "init".}: proc (ctx: ptr ptr SslrecInCbcClass; + bcImpl: ptr BlockCbcdecClass; bcKey: pointer; + bcKeyLen: uint; digImpl: ptr HashClass; + macKey: pointer; macKeyLen: uint; + macOutLen: uint; iv: pointer) {.importcFunc.} + + + +type + SslrecOutCbcClass* {.importc: "br_sslrec_out_cbc_class", + header: "bearssl_ssl.h", bycopy.} = object + inner* {.importc: "inner".}: SslrecOutClass + init* {.importc: "init".}: proc (ctx: ptr ptr SslrecOutCbcClass; + bcImpl: ptr BlockCbcencClass; bcKey: pointer; + bcKeyLen: uint; digImpl: ptr HashClass; + macKey: pointer; macKeyLen: uint; + macOutLen: uint; iv: pointer) {.importcFunc.} + + + +type + INNER_C_UNION_bearssl_ssl_1* {.importc: "br_sslrec_in_cbc_context::no_name", + header: "bearssl_ssl.h", bycopy, union.} = object + vtable* {.importc: "vtable".}: ptr BlockCbcdecClass + aes* {.importc: "aes".}: AesGenCbcdecKeys + des* {.importc: "des".}: DesGenCbcdecKeys + + SslrecInCbcContext* {.importc: "br_sslrec_in_cbc_context", + header: "bearssl_ssl.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr SslrecInCbcClass + seq* {.importc: "seq".}: uint64 + bc* {.importc: "bc".}: INNER_C_UNION_bearssl_ssl_1 + mac* {.importc: "mac".}: HmacKeyContext + macLen* {.importc: "mac_len".}: uint + iv* {.importc: "iv".}: array[16, byte] + explicitIV* {.importc: "explicit_IV".}: cint + + + +var sslrecInCbcVtable* {.importc: "br_sslrec_in_cbc_vtable", header: "bearssl_ssl.h".}: SslrecInCbcClass + + +type + INNER_C_UNION_bearssl_ssl_3* {.importc: "br_sslrec_out_cbc_context::no_name", + header: "bearssl_ssl.h", bycopy, union.} = object + vtable* {.importc: "vtable".}: ptr BlockCbcencClass + aes* {.importc: "aes".}: AesGenCbcencKeys + des* {.importc: "des".}: DesGenCbcencKeys + + SslrecOutCbcContext* {.importc: "br_sslrec_out_cbc_context", + header: "bearssl_ssl.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr SslrecOutCbcClass + seq* {.importc: "seq".}: uint64 + bc* {.importc: "bc".}: INNER_C_UNION_bearssl_ssl_3 + mac* {.importc: "mac".}: HmacKeyContext + macLen* {.importc: "mac_len".}: uint + iv* {.importc: "iv".}: array[16, byte] + explicitIV* {.importc: "explicit_IV".}: cint + + + +var sslrecOutCbcVtable* {.importc: "br_sslrec_out_cbc_vtable", header: "bearssl_ssl.h".}: SslrecOutCbcClass + + +type + SslrecInGcmClass* {.importc: "br_sslrec_in_gcm_class", header: "bearssl_ssl.h", + bycopy.} = object + inner* {.importc: "inner".}: SslrecInClass + init* {.importc: "init".}: proc (ctx: ptr ptr SslrecInGcmClass; + bcImpl: ptr BlockCtrClass; key: pointer; + keyLen: uint; ghImpl: Ghash; iv: pointer) {.importcFunc.} + + + +type + SslrecOutGcmClass* {.importc: "br_sslrec_out_gcm_class", + header: "bearssl_ssl.h", bycopy.} = object + inner* {.importc: "inner".}: SslrecOutClass + init* {.importc: "init".}: proc (ctx: ptr ptr SslrecOutGcmClass; + bcImpl: ptr BlockCtrClass; key: pointer; + keyLen: uint; ghImpl: Ghash; iv: pointer) {.importcFunc.} + + + +type + INNER_C_UNION_bearssl_ssl_6* {.importc: "br_sslrec_gcm_context::no_name", + header: "bearssl_ssl.h", bycopy, union.} = object + gen* {.importc: "gen".}: pointer + `in`* {.importc: "in".}: ptr SslrecInGcmClass + `out`* {.importc: "out".}: ptr SslrecOutGcmClass + + INNER_C_UNION_bearssl_ssl_7* {.importc: "br_sslrec_gcm_context::no_name", + header: "bearssl_ssl.h", bycopy, union.} = object + vtable* {.importc: "vtable".}: ptr BlockCtrClass + aes* {.importc: "aes".}: AesGenCtrKeys + + SslrecGcmContext* {.importc: "br_sslrec_gcm_context", header: "bearssl_ssl.h", + bycopy.} = object + vtable* {.importc: "vtable".}: INNER_C_UNION_bearssl_ssl_6 + seq* {.importc: "seq".}: uint64 + bc* {.importc: "bc".}: INNER_C_UNION_bearssl_ssl_7 + gh* {.importc: "gh".}: Ghash + iv* {.importc: "iv".}: array[4, byte] + h* {.importc: "h".}: array[16, byte] + + +var sslrecInGcmVtable* {.importc: "br_sslrec_in_gcm_vtable", header: "bearssl_ssl.h".}: SslrecInGcmClass + + + +var sslrecOutGcmVtable* {.importc: "br_sslrec_out_gcm_vtable", header: "bearssl_ssl.h".}: SslrecOutGcmClass + + +type + SslrecInChapolClass* {.importc: "br_sslrec_in_chapol_class", + header: "bearssl_ssl.h", bycopy.} = object + inner* {.importc: "inner".}: SslrecInClass + init* {.importc: "init".}: proc (ctx: ptr ptr SslrecInChapolClass; + ichacha: Chacha20Run; ipoly: Poly1305Run; + key: pointer; iv: pointer) {.importcFunc.} + + + +type + SslrecOutChapolClass* {.importc: "br_sslrec_out_chapol_class", + header: "bearssl_ssl.h", bycopy.} = object + inner* {.importc: "inner".}: SslrecOutClass + init* {.importc: "init".}: proc (ctx: ptr ptr SslrecOutChapolClass; + ichacha: Chacha20Run; ipoly: Poly1305Run; + key: pointer; iv: pointer) {.importcFunc.} + + + +type + INNER_C_UNION_bearssl_ssl_9* {.importc: "br_sslrec_chapol_context::no_name", + header: "bearssl_ssl.h", bycopy, union.} = object + gen* {.importc: "gen".}: pointer + `in`* {.importc: "in".}: ptr SslrecInChapolClass + `out`* {.importc: "out".}: ptr SslrecOutChapolClass + + SslrecChapolContext* {.importc: "br_sslrec_chapol_context", + header: "bearssl_ssl.h", bycopy.} = object + vtable* {.importc: "vtable".}: INNER_C_UNION_bearssl_ssl_9 + seq* {.importc: "seq".}: uint64 + key* {.importc: "key".}: array[32, byte] + iv* {.importc: "iv".}: array[12, byte] + ichacha* {.importc: "ichacha".}: Chacha20Run + ipoly* {.importc: "ipoly".}: Poly1305Run + + +var sslrecInChapolVtable* {.importc: "br_sslrec_in_chapol_vtable", header: "bearssl_ssl.h".}: SslrecInChapolClass + + + +var sslrecOutChapolVtable* {.importc: "br_sslrec_out_chapol_vtable", header: "bearssl_ssl.h".}: SslrecOutChapolClass + + +type + SslrecInCcmClass* {.importc: "br_sslrec_in_ccm_class", header: "bearssl_ssl.h", + bycopy.} = object + inner* {.importc: "inner".}: SslrecInClass + init* {.importc: "init".}: proc (ctx: ptr ptr SslrecInCcmClass; + bcImpl: ptr BlockCtrcbcClass; key: pointer; + keyLen: uint; iv: pointer; tagLen: uint) {. + importcFunc.} + + + +type + SslrecOutCcmClass* {.importc: "br_sslrec_out_ccm_class", + header: "bearssl_ssl.h", bycopy.} = object + inner* {.importc: "inner".}: SslrecOutClass + init* {.importc: "init".}: proc (ctx: ptr ptr SslrecOutCcmClass; + bcImpl: ptr BlockCtrcbcClass; key: pointer; + keyLen: uint; iv: pointer; tagLen: uint) {. + importcFunc.} + + + +type + INNER_C_UNION_bearssl_ssl_12* {.importc: "br_sslrec_ccm_context::no_name", + header: "bearssl_ssl.h", bycopy, union.} = object + gen* {.importc: "gen".}: pointer + `in`* {.importc: "in".}: ptr SslrecInCcmClass + `out`* {.importc: "out".}: ptr SslrecOutCcmClass + + INNER_C_UNION_bearssl_ssl_13* {.importc: "br_sslrec_ccm_context::no_name", + header: "bearssl_ssl.h", bycopy, union.} = object + vtable* {.importc: "vtable".}: ptr BlockCtrcbcClass + aes* {.importc: "aes".}: AesGenCtrcbcKeys + + SslrecCcmContext* {.importc: "br_sslrec_ccm_context", header: "bearssl_ssl.h", + bycopy.} = object + vtable* {.importc: "vtable".}: INNER_C_UNION_bearssl_ssl_12 + seq* {.importc: "seq".}: uint64 + bc* {.importc: "bc".}: INNER_C_UNION_bearssl_ssl_13 + iv* {.importc: "iv".}: array[4, byte] + tagLen* {.importc: "tag_len".}: uint + + + +var sslrecInCcmVtable* {.importc: "br_sslrec_in_ccm_vtable", header: "bearssl_ssl.h".}: SslrecInCcmClass + + +var sslrecOutCcmVtable* {.importc: "br_sslrec_out_ccm_vtable", header: "bearssl_ssl.h".}: SslrecOutCcmClass + + +type + SslSessionParameters* {.importc: "br_ssl_session_parameters", + header: "bearssl_ssl.h", bycopy.} = object + sessionId* {.importc: "session_id".}: array[32, byte] + sessionIdLen* {.importc: "session_id_len".}: byte + version* {.importc: "version".}: uint16 + cipherSuite* {.importc: "cipher_suite".}: uint16 + masterSecret* {.importc: "master_secret".}: array[48, byte] + + + +const + MAX_CIPHER_SUITES* = 48 + + +type + INNER_C_UNION_bearssl_ssl_17* {.importc: "br_ssl_engine_context::no_name", + header: "bearssl_ssl.h", bycopy, union.} = object + vtable* {.importc: "vtable".}: ptr SslrecInClass + cbc* {.importc: "cbc".}: SslrecInCbcContext + gcm* {.importc: "gcm".}: SslrecGcmContext + chapol* {.importc: "chapol".}: SslrecChapolContext + ccm* {.importc: "ccm".}: SslrecCcmContext + + INNER_C_UNION_bearssl_ssl_18* {.importc: "br_ssl_engine_context::no_name", + header: "bearssl_ssl.h", bycopy, union.} = object + vtable* {.importc: "vtable".}: ptr SslrecOutClass + clear* {.importc: "clear".}: SslrecOutClearContext + cbc* {.importc: "cbc".}: SslrecOutCbcContext + gcm* {.importc: "gcm".}: SslrecGcmContext + chapol* {.importc: "chapol".}: SslrecChapolContext + ccm* {.importc: "ccm".}: SslrecCcmContext + + INNER_C_STRUCT_bearssl_ssl_19* {.importc: "br_ssl_engine_context::no_name", + header: "bearssl_ssl.h", bycopy.} = object + dp* {.importc: "dp".}: ptr uint32 + rp* {.importc: "rp".}: ptr uint32 + ip* {.importc: "ip".}: ptr byte + + SslEngineContext* {.importc: "br_ssl_engine_context", header: "bearssl_ssl.h", + bycopy.} = object + err* {.importc: "err".}: cint + ibuf* {.importc: "ibuf".}: ptr byte + obuf* {.importc: "obuf".}: ptr byte + ibufLen* {.importc: "ibuf_len".}: uint + obufLen* {.importc: "obuf_len".}: uint + maxFragLen* {.importc: "max_frag_len".}: uint16 + logMaxFragLen* {.importc: "log_max_frag_len".}: byte + peerLogMaxFragLen* {.importc: "peer_log_max_frag_len".}: byte + ixa* {.importc: "ixa".}: uint + ixb* {.importc: "ixb".}: uint + ixc* {.importc: "ixc".}: uint + oxa* {.importc: "oxa".}: uint + oxb* {.importc: "oxb".}: uint + oxc* {.importc: "oxc".}: uint + iomode* {.importc: "iomode".}: byte + incrypt* {.importc: "incrypt".}: byte + shutdownRecv* {.importc: "shutdown_recv".}: byte + recordTypeIn* {.importc: "record_type_in".}: byte + recordTypeOut* {.importc: "record_type_out".}: byte + versionIn* {.importc: "version_in".}: uint16 + versionOut* {.importc: "version_out".}: uint16 + `in`* {.importc: "in".}: INNER_C_UNION_bearssl_ssl_17 + `out`* {.importc: "out".}: INNER_C_UNION_bearssl_ssl_18 + applicationData* {.importc: "application_data".}: byte + rng* {.importc: "rng".}: HmacDrbgContext + rngInitDone* {.importc: "rng_init_done".}: cint + rngOsRandDone* {.importc: "rng_os_rand_done".}: cint + versionMin* {.importc: "version_min".}: uint16 + versionMax* {.importc: "version_max".}: uint16 + suitesBuf* {.importc: "suites_buf".}: array[MAX_CIPHER_SUITES, uint16] + suitesNum* {.importc: "suites_num".}: byte + serverName* {.importc: "server_name".}: array[256, char] + clientRandom* {.importc: "client_random".}: array[32, byte] + serverRandom* {.importc: "server_random".}: array[32, byte] + session* {.importc: "session".}: SslSessionParameters + ecdheCurve* {.importc: "ecdhe_curve".}: byte + ecdhePoint* {.importc: "ecdhe_point".}: array[133, byte] + ecdhePointLen* {.importc: "ecdhe_point_len".}: byte + reneg* {.importc: "reneg".}: byte + savedFinished* {.importc: "saved_finished".}: array[24, byte] + flags* {.importc: "flags".}: uint32 + cpu* {.importc: "cpu".}: INNER_C_STRUCT_bearssl_ssl_19 + dpStack* {.importc: "dp_stack".}: array[32, uint32] + rpStack* {.importc: "rp_stack".}: array[32, uint32] + pad* {.importc: "pad".}: array[512, byte] + hbufIn* {.importc: "hbuf_in".}: ptr byte + hbufOut* {.importc: "hbuf_out".}: ptr byte + savedHbufOut* {.importc: "saved_hbuf_out".}: ptr byte + hlenIn* {.importc: "hlen_in".}: uint + hlenOut* {.importc: "hlen_out".}: uint + hsrun* {.importc: "hsrun".}: proc (ctx: pointer) {.importcFunc.} + action* {.importc: "action".}: byte + alert* {.importc: "alert".}: byte + closeReceived* {.importc: "close_received".}: byte + mhash* {.importc: "mhash".}: MultihashContext + x509ctx* {.importc: "x509ctx".}: ptr ptr X509Class + chain* {.importc: "chain".}: ptr X509Certificate + chainLen* {.importc: "chain_len".}: uint + certCur* {.importc: "cert_cur".}: ptr byte + certLen* {.importc: "cert_len".}: uint + protocolNames* {.importc: "protocol_names".}: cstringArray + protocolNamesNum* {.importc: "protocol_names_num".}: uint16 + selectedProtocol* {.importc: "selected_protocol".}: uint16 + prf10* {.importc: "prf10".}: TlsPrfImpl + prfSha256* {.importc: "prf_sha256".}: TlsPrfImpl + prfSha384* {.importc: "prf_sha384".}: TlsPrfImpl + iaesCbcenc* {.importc: "iaes_cbcenc".}: ptr BlockCbcencClass + iaesCbcdec* {.importc: "iaes_cbcdec".}: ptr BlockCbcdecClass + iaesCtr* {.importc: "iaes_ctr".}: ptr BlockCtrClass + iaesCtrcbc* {.importc: "iaes_ctrcbc".}: ptr BlockCtrcbcClass + idesCbcenc* {.importc: "ides_cbcenc".}: ptr BlockCbcencClass + idesCbcdec* {.importc: "ides_cbcdec".}: ptr BlockCbcdecClass + ighash* {.importc: "ighash".}: Ghash + ichacha* {.importc: "ichacha".}: Chacha20Run + ipoly* {.importc: "ipoly".}: Poly1305Run + icbcIn* {.importc: "icbc_in".}: ptr SslrecInCbcClass + icbcOut* {.importc: "icbc_out".}: ptr SslrecOutCbcClass + igcmIn* {.importc: "igcm_in".}: ptr SslrecInGcmClass + igcmOut* {.importc: "igcm_out".}: ptr SslrecOutGcmClass + ichapolIn* {.importc: "ichapol_in".}: ptr SslrecInChapolClass + ichapolOut* {.importc: "ichapol_out".}: ptr SslrecOutChapolClass + iccmIn* {.importc: "iccm_in".}: ptr SslrecInCcmClass + iccmOut* {.importc: "iccm_out".}: ptr SslrecOutCcmClass + iec* {.importc: "iec".}: ptr EcImpl + irsavrfy* {.importc: "irsavrfy".}: RsaPkcs1Vrfy + iecdsa* {.importc: "iecdsa".}: EcdsaVrfy + + + +proc sslEngineGetFlags*(cc: var SslEngineContext): uint32 {.inline.} = + return cc.flags + +proc sslEngineSetAllFlags*(cc: var SslEngineContext; flags: uint32) {.inline.} = + cc.flags = flags + +proc sslEngineAddFlags*(cc: var SslEngineContext; flags: uint32) {.inline.} = + cc.flags = cc.flags or flags + +proc sslEngineRemoveFlags*(cc: var SslEngineContext; flags: uint32) {.inline.} = + cc.flags = cc.flags and not flags + + +const + OPT_ENFORCE_SERVER_PREFERENCES* = (1'u32 shl 0) + +const + OPT_NO_RENEGOTIATION* = (1'u32 shl 1) + +const + OPT_TOLERATE_NO_CLIENT_AUTH* = (1'u32 shl 2) + +const + OPT_FAIL_ON_ALPN_MISMATCH* = (1'u32 shl 3) + +proc sslEngineSetVersions*(cc: var SslEngineContext; versionMin: uint16; + versionMax: uint16) {.inline.} = + cc.versionMin = versionMin + cc.versionMax = versionMax + +proc sslEngineSetSuites*(cc: var SslEngineContext; suites: ptr uint16; + suitesNum: uint) {.importcFunc, + importc: "br_ssl_engine_set_suites", header: "bearssl_ssl.h".} + +proc sslEngineSetX509*(cc: var SslEngineContext; x509ctx: ptr ptr X509Class) {.inline, + importcFunc.} = + cc.x509ctx = x509ctx + + +proc sslEngineSetProtocolNames*(ctx: var SslEngineContext; names: cstringArray; + num: uint) {.inline.} = + ctx.protocolNames = names + ctx.protocolNamesNum = uint16 num + +proc sslEngineGetSelectedProtocol*(ctx: var SslEngineContext): cstring {.inline.} = + var k: cuint + k = ctx.selectedProtocol + return if (k == 0 or k == 0xFFFF): nil else: ctx.protocolNames[k - 1] + + +proc sslEngineSetHash*(ctx: var SslEngineContext; id: cint; impl: ptr HashClass) {. + inline.} = + multihashSetimpl(ctx.mhash, id, impl) + + +proc sslEngineGetHash*(ctx: var SslEngineContext; id: cint): ptr HashClass {.inline, + importcFunc.} = + return multihashGetimpl(ctx.mhash, id) + + +proc sslEngineSetPrf10*(cc: var SslEngineContext; impl: TlsPrfImpl) {.inline.} = + cc.prf10 = impl + + +proc sslEngineSetPrfSha256*(cc: var SslEngineContext; impl: TlsPrfImpl) {.inline.} = + cc.prfSha256 = impl + + +proc sslEngineSetPrfSha384*(cc: var SslEngineContext; impl: TlsPrfImpl) {.inline.} = + cc.prfSha384 = impl + + +proc sslEngineSetAesCbc*(cc: var SslEngineContext; implEnc: ptr BlockCbcencClass; + implDec: ptr BlockCbcdecClass) {.inline.} = + cc.iaesCbcenc = implEnc + cc.iaesCbcdec = implDec + + +proc sslEngineSetDefaultAesCbc*(cc: var SslEngineContext) {.importcFunc, + importc: "br_ssl_engine_set_default_aes_cbc", header: "bearssl_ssl.h".} + +proc sslEngineSetAesCtr*(cc: var SslEngineContext; impl: ptr BlockCtrClass) {.inline, + importcFunc.} = + cc.iaesCtr = impl + + +proc sslEngineSetDefaultAesGcm*(cc: var SslEngineContext) {.importcFunc, + importc: "br_ssl_engine_set_default_aes_gcm", header: "bearssl_ssl.h".} + +proc sslEngineSetDesCbc*(cc: var SslEngineContext; implEnc: ptr BlockCbcencClass; + implDec: ptr BlockCbcdecClass) {.inline.} = + cc.idesCbcenc = implEnc + cc.idesCbcdec = implDec + + +proc sslEngineSetDefaultDesCbc*(cc: var SslEngineContext) {.importcFunc, + importc: "br_ssl_engine_set_default_des_cbc", header: "bearssl_ssl.h".} + +proc sslEngineSetGhash*(cc: var SslEngineContext; impl: Ghash) {.inline.} = + cc.ighash = impl + + +proc sslEngineSetChacha20*(cc: var SslEngineContext; ichacha: Chacha20Run) {.inline, + importcFunc.} = + cc.ichacha = ichacha + + +proc sslEngineSetPoly1305*(cc: var SslEngineContext; ipoly: Poly1305Run) {.inline, + importcFunc.} = + cc.ipoly = ipoly + + +proc sslEngineSetDefaultChapol*(cc: var SslEngineContext) {.importcFunc, + importc: "br_ssl_engine_set_default_chapol", header: "bearssl_ssl.h".} + +proc sslEngineSetAesCtrcbc*(cc: var SslEngineContext; impl: ptr BlockCtrcbcClass) {. + inline.} = + cc.iaesCtrcbc = impl + + +proc sslEngineSetDefaultAesCcm*(cc: var SslEngineContext) {.importcFunc, + importc: "br_ssl_engine_set_default_aes_ccm", header: "bearssl_ssl.h".} + +proc sslEngineSetCbc*(cc: var SslEngineContext; implIn: ptr SslrecInCbcClass; + implOut: ptr SslrecOutCbcClass) {.inline.} = + cc.icbcIn = implIn + cc.icbcOut = implOut + + +proc sslEngineSetGcm*(cc: var SslEngineContext; implIn: ptr SslrecInGcmClass; + implOut: ptr SslrecOutGcmClass) {.inline.} = + cc.igcmIn = implIn + cc.igcmOut = implOut + + +proc sslEngineSetCcm*(cc: var SslEngineContext; implIn: ptr SslrecInCcmClass; + implOut: ptr SslrecOutCcmClass) {.inline.} = + cc.iccmIn = implIn + cc.iccmOut = implOut + + +proc sslEngineSetChapol*(cc: var SslEngineContext; implIn: ptr SslrecInChapolClass; + implOut: ptr SslrecOutChapolClass) {.inline.} = + cc.ichapolIn = implIn + cc.ichapolOut = implOut + +proc sslEngineSetEc*(cc: var SslEngineContext; iec: ptr EcImpl) {.inline.} = + cc.iec = iec + + +proc sslEngineSetDefaultEc*(cc: var SslEngineContext) {.importcFunc, + importc: "br_ssl_engine_set_default_ec", header: "bearssl_ssl.h".} + +proc sslEngineGetEc*(cc: var SslEngineContext): ptr EcImpl {.inline.} = + return cc.iec + + +proc sslEngineSetRsavrfy*(cc: var SslEngineContext; irsavrfy: RsaPkcs1Vrfy) {.inline, + importcFunc.} = + cc.irsavrfy = irsavrfy + + +proc sslEngineSetDefaultRsavrfy*(cc: var SslEngineContext) {.importcFunc, + importc: "br_ssl_engine_set_default_rsavrfy", header: "bearssl_ssl.h".} + +proc sslEngineGetRsavrfy*(cc: var SslEngineContext): RsaPkcs1Vrfy {.inline.} = + return cc.irsavrfy + +proc sslEngineSetEcdsa*(cc: var SslEngineContext; iecdsa: EcdsaVrfy) {.inline.} = + cc.iecdsa = iecdsa + + +proc sslEngineSetDefaultEcdsa*(cc: var SslEngineContext) {.importcFunc, + importc: "br_ssl_engine_set_default_ecdsa", header: "bearssl_ssl.h".} + +proc sslEngineGetEcdsa*(cc: var SslEngineContext): EcdsaVrfy {.inline.} = + return cc.iecdsa + + +proc sslEngineSetBuffer*(cc: var SslEngineContext; iobuf: pointer; iobufLen: uint; + bidi: cint) {.importcFunc, importc: "br_ssl_engine_set_buffer", + header: "bearssl_ssl.h".} + +proc sslEngineSetBuffersBidi*(cc: var SslEngineContext; ibuf: pointer; + ibufLen: uint; obuf: pointer; obufLen: uint) {. + importcFunc, importc: "br_ssl_engine_set_buffers_bidi", header: "bearssl_ssl.h".} + +proc sslEngineInjectEntropy*(cc: var SslEngineContext; data: pointer; len: uint) {. + importcFunc, importc: "br_ssl_engine_inject_entropy", header: "bearssl_ssl.h".} + +proc sslEngineGetServerName*(cc: var SslEngineContext): cstring {.inline.} = + return addr cc.serverName + + +proc sslEngineGetVersion*(cc: var SslEngineContext): cuint {.inline.} = + return cc.session.version + + +proc sslEngineGetSessionParameters*(cc: var SslEngineContext; + pp: ptr SslSessionParameters) {.inline.} = + copyMem(pp, addr(cc.session), sizeof(pp[])) + +proc sslEngineSetSessionParameters*(cc: var SslEngineContext; + pp: ptr SslSessionParameters) {.inline.} = + copyMem(addr(cc.session), pp, sizeof(pp[])) + + +proc sslEngineGetEcdheCurve*(cc: var SslEngineContext): cint {.inline.} = + return cint cc.ecdheCurve + + +proc sslEngineCurrentState*(cc: var SslEngineContext): cuint {.importcFunc, + importc: "br_ssl_engine_current_state", header: "bearssl_ssl.h".} + +const + SSL_CLOSED* = 0x0001 + + +const + SSL_SENDREC* = 0x0002 + + +const + SSL_RECVREC* = 0x0004 + + +const + SSL_SENDAPP* = 0x0008 + + +const + SSL_RECVAPP* = 0x0010 + +proc sslEngineLastError*(cc: var SslEngineContext): cint {.inline.} = + return cc.err + + +proc sslEngineSendappBuf*(cc: var SslEngineContext; len: var uint): ptr byte {. + importcFunc, importc: "br_ssl_engine_sendapp_buf", header: "bearssl_ssl.h".} + +proc sslEngineSendappAck*(cc: var SslEngineContext; len: uint) {.importcFunc, + importc: "br_ssl_engine_sendapp_ack", header: "bearssl_ssl.h".} + +proc sslEngineRecvappBuf*(cc: var SslEngineContext; len: var uint): ptr byte {. + importcFunc, importc: "br_ssl_engine_recvapp_buf", header: "bearssl_ssl.h".} + +proc sslEngineRecvappAck*(cc: var SslEngineContext; len: uint) {.importcFunc, + importc: "br_ssl_engine_recvapp_ack", header: "bearssl_ssl.h".} + +proc sslEngineSendrecBuf*(cc: var SslEngineContext; len: var uint): ptr byte {. + importcFunc, importc: "br_ssl_engine_sendrec_buf", header: "bearssl_ssl.h".} + +proc sslEngineSendrecAck*(cc: var SslEngineContext; len: uint) {.importcFunc, + importc: "br_ssl_engine_sendrec_ack", header: "bearssl_ssl.h".} + +proc sslEngineRecvrecBuf*(cc: var SslEngineContext; len: var uint): ptr byte {. + importcFunc, importc: "br_ssl_engine_recvrec_buf", header: "bearssl_ssl.h".} + +proc sslEngineRecvrecAck*(cc: var SslEngineContext; len: uint) {.importcFunc, + importc: "br_ssl_engine_recvrec_ack", header: "bearssl_ssl.h".} + +proc sslEngineFlush*(cc: var SslEngineContext; force: cint) {.importcFunc, + importc: "br_ssl_engine_flush", header: "bearssl_ssl.h".} + +proc sslEngineClose*(cc: var SslEngineContext) {.importcFunc, + importc: "br_ssl_engine_close", header: "bearssl_ssl.h".} + +proc sslEngineRenegotiate*(cc: var SslEngineContext): cint {.importcFunc, + importc: "br_ssl_engine_renegotiate", header: "bearssl_ssl.h".} + +proc sslKeyExport*(cc: var SslEngineContext; dst: pointer; len: uint; label: cstring; + context: pointer; contextLen: uint): cint {.importcFunc, + importc: "br_ssl_key_export", header: "bearssl_ssl.h".} + +type + SslClientCertificate* {.importc: "br_ssl_client_certificate", + header: "bearssl_ssl.h", bycopy.} = object + authType* {.importc: "auth_type".}: cint + hashId* {.importc: "hash_id".}: cint + chain* {.importc: "chain".}: ptr X509Certificate + chainLen* {.importc: "chain_len".}: uint + + + +const + AUTH_ECDH* = 0 + + +const + AUTH_RSA* = 1 + + +const + AUTH_ECDSA* = 3 + + +type + SslClientCertificateClass* {.importc: "br_ssl_client_certificate_class", + header: "bearssl_ssl.h", bycopy.} = object + contextSize* {.importc: "context_size".}: uint + startNameList* {.importc: "start_name_list".}: proc ( + pctx: ptr ptr SslClientCertificateClass) {.importcFunc.} + startName* {.importc: "start_name".}: proc ( + pctx: ptr ptr SslClientCertificateClass; len: uint) {.importcFunc.} + appendName* {.importc: "append_name".}: proc ( + pctx: ptr ptr SslClientCertificateClass; data: ptr byte; len: uint) {.importcFunc.} + endName* {.importc: "end_name".}: proc (pctx: ptr ptr SslClientCertificateClass) {. + importcFunc.} + endNameList* {.importc: "end_name_list".}: proc ( + pctx: ptr ptr SslClientCertificateClass) {.importcFunc.} + choose* {.importc: "choose".}: proc (pctx: ptr ptr SslClientCertificateClass; + cc: var SslClientContext; authTypes: uint32; + choices: ptr SslClientCertificate) {.importcFunc.} + doKeyx* {.importc: "do_keyx".}: proc (pctx: ptr ptr SslClientCertificateClass; + data: ptr byte; len: var uint): uint32 {. + importcFunc.} + doSign* {.importc: "do_sign".}: proc (pctx: ptr ptr SslClientCertificateClass; + hashId: cint; hvLen: uint; + data: ptr byte; len: uint): uint {.importcFunc.} + + + + SslClientCertificateRsaContext* {.importc: "br_ssl_client_certificate_rsa_context", + header: "bearssl_ssl.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr SslClientCertificateClass + chain* {.importc: "chain".}: ptr X509Certificate + chainLen* {.importc: "chain_len".}: uint + sk* {.importc: "sk".}: ptr RsaPrivateKey + irsasign* {.importc: "irsasign".}: RsaPkcs1Sign + + + + SslClientCertificateEcContext* {.importc: "br_ssl_client_certificate_ec_context", + header: "bearssl_ssl.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr SslClientCertificateClass + chain* {.importc: "chain".}: ptr X509Certificate + chainLen* {.importc: "chain_len".}: uint + sk* {.importc: "sk".}: ptr EcPrivateKey + allowedUsages* {.importc: "allowed_usages".}: cuint + issuerKeyType* {.importc: "issuer_key_type".}: cuint + mhash* {.importc: "mhash".}: ptr MultihashContext + iec* {.importc: "iec".}: ptr EcImpl + iecdsa* {.importc: "iecdsa".}: EcdsaSign + + + + + INNER_C_UNION_bearssl_ssl_20* {.importc: "no_name", header: "bearssl_ssl.h", + bycopy, union.} = object + vtable* {.importc: "vtable".}: ptr SslClientCertificateClass + singleRsa* {.importc: "single_rsa".}: SslClientCertificateRsaContext + singleEc* {.importc: "single_ec".}: SslClientCertificateEcContext + + SslClientContext* {.importc: "br_ssl_client_context", header: "bearssl_ssl.h", + bycopy.} = object + eng* {.importc: "eng".}: SslEngineContext + minClienthelloLen* {.importc: "min_clienthello_len".}: uint16 + hashes* {.importc: "hashes".}: uint32 + serverCurve* {.importc: "server_curve".}: cint + clientAuthVtable* {.importc: "client_auth_vtable".}: ptr ptr SslClientCertificateClass + authType* {.importc: "auth_type".}: byte + hashId* {.importc: "hash_id".}: byte + clientAuth* {.importc: "client_auth".}: INNER_C_UNION_bearssl_ssl_20 + irsapub* {.importc: "irsapub".}: RsaPublic + + + +proc sslClientGetServerHashes*(cc: var SslClientContext): uint32 {.inline.} = + return cc.hashes + +proc sslClientGetServerCurve*(cc: var SslClientContext): cint {.inline.} = + return cc.serverCurve + + +proc sslClientInitFull*(cc: var SslClientContext; xc: ptr X509MinimalContext; + trustAnchors: ptr X509TrustAnchor; trustAnchorsNum: uint) {. + importcFunc, importc: "br_ssl_client_init_full", header: "bearssl_ssl.h".} + +proc sslClientZero*(cc: var SslClientContext) {.importcFunc, importc: "br_ssl_client_zero", + header: "bearssl_ssl.h".} + +proc sslClientSetClientCertificate*(cc: var SslClientContext; + pctx: ptr ptr SslClientCertificateClass) {. + inline.} = + cc.clientAuthVtable = pctx + + +proc sslClientSetRsapub*(cc: var SslClientContext; irsapub: RsaPublic) {.inline.} = + cc.irsapub = irsapub + + +proc sslClientSetDefaultRsapub*(cc: var SslClientContext) {.importcFunc, + importc: "br_ssl_client_set_default_rsapub", header: "bearssl_ssl.h".} + +proc sslClientSetMinClienthelloLen*(cc: var SslClientContext; len: uint16) {.inline, + importcFunc.} = + cc.minClienthelloLen = len + + +proc sslClientReset*(cc: var SslClientContext; serverName: cstring; + resumeSession: cint): cint {.importcFunc, + importc: "br_ssl_client_reset", header: "bearssl_ssl.h".} + +proc sslClientForgetSession*(cc: var SslClientContext) {.inline.} = + cc.eng.session.sessionIdLen = byte(0) + + +proc sslClientSetSingleRsa*(cc: var SslClientContext; chain: ptr X509Certificate; + chainLen: int; sk: ptr RsaPrivateKey; + irsasign: RsaPkcs1Sign) {.importcFunc, + importc: "br_ssl_client_set_single_rsa", header: "bearssl_ssl.h".} + +proc sslClientSetSingleEc*(cc: var SslClientContext; chain: ptr X509Certificate; + chainLen: int; sk: ptr EcPrivateKey; + allowedUsages: cuint; certIssuerKeyType: cuint; + iec: ptr EcImpl; iecdsa: EcdsaSign) {.importcFunc, + importc: "br_ssl_client_set_single_ec", header: "bearssl_ssl.h".} + +type + SuiteTranslated* = array[2, uint16] + + +const + SSLKEYX_RSA* = 0 + SSLKEYX_ECDHE_RSA* = 1 + SSLKEYX_ECDHE_ECDSA* = 2 + SSLKEYX_ECDH_RSA* = 3 + SSLKEYX_ECDH_ECDSA* = 4 + SSLENC_3DES_CBC* = 0 + SSLENC_AES128_CBC* = 1 + SSLENC_AES256_CBC* = 2 + SSLENC_AES128_GCM* = 3 + SSLENC_AES256_GCM* = 4 + SSLENC_CHACHA20* = 5 + SSLMAC_AEAD* = 0 + SSLMAC_SHA1* = sha1ID + SSLMAC_SHA256* = sha256ID + SSLMAC_SHA384* = sha384ID + SSLPRF_SHA256* = sha256ID + SSLPRF_SHA384* = sha384ID + +type + SslServerChoices* {.importc: "br_ssl_server_choices", header: "bearssl_ssl.h", + bycopy.} = object + cipherSuite* {.importc: "cipher_suite".}: uint16 + algoId* {.importc: "algo_id".}: cuint + chain* {.importc: "chain".}: ptr X509Certificate + chainLen* {.importc: "chain_len".}: uint + + + +type + SslServerPolicyClass* {.importc: "br_ssl_server_policy_class", + header: "bearssl_ssl.h", bycopy.} = object + contextSize* {.importc: "context_size".}: uint + choose* {.importc: "choose".}: proc (pctx: ptr ptr SslServerPolicyClass; + cc: var SslServerContext; + choices: ptr SslServerChoices): cint {.importcFunc.} + doKeyx* {.importc: "do_keyx".}: proc (pctx: ptr ptr SslServerPolicyClass; + data: ptr byte; len: var uint): uint32 {. + importcFunc.} + doSign* {.importc: "do_sign".}: proc (pctx: ptr ptr SslServerPolicyClass; + algoId: cuint; data: ptr byte; + hvLen: uint; len: uint): uint {.importcFunc.} + + + + + SslServerPolicyRsaContext* {.importc: "br_ssl_server_policy_rsa_context", + header: "bearssl_ssl.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr SslServerPolicyClass + chain* {.importc: "chain".}: ptr X509Certificate + chainLen* {.importc: "chain_len".}: uint + sk* {.importc: "sk".}: ptr RsaPrivateKey + allowedUsages* {.importc: "allowed_usages".}: cuint + irsacore* {.importc: "irsacore".}: RsaPrivate + irsasign* {.importc: "irsasign".}: RsaPkcs1Sign + + + + + SslServerPolicyEcContext* {.importc: "br_ssl_server_policy_ec_context", + header: "bearssl_ssl.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr SslServerPolicyClass + chain* {.importc: "chain".}: ptr X509Certificate + chainLen* {.importc: "chain_len".}: uint + sk* {.importc: "sk".}: ptr EcPrivateKey + allowedUsages* {.importc: "allowed_usages".}: cuint + certIssuerKeyType* {.importc: "cert_issuer_key_type".}: cuint + mhash* {.importc: "mhash".}: ptr MultihashContext + iec* {.importc: "iec".}: ptr EcImpl + iecdsa* {.importc: "iecdsa".}: EcdsaSign + + + + SslSessionCacheClass* {.importc: "br_ssl_session_cache_class", + header: "bearssl_ssl.h", bycopy.} = object + contextSize* {.importc: "context_size".}: uint + save* {.importc: "save".}: proc (ctx: ptr ptr SslSessionCacheClass; + serverCtx: ptr SslServerContext; + params: ptr SslSessionParameters) {.importcFunc.} + load* {.importc: "load".}: proc (ctx: ptr ptr SslSessionCacheClass; + serverCtx: ptr SslServerContext; + params: ptr SslSessionParameters): cint {.importcFunc.} + + + + + SslSessionCacheLru* {.importc: "br_ssl_session_cache_lru", + header: "bearssl_ssl.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr SslSessionCacheClass + store* {.importc: "store".}: ptr byte + storeLen* {.importc: "store_len".}: uint + storePtr* {.importc: "store_ptr".}: uint + indexKey* {.importc: "index_key".}: array[32, byte] + hash* {.importc: "hash".}: ptr HashClass + initDone* {.importc: "init_done".}: cint + head* {.importc: "head".}: uint32 + tail* {.importc: "tail".}: uint32 + root* {.importc: "root".}: uint32 + + + + INNER_C_UNION_bearssl_ssl_21* {.importc: "no_name", header: "bearssl_ssl.h", + bycopy, union.} = object + vtable* {.importc: "vtable".}: ptr SslServerPolicyClass + singleRsa* {.importc: "single_rsa".}: SslServerPolicyRsaContext + singleEc* {.importc: "single_ec".}: SslServerPolicyEcContext + + SslServerContext* {.importc: "br_ssl_server_context", header: "bearssl_ssl.h", + bycopy.} = object + eng* {.importc: "eng".}: SslEngineContext + clientMaxVersion* {.importc: "client_max_version".}: uint16 + cacheVtable* {.importc: "cache_vtable".}: ptr ptr SslSessionCacheClass + clientSuites* {.importc: "client_suites".}: array[MAX_CIPHER_SUITES, + SuiteTranslated] + clientSuitesNum* {.importc: "client_suites_num".}: byte + hashes* {.importc: "hashes".}: uint32 + curves* {.importc: "curves".}: uint32 + policyVtable* {.importc: "policy_vtable".}: ptr ptr SslServerPolicyClass + signHashId* {.importc: "sign_hash_id".}: uint16 + chainHandler* {.importc: "chain_handler".}: INNER_C_UNION_bearssl_ssl_21 + ecdheKey* {.importc: "ecdhe_key".}: array[70, byte] + ecdheKeyLen* {.importc: "ecdhe_key_len".}: uint + taNames* {.importc: "ta_names".}: ptr X500Name + tas* {.importc: "tas".}: ptr X509TrustAnchor + numTas* {.importc: "num_tas".}: uint + curDnIndex* {.importc: "cur_dn_index".}: uint + curDn* {.importc: "cur_dn".}: ptr byte + curDnLen* {.importc: "cur_dn_len".}: uint + hashCV* {.importc: "hash_CV".}: array[64, byte] + hashCV_len* {.importc: "hash_CV_len".}: uint + hashCV_id* {.importc: "hash_CV_id".}: cint + +proc sslSessionCacheLruInit*(cc: var SslSessionCacheLru; store: ptr cuchar; + storeLen: int) {.importcFunc, + importc: "br_ssl_session_cache_lru_init", header: "bearssl_ssl.h".} + +proc sslSessionCacheLruForget*(cc: var SslSessionCacheLru; id: ptr cuchar) {.importcFunc, + importc: "br_ssl_session_cache_lru_forget", header: "bearssl_ssl.h".} + + + + +proc sslServerInitFullRsa*(cc: var SslServerContext; chain: ptr X509Certificate; + chainLen: uint; sk: ptr RsaPrivateKey) {.importcFunc, + importc: "br_ssl_server_init_full_rsa", header: "bearssl_ssl.h".} + +proc sslServerInitFullEc*(cc: var SslServerContext; chain: ptr X509Certificate; + chainLen: uint; certIssuerKeyType: cuint; + sk: ptr EcPrivateKey) {.importcFunc, + importc: "br_ssl_server_init_full_ec", header: "bearssl_ssl.h".} + +proc sslServerInitMinr2g*(cc: var SslServerContext; chain: ptr X509Certificate; + chainLen: uint; sk: ptr RsaPrivateKey) {.importcFunc, + importc: "br_ssl_server_init_minr2g", header: "bearssl_ssl.h".} + +proc sslServerInitMine2g*(cc: var SslServerContext; chain: ptr X509Certificate; + chainLen: uint; sk: ptr RsaPrivateKey) {.importcFunc, + importc: "br_ssl_server_init_mine2g", header: "bearssl_ssl.h".} + +proc sslServerInitMinf2g*(cc: var SslServerContext; chain: ptr X509Certificate; + chainLen: uint; sk: ptr EcPrivateKey) {.importcFunc, + importc: "br_ssl_server_init_minf2g", header: "bearssl_ssl.h".} + +proc sslServerInitMinu2g*(cc: var SslServerContext; chain: ptr X509Certificate; + chainLen: uint; sk: ptr EcPrivateKey) {.importcFunc, + importc: "br_ssl_server_init_minu2g", header: "bearssl_ssl.h".} + +proc sslServerInitMinv2g*(cc: var SslServerContext; chain: ptr X509Certificate; + chainLen: uint; sk: ptr EcPrivateKey) {.importcFunc, + importc: "br_ssl_server_init_minv2g", header: "bearssl_ssl.h".} + +proc sslServerInitMine2c*(cc: var SslServerContext; chain: ptr X509Certificate; + chainLen: uint; sk: ptr RsaPrivateKey) {.importcFunc, + importc: "br_ssl_server_init_mine2c", header: "bearssl_ssl.h".} + +proc sslServerInitMinf2c*(cc: var SslServerContext; chain: ptr X509Certificate; + chainLen: uint; sk: ptr EcPrivateKey) {.importcFunc, + importc: "br_ssl_server_init_minf2c", header: "bearssl_ssl.h".} + +proc sslServerGetClientSuites*(cc: var SslServerContext; num: ptr uint): + ptr array[MAX_CIPHER_SUITES, SuiteTranslated] {. + inline.} = + num[] = cc.clientSuitesNum + return addr cc.clientSuites + + +proc sslServerGetClientHashes*(cc: var SslServerContext): uint32 {.inline.} = + return cc.hashes + + +proc sslServerGetClientCurves*(cc: var SslServerContext): uint32 {.inline.} = + return cc.curves + + +proc sslServerZero*(cc: var SslServerContext) {.importcFunc, importc: "br_ssl_server_zero", + header: "bearssl_ssl.h".} + +proc sslServerSetPolicy*(cc: var SslServerContext; + pctx: ptr ptr SslServerPolicyClass) {.inline.} = + cc.policyVtable = pctx + + +proc sslServerSetSingleRsa*(cc: var SslServerContext; chain: ptr X509Certificate; + chainLen: uint; sk: ptr RsaPrivateKey; + allowedUsages: cuint; irsacore: RsaPrivate; + irsasign: RsaPkcs1Sign) {.importcFunc, + importc: "br_ssl_server_set_single_rsa", header: "bearssl_ssl.h".} + +proc sslServerSetSingleEc*(cc: var SslServerContext; chain: ptr X509Certificate; + chainLen: uint; sk: ptr EcPrivateKey; + allowedUsages: cuint; certIssuerKeyType: cuint; + iec: ptr EcImpl; iecdsa: EcdsaSign) {.importcFunc, + importc: "br_ssl_server_set_single_ec", header: "bearssl_ssl.h".} + +proc sslServerSetTrustAnchorNames*(cc: var SslServerContext; taNames: ptr X500Name; + num: uint) {.inline.} = + cc.taNames = taNames + cc.tas = nil + cc.numTas = num + + +proc sslServerSetTrustAnchorNamesAlt*(cc: var SslServerContext; + tas: ptr X509TrustAnchor; num: uint) {.inline.} = + cc.taNames = nil + cc.tas = tas + cc.numTas = num + + +proc sslServerSetCache*(cc: var SslServerContext; + vtable: ptr ptr SslSessionCacheClass) {.inline.} = + cc.cacheVtable = vtable + + +proc sslServerReset*(cc: var SslServerContext): cint {.importcFunc, + importc: "br_ssl_server_reset", header: "bearssl_ssl.h".} + +type + SslioContext* {.importc: "br_sslio_context", header: "bearssl_ssl.h", bycopy.} = object + engine* {.importc: "engine".}: ptr SslEngineContext + lowRead* {.importc: "low_read".}: proc (readContext: pointer; data: ptr byte; + len: uint): cint {.importcFunc.} + readContext* {.importc: "read_context".}: pointer + lowWrite* {.importc: "low_write".}: proc (writeContext: pointer; data: ptr byte; + len: uint): cint {.importcFunc.} + writeContext* {.importc: "write_context".}: pointer + + + +proc sslioInit*(ctx: var SslioContext; engine: ptr SslEngineContext; lowRead: proc ( + readContext: pointer; data: ptr byte; len: uint): cint {.importcFunc.}; + readContext: pointer; lowWrite: proc (writeContext: pointer; + data: ptr byte; len: uint): cint {.importcFunc.}; writeContext: pointer) {.importcFunc, + importc: "br_sslio_init", header: "bearssl_ssl.h".} + +proc sslioRead*(cc: var SslioContext; dst: pointer; len: uint): cint {.importcFunc, + importc: "br_sslio_read", header: "bearssl_ssl.h".} + +proc sslioReadAll*(cc: var SslioContext; dst: pointer; len: uint): cint {.importcFunc, + importc: "br_sslio_read_all", header: "bearssl_ssl.h".} + +proc sslioWrite*(cc: var SslioContext; src: pointer; len: uint): cint {.importcFunc, + importc: "br_sslio_write", header: "bearssl_ssl.h".} + +proc sslioWriteAll*(cc: var SslioContext; src: pointer; len: uint): cint {.importcFunc, + importc: "br_sslio_write_all", header: "bearssl_ssl.h".} + +proc sslioFlush*(cc: var SslioContext): cint {.importcFunc, importc: "br_sslio_flush", + header: "bearssl_ssl.h".} + +proc sslioClose*(cc: var SslioContext): cint {.importcFunc, importc: "br_sslio_close", + header: "bearssl_ssl.h".} + +const + TLS_NULL_WITH_NULL_NULL* = 0x0000 + TLS_RSA_WITH_NULL_MD5* = 0x0001 + TLS_RSA_WITH_NULL_SHA* = 0x0002 + TLS_RSA_WITH_NULL_SHA256* = 0x003B + TLS_RSA_WITH_RC4_128_MD5* = 0x0004 + TLS_RSA_WITH_RC4_128_SHA* = 0x0005 + TLS_RSA_WITH_3DES_EDE_CBC_SHA* = 0x000A + TLS_RSA_WITH_AES_128_CBC_SHA* = 0x002F + TLS_RSA_WITH_AES_256_CBC_SHA* = 0x0035 + TLS_RSA_WITH_AES_128_CBC_SHA256* = 0x003C + TLS_RSA_WITH_AES_256_CBC_SHA256* = 0x003D + TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA* = 0x000D + TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA* = 0x0010 + TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA* = 0x0013 + TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA* = 0x0016 + TLS_DH_DSS_WITH_AES_128_CBC_SHA* = 0x0030 + TLS_DH_RSA_WITH_AES_128_CBC_SHA* = 0x0031 + TLS_DHE_DSS_WITH_AES_128_CBC_SHA* = 0x0032 + TLS_DHE_RSA_WITH_AES_128_CBC_SHA* = 0x0033 + TLS_DH_DSS_WITH_AES_256_CBC_SHA* = 0x0036 + TLS_DH_RSA_WITH_AES_256_CBC_SHA* = 0x0037 + TLS_DHE_DSS_WITH_AES_256_CBC_SHA* = 0x0038 + TLS_DHE_RSA_WITH_AES_256_CBC_SHA* = 0x0039 + TLS_DH_DSS_WITH_AES_128_CBC_SHA256* = 0x003E + TLS_DH_RSA_WITH_AES_128_CBC_SHA256* = 0x003F + TLS_DHE_DSS_WITH_AES_128_CBC_SHA256* = 0x0040 + TLS_DHE_RSA_WITH_AES_128_CBC_SHA256* = 0x0067 + TLS_DH_DSS_WITH_AES_256_CBC_SHA256* = 0x0068 + TLS_DH_RSA_WITH_AES_256_CBC_SHA256* = 0x0069 + TLS_DHE_DSS_WITH_AES_256_CBC_SHA256* = 0x006A + TLS_DHE_RSA_WITH_AES_256_CBC_SHA256* = 0x006B + TLS_DH_anonWITH_RC4128MD5* = 0x0018 + TLS_DH_anonWITH_3DES_EDE_CBC_SHA* = 0x001B + TLS_DH_anonWITH_AES_128CBC_SHA* = 0x0034 + TLS_DH_anonWITH_AES_256CBC_SHA* = 0x003A + TLS_DH_anonWITH_AES_128CBC_SHA256* = 0x006C + TLS_DH_anonWITH_AES_256CBC_SHA256* = 0x006D + + +const + TLS_ECDH_ECDSA_WITH_NULL_SHA* = 0xC001 + TLS_ECDH_ECDSA_WITH_RC4_128_SHA* = 0xC002 + TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA* = 0xC003 + TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA* = 0xC004 + TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA* = 0xC005 + TLS_ECDHE_ECDSA_WITH_NULL_SHA* = 0xC006 + TLS_ECDHE_ECDSA_WITH_RC4_128_SHA* = 0xC007 + TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA* = 0xC008 + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA* = 0xC009 + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA* = 0xC00A + TLS_ECDH_RSA_WITH_NULL_SHA* = 0xC00B + TLS_ECDH_RSA_WITH_RC4_128_SHA* = 0xC00C + TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA* = 0xC00D + TLS_ECDH_RSA_WITH_AES_128_CBC_SHA* = 0xC00E + TLS_ECDH_RSA_WITH_AES_256_CBC_SHA* = 0xC00F + TLS_ECDHE_RSA_WITH_NULL_SHA* = 0xC010 + TLS_ECDHE_RSA_WITH_RC4_128_SHA* = 0xC011 + TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA* = 0xC012 + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA* = 0xC013 + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA* = 0xC014 + TLS_ECDH_anonWITH_NULL_SHA* = 0xC015 + TLS_ECDH_anonWITH_RC4128SHA* = 0xC016 + TLS_ECDH_anonWITH_3DES_EDE_CBC_SHA* = 0xC017 + TLS_ECDH_anonWITH_AES_128CBC_SHA* = 0xC018 + TLS_ECDH_anonWITH_AES_256CBC_SHA* = 0xC019 + + +const + TLS_RSA_WITH_AES_128_GCM_SHA256* = 0x009C + TLS_RSA_WITH_AES_256_GCM_SHA384* = 0x009D + TLS_DHE_RSA_WITH_AES_128_GCM_SHA256* = 0x009E + TLS_DHE_RSA_WITH_AES_256_GCM_SHA384* = 0x009F + TLS_DH_RSA_WITH_AES_128_GCM_SHA256* = 0x00A0 + TLS_DH_RSA_WITH_AES_256_GCM_SHA384* = 0x00A1 + TLS_DHE_DSS_WITH_AES_128_GCM_SHA256* = 0x00A2 + TLS_DHE_DSS_WITH_AES_256_GCM_SHA384* = 0x00A3 + TLS_DH_DSS_WITH_AES_128_GCM_SHA256* = 0x00A4 + TLS_DH_DSS_WITH_AES_256_GCM_SHA384* = 0x00A5 + TLS_DH_anonWITH_AES_128GCM_SHA256* = 0x00A6 + TLS_DH_anonWITH_AES_256GCM_SHA384* = 0x00A7 + + +const + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256* = 0xC023 + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384* = 0xC024 + TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256* = 0xC025 + TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384* = 0xC026 + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256* = 0xC027 + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384* = 0xC028 + TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256* = 0xC029 + TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384* = 0xC02A + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256* = 0xC02B + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384* = 0xC02C + TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256* = 0xC02D + TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384* = 0xC02E + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256* = 0xC02F + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384* = 0xC030 + TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256* = 0xC031 + TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384* = 0xC032 + + +const + TLS_RSA_WITH_AES_128_CCM* = 0xC09C + TLS_RSA_WITH_AES_256_CCM* = 0xC09D + TLS_RSA_WITH_AES_128_CCM_8* = 0xC0A0 + TLS_RSA_WITH_AES_256_CCM_8* = 0xC0A1 + TLS_ECDHE_ECDSA_WITH_AES_128_CCM* = 0xC0AC + TLS_ECDHE_ECDSA_WITH_AES_256_CCM* = 0xC0AD + TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8* = 0xC0AE + TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8* = 0xC0AF + + +const + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256* = 0xCCA8 + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256* = 0xCCA9 + TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256* = 0xCCAA + TLS_PSK_WITH_CHACHA20_POLY1305_SHA256* = 0xCCAB + TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256* = 0xCCAC + TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256* = 0xCCAD + TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256* = 0xCCAE + + +const + TLS_FALLBACK_SCSV* = 0x5600 + + +const + ALERT_CLOSE_NOTIFY* = 0 + ALERT_UNEXPECTED_MESSAGE* = 10 + ALERT_BAD_RECORD_MAC* = 20 + ALERT_RECORD_OVERFLOW* = 22 + ALERT_DECOMPRESSION_FAILURE* = 30 + ALERT_HANDSHAKE_FAILURE* = 40 + ALERT_BAD_CERTIFICATE* = 42 + ALERT_UNSUPPORTED_CERTIFICATE* = 43 + ALERT_CERTIFICATE_REVOKED* = 44 + ALERT_CERTIFICATE_EXPIRED* = 45 + ALERT_CERTIFICATE_UNKNOWN* = 46 + ALERT_ILLEGAL_PARAMETER* = 47 + ALERT_UNKNOWN_CA* = 48 + ALERT_ACCESS_DENIED* = 49 + ALERT_DECODE_ERROR* = 50 + ALERT_DECRYPT_ERROR* = 51 + ALERT_PROTOCOL_VERSION* = 70 + ALERT_INSUFFICIENT_SECURITY* = 71 + ALERT_INTERNAL_ERROR* = 80 + ALERT_USER_CANCELED* = 90 + ALERT_NO_RENEGOTIATION* = 100 + ALERT_UNSUPPORTED_EXTENSION* = 110 + ALERT_NO_APPLICATION_PROTOCOL* = 120 diff --git a/vendor/nim-bearssl/bearssl/abi/bearssl_x509.nim b/vendor/nim-bearssl/bearssl/abi/bearssl_x509.nim new file mode 100644 index 000000000..24f9392f8 --- /dev/null +++ b/vendor/nim-bearssl/bearssl/abi/bearssl_x509.nim @@ -0,0 +1,488 @@ +import + "."/[bearssl_ec, bearssl_hash, bearssl_rsa, csources] + +{.pragma: importcFunc, cdecl, gcsafe, noSideEffect, raises: [].} +{.used.} + +const + bearX509Path = bearSrcPath & "x509/" + +{.compile: bearX509Path & "asn1enc.c".} +{.compile: bearX509Path & "encode_ec_pk8der.c".} +{.compile: bearX509Path & "encode_ec_rawder.c".} +{.compile: bearX509Path & "encode_rsa_pk8der.c".} +{.compile: bearX509Path & "encode_rsa_rawder.c".} +{.compile: bearX509Path & "skey_decoder.c".} +{.compile: bearX509Path & "x509_decoder.c".} +{.compile: bearX509Path & "x509_knownkey.c".} +{.compile: bearX509Path & "x509_minimal.c".} +{.compile: bearX509Path & "x509_minimal_full.c".} + +const + ERR_X509_OK* = 32 + + +const + ERR_X509_INVALID_VALUE* = 33 + + +const + ERR_X509_TRUNCATED* = 34 + + +const + ERR_X509_EMPTY_CHAIN* = 35 + + +const + ERR_X509_INNER_TRUNC* = 36 + + +const + ERR_X509_BAD_TAG_CLASS* = 37 + + +const + ERR_X509_BAD_TAG_VALUE* = 38 + + +const + ERR_X509_INDEFINITE_LENGTH* = 39 + + +const + ERR_X509_EXTRA_ELEMENT* = 40 + + +const + ERR_X509_UNEXPECTED* = 41 + + +const + ERR_X509_NOT_CONSTRUCTED* = 42 + + +const + ERR_X509_NOT_PRIMITIVE* = 43 + + +const + ERR_X509_PARTIAL_BYTE* = 44 + + +const + ERR_X509_BAD_BOOLEAN* = 45 + + +const + ERR_X509_OVERFLOW* = 46 + + +const + ERR_X509_BAD_DN* = 47 + + +const + ERR_X509_BAD_TIME* = 48 + + +const + ERR_X509_UNSUPPORTED* = 49 + + +const + ERR_X509_LIMIT_EXCEEDED* = 50 + + +const + ERR_X509_WRONG_KEY_TYPE* = 51 + + +const + ERR_X509_BAD_SIGNATURE* = 52 + + +const + ERR_X509_TIME_UNKNOWN* = 53 + + +const + ERR_X509_EXPIRED* = 54 + + +const + ERR_X509_DN_MISMATCH* = 55 + + +const + ERR_X509_BAD_SERVER_NAME* = 56 + + +const + ERR_X509_CRITICAL_EXTENSION* = 57 + + +const + ERR_X509_NOT_CA* = 58 + + +const + ERR_X509_FORBIDDEN_KEY_USAGE* = 59 + + +const + ERR_X509_WEAK_PUBLIC_KEY* = 60 + + +const + ERR_X509_NOT_TRUSTED* = 62 + + +type + INNER_C_UNION_bearssl_x509_1* {.importc: "br_x509_pkey::no_name", + header: "bearssl_x509.h", bycopy, union.} = object + rsa* {.importc: "rsa".}: RsaPublicKey + ec* {.importc: "ec".}: EcPublicKey + + X509Pkey* {.importc: "br_x509_pkey", header: "bearssl_x509.h", bycopy.} = object + keyType* {.importc: "key_type".}: byte + key* {.importc: "key".}: INNER_C_UNION_bearssl_x509_1 + + + +type + X500Name* {.importc: "br_x500_name", header: "bearssl_x509.h", bycopy.} = object + data* {.importc: "data".}: ptr byte + len* {.importc: "len".}: uint + + + +type + X509TrustAnchor* {.importc: "br_x509_trust_anchor", header: "bearssl_x509.h", + bycopy.} = object + dn* {.importc: "dn".}: X500Name + flags* {.importc: "flags".}: cuint + pkey* {.importc: "pkey".}: X509Pkey + + + +const + X509_TA_CA* = 0x0001 + + +const + KEYTYPE_RSA* = 1 + + +const + KEYTYPE_EC* = 2 + + +const + KEYTYPE_KEYX* = 0x10 + + +const + KEYTYPE_SIGN* = 0x20 + + +type + X509Class* {.importc: "br_x509_class", header: "bearssl_x509.h", bycopy.} = object + contextSize* {.importc: "context_size".}: uint + startChain* {.importc: "start_chain".}: proc (ctx: ptr ptr X509Class; + serverName: cstring) {.importcFunc.} + startCert* {.importc: "start_cert".}: proc (ctx: ptr ptr X509Class; length: uint32) {. + importcFunc.} + append* {.importc: "append".}: proc (ctx: ptr ptr X509Class; buf: ptr byte; + len: uint) {.importcFunc.} + endCert* {.importc: "end_cert".}: proc (ctx: ptr ptr X509Class) {.importcFunc.} + endChain* {.importc: "end_chain".}: proc (ctx: ptr ptr X509Class): cuint {.importcFunc.} + getPkey* {.importc: "get_pkey".}: proc (ctx: ptr ptr X509Class; usages: ptr cuint): ptr X509Pkey {. + importcFunc.} + + + +type + X509KnownkeyContext* {.importc: "br_x509_knownkey_context", + header: "bearssl_x509.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr X509Class + pkey* {.importc: "pkey".}: X509Pkey + usages* {.importc: "usages".}: cuint + + +var x509KnownkeyVtable* {.importc: "br_x509_knownkey_vtable", + header: "bearssl_x509.h".}: X509Class + +proc x509KnownkeyInitRsa*(ctx: var X509KnownkeyContext; pk: ptr RsaPublicKey; + usages: cuint) {.importcFunc, + importc: "br_x509_knownkey_init_rsa", + header: "bearssl_x509.h".} + +proc x509KnownkeyInitEc*(ctx: var X509KnownkeyContext; pk: ptr EcPublicKey; + usages: cuint) {.importcFunc, + importc: "br_x509_knownkey_init_ec", + header: "bearssl_x509.h".} + +const + X509_BUFSIZE_KEY* = 520 + X509_BUFSIZE_SIG* = 512 + + +type + NameElement* {.importc: "br_name_element", header: "bearssl_x509.h", bycopy.} = object + oid* {.importc: "oid".}: ptr byte + buf* {.importc: "buf".}: cstring + len* {.importc: "len".}: uint + status* {.importc: "status".}: cint + + + +type + INNER_C_STRUCT_bearssl_x509_3* {.importc: "br_x509_minimal_context::no_name", + header: "bearssl_x509.h", bycopy.} = object + dp* {.importc: "dp".}: ptr uint32 + rp* {.importc: "rp".}: ptr uint32 + ip* {.importc: "ip".}: ptr byte + + X509MinimalContext* {.importc: "br_x509_minimal_context", + header: "bearssl_x509.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr X509Class + pkey* {.importc: "pkey".}: X509Pkey + cpu* {.importc: "cpu".}: INNER_C_STRUCT_bearssl_x509_3 + dpStack* {.importc: "dp_stack".}: array[32, uint32] + rpStack* {.importc: "rp_stack".}: array[32, uint32] + err* {.importc: "err".}: cint + serverName* {.importc: "server_name".}: cstring + keyUsages* {.importc: "key_usages".}: byte + days* {.importc: "days".}: uint32 + seconds* {.importc: "seconds".}: uint32 + certLength* {.importc: "cert_length".}: uint32 + numCerts* {.importc: "num_certs".}: uint32 + hbuf* {.importc: "hbuf".}: ptr byte + hlen* {.importc: "hlen".}: uint + pad* {.importc: "pad".}: array[256, byte] + eePkeyData* {.importc: "ee_pkey_data".}: array[X509_BUFSIZE_KEY, byte] + pkeyData* {.importc: "pkey_data".}: array[X509_BUFSIZE_KEY, byte] + certSignerKeyType* {.importc: "cert_signer_key_type".}: byte + certSigHashOid* {.importc: "cert_sig_hash_oid".}: uint16 + certSigHashLen* {.importc: "cert_sig_hash_len".}: byte + certSig* {.importc: "cert_sig".}: array[X509_BUFSIZE_SIG, byte] + certSigLen* {.importc: "cert_sig_len".}: uint16 + minRsaSize* {.importc: "min_rsa_size".}: int16 + trustAnchors* {.importc: "trust_anchors".}: ptr X509TrustAnchor + trustAnchorsNum* {.importc: "trust_anchors_num".}: uint + doMhash* {.importc: "do_mhash".}: byte + mhash* {.importc: "mhash".}: MultihashContext + tbsHash* {.importc: "tbs_hash".}: array[64, byte] + doDnHash* {.importc: "do_dn_hash".}: byte + dnHashImpl* {.importc: "dn_hash_impl".}: ptr HashClass + dnHash* {.importc: "dn_hash".}: HashCompatContext + currentDnHash* {.importc: "current_dn_hash".}: array[64, byte] + nextDnHash* {.importc: "next_dn_hash".}: array[64, byte] + savedDnHash* {.importc: "saved_dn_hash".}: array[64, byte] + nameElts* {.importc: "name_elts".}: ptr NameElement + numNameElts* {.importc: "num_name_elts".}: uint + irsa* {.importc: "irsa".}: RsaPkcs1Vrfy + iecdsa* {.importc: "iecdsa".}: EcdsaVrfy + iec* {.importc: "iec".}: ptr EcImpl + + +var x509MinimalVtable* {.importc: "br_x509_minimal_vtable", header: "bearssl_x509.h".}: X509Class + +proc x509MinimalInit*(ctx: var X509MinimalContext; dnHashImpl: ptr HashClass; + trustAnchors: ptr X509TrustAnchor; trustAnchorsNum: uint) {. + importcFunc, importc: "br_x509_minimal_init", header: "bearssl_x509.h".} + +proc x509MinimalSetHash*(ctx: var X509MinimalContext; id: cint; impl: ptr HashClass) {. + inline.} = + multihashSetimpl(ctx.mhash, id, impl) + + +proc x509MinimalSetRsa*(ctx: var X509MinimalContext; irsa: RsaPkcs1Vrfy) {.inline.} = + ctx.irsa = irsa + + +proc x509MinimalSetEcdsa*(ctx: var X509MinimalContext; iec: ptr EcImpl; + iecdsa: EcdsaVrfy) {.inline.} = + ctx.iecdsa = iecdsa + ctx.iec = iec + + +proc x509MinimalInitFull*(ctx: var X509MinimalContext; + trustAnchors: ptr X509TrustAnchor; + trustAnchorsNum: uint) {.importcFunc, + importc: "br_x509_minimal_init_full", header: "bearssl_x509.h".} + +proc x509MinimalSetTime*(ctx: var X509MinimalContext; days: uint32; seconds: uint32) {. + inline.} = + ctx.days = days + ctx.seconds = seconds + + +proc x509MinimalSetMinrsa*(ctx: var X509MinimalContext; byteLength: cint) {.inline, + importcFunc.} = + ctx.minRsaSize = (int16)(byteLength - 128) + + +proc x509MinimalSetNameElements*(ctx: var X509MinimalContext; elts: ptr NameElement; + numElts: uint) {.inline.} = + ctx.nameElts = elts + ctx.numNameElts = numElts + + +type + INNER_C_STRUCT_bearssl_x509_5* {.importc: "br_x509_decoder_context::no_name", + header: "bearssl_x509.h", bycopy.} = object + dp* {.importc: "dp".}: ptr uint32 + rp* {.importc: "rp".}: ptr uint32 + ip* {.importc: "ip".}: ptr byte + + X509DecoderContext* {.importc: "br_x509_decoder_context", + header: "bearssl_x509.h", bycopy.} = object + pkey* {.importc: "pkey".}: X509Pkey + cpu* {.importc: "cpu".}: INNER_C_STRUCT_bearssl_x509_5 + dpStack* {.importc: "dp_stack".}: array[32, uint32] + rpStack* {.importc: "rp_stack".}: array[32, uint32] + err* {.importc: "err".}: cint + pad* {.importc: "pad".}: array[256, byte] + decoded* {.importc: "decoded".}: bool + notbeforeDays* {.importc: "notbefore_days".}: uint32 + notbeforeSeconds* {.importc: "notbefore_seconds".}: uint32 + notafterDays* {.importc: "notafter_days".}: uint32 + notafterSeconds* {.importc: "notafter_seconds".}: uint32 + isCA* {.importc: "isCA".}: bool + copyDn* {.importc: "copy_dn".}: byte + appendDnCtx* {.importc: "append_dn_ctx".}: pointer + appendDn* {.importc: "append_dn".}: proc (ctx: pointer; buf: pointer; len: uint) {. + importcFunc.} + hbuf* {.importc: "hbuf".}: ptr byte + hlen* {.importc: "hlen".}: uint + pkeyData* {.importc: "pkey_data".}: array[X509_BUFSIZE_KEY, byte] + signerKeyType* {.importc: "signer_key_type".}: byte + signerHashId* {.importc: "signer_hash_id".}: byte + + + +proc x509DecoderInit*(ctx: var X509DecoderContext; appendDn: proc (ctx: pointer; + buf: pointer; len: uint) {.importcFunc.}; appendDnCtx: pointer) {.importcFunc, + importc: "br_x509_decoder_init", header: "bearssl_x509.h".} + +proc x509DecoderPush*(ctx: var X509DecoderContext; data: pointer; len: uint) {.importcFunc, + importc: "br_x509_decoder_push", header: "bearssl_x509.h".} + +proc x509DecoderGetPkey*(ctx: var X509DecoderContext): ptr X509Pkey {.inline.} = + if ctx.decoded and ctx.err == 0: + return addr(ctx.pkey) + else: + return nil + + +proc x509DecoderLastError*(ctx: var X509DecoderContext): cint {.inline.} = + if ctx.err != 0: + return ctx.err + if not ctx.decoded: + return ERR_X509_TRUNCATED + return 0 + +proc x509DecoderIsCA*(ctx: var X509DecoderContext): cint {.inline.} = + return cint ctx.isCA + +proc x509DecoderGetSignerKeyType*(ctx: var X509DecoderContext): cint {.inline.} = + return cint ctx.signerKeyType + +proc x509DecoderGetSignerHashId*(ctx: var X509DecoderContext): cint {.inline.} = + return cint ctx.signerHashId + +type + X509Certificate* {.importc: "br_x509_certificate", header: "bearssl_x509.h", bycopy.} = object + data* {.importc: "data".}: ptr byte + dataLen* {.importc: "data_len".}: uint + + + +type + INNER_C_UNION_bearssl_x509_8* {.importc: "br_skey_decoder_context::no_name", + header: "bearssl_x509.h", bycopy, union.} = object + rsa* {.importc: "rsa".}: RsaPrivateKey + ec* {.importc: "ec".}: EcPrivateKey + + INNER_C_STRUCT_bearssl_x509_9* {.importc: "br_skey_decoder_context::no_name", + header: "bearssl_x509.h", bycopy.} = object + dp* {.importc: "dp".}: ptr uint32 + rp* {.importc: "rp".}: ptr uint32 + ip* {.importc: "ip".}: ptr byte + + SkeyDecoderContext* {.importc: "br_skey_decoder_context", + header: "bearssl_x509.h", bycopy.} = object + key* {.importc: "key".}: INNER_C_UNION_bearssl_x509_8 + cpu* {.importc: "cpu".}: INNER_C_STRUCT_bearssl_x509_9 + dpStack* {.importc: "dp_stack".}: array[32, uint32] + rpStack* {.importc: "rp_stack".}: array[32, uint32] + err* {.importc: "err".}: cint + hbuf* {.importc: "hbuf".}: ptr byte + hlen* {.importc: "hlen".}: uint + pad* {.importc: "pad".}: array[256, byte] + keyType* {.importc: "key_type".}: byte + keyData* {.importc: "key_data".}: array[3 * X509_BUFSIZE_SIG, byte] + + + +proc skeyDecoderInit*(ctx: var SkeyDecoderContext) {.importcFunc, + importc: "br_skey_decoder_init", header: "bearssl_x509.h".} + +proc skeyDecoderPush*(ctx: var SkeyDecoderContext; data: pointer; len: uint) {.importcFunc, + importc: "br_skey_decoder_push", header: "bearssl_x509.h".} + +proc skeyDecoderLastError*(ctx: var SkeyDecoderContext): cint {.inline.} = + if ctx.err != 0: + return ctx.err + if ctx.keyType == '\0'.byte: + return ERR_X509_TRUNCATED + return 0 + + +proc skeyDecoderKeyType*(ctx: var SkeyDecoderContext): cint {.inline.} = + if ctx.err == 0: + return cint ctx.keyType + else: + return 0 + + +proc skeyDecoderGetRsa*(ctx: var SkeyDecoderContext): ptr RsaPrivateKey {.inline.} = + if ctx.err == 0 and ctx.keyType == KEYTYPE_RSA: + return addr(ctx.key.rsa) + else: + return nil + + +proc skeyDecoderGetEc*(ctx: var SkeyDecoderContext): ptr EcPrivateKey {.inline.} = + if ctx.err == 0 and ctx.keyType == KEYTYPE_EC: + return addr(ctx.key.ec) + else: + return nil + + +proc encodeRsaRawDer*(dest: pointer; sk: ptr RsaPrivateKey; pk: ptr RsaPublicKey; + d: pointer; dlen: uint): uint {.importcFunc, + importc: "br_encode_rsa_raw_der", header: "bearssl_x509.h".} + +proc encodeRsaPkcs8Der*(dest: pointer; sk: ptr RsaPrivateKey; pk: ptr RsaPublicKey; + d: pointer; dlen: uint): uint {.importcFunc, + importc: "br_encode_rsa_pkcs8_der", header: "bearssl_x509.h".} + +proc encodeEcRawDer*(dest: pointer; sk: ptr EcPrivateKey; pk: ptr EcPublicKey): uint {. + importcFunc, importc: "br_encode_ec_raw_der", header: "bearssl_x509.h".} + +proc encodeEcPkcs8Der*(dest: pointer; sk: ptr EcPrivateKey; pk: ptr EcPublicKey): uint {. + importcFunc, importc: "br_encode_ec_pkcs8_der", header: "bearssl_x509.h".} + +const + ENCODE_PEM_RSA_RAW* = "RSA PRIVATE KEY" + + +const + ENCODE_PEM_EC_RAW* = "EC PRIVATE KEY" + + +const + ENCODE_PEM_PKCS8* = "PRIVATE KEY" diff --git a/vendor/nim-bearssl/bearssl/abi/brssl.nim b/vendor/nim-bearssl/bearssl/abi/brssl.nim new file mode 100644 index 000000000..4ba073a81 --- /dev/null +++ b/vendor/nim-bearssl/bearssl/abi/brssl.nim @@ -0,0 +1,26 @@ +import + "."/[csources, bearssl_x509] + +{.pragma: importcFunc, cdecl, gcsafe, noSideEffect, raises: [].} +{.used.} + +const + bearToolsPath = bearPath & "tools/" + + +{.compile: bearToolsPath & "vector.c".} +{.compile: bearToolsPath & "xmem.c".} +{.compile: bearToolsPath & "names.c".} +{.compile: bearToolsPath & "certs.c".} +{.compile: bearToolsPath & "files.c".} + +type + X509NoanchorContext* {.importc: "x509_noanchor_context", header: "brssl.h", bycopy.} = object + vtable* {.importc: "vtable".}: ptr X509Class + inner* {.importc: "inner".}: ptr ptr X509Class + +proc x509NoanchorInit*(xwc: var X509NoanchorContext; inner: ptr ptr X509Class) {.importcFunc, + importc: "x509_noanchor_init", header: "brssl.h".} + +proc initNoAnchor*(xwc: var X509NoanchorContext, inner: ptr ptr X509Class) {. + importcFunc, importc: "x509_noanchor_init", header: "brssl.h", deprecated: "x509NoanchorInit".} diff --git a/vendor/nim-bearssl/bearssl/abi/cacert.nim b/vendor/nim-bearssl/bearssl/abi/cacert.nim new file mode 100644 index 000000000..a916956d3 --- /dev/null +++ b/vendor/nim-bearssl/bearssl/abi/cacert.nim @@ -0,0 +1,23 @@ +## Nim-BearSSL +## Copyright (c) 2018-2021 Status Research & Development GmbH +## Licensed under either of +## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +## * MIT license ([LICENSE-MIT](LICENSE-MIT)) +## at your option. +## This file may not be copied, modified, or distributed except according to +## those terms. + +## This module provides access to Mozilla's CA certificate store in PEM format. +## This certificate store was downloaded from +## https://curl.haxx.se/ca/cacert.pem +## And converted to C header using ``brssl ta cacert.pem > cacert.h``. + +import ./csources +from ./bearssl_x509 import X509TrustAnchor + +{.passc: "-I" & bearPath & "../certs/".} + +var MozillaTrustAnchors* {. + importc: "TAs", header: "cacert20210119.h".}: array[129, X509TrustAnchor] +var MozillaTrustAnchorsCount* {. + importc: "TAs_NUM", header: "cacert20210119.h".}: cint diff --git a/vendor/nim-bearssl/bearssl/abi/config.nim b/vendor/nim-bearssl/bearssl/abi/config.nim new file mode 100644 index 000000000..2768480a8 --- /dev/null +++ b/vendor/nim-bearssl/bearssl/abi/config.nim @@ -0,0 +1,21 @@ +import + "."/[csources] + +{.pragma: importcFunc, cdecl, gcsafe, noSideEffect, raises: [].} +{.pragma: headerFunc, importcFunc, header: "bearssl.h".} +{.used.} + +const + bearRootPath = bearSrcPath + +{.compile: bearRootPath & "settings.c".} + +type + ConfigOption* {.importc: "br_config_option", header: "bearssl.h", bycopy.} = object + name* {.importc: "name".}: cstring + value* {.importc: "value".}: clong + +# TODO: missing `extern "C"` in bearssl.h means this function cannot +# be used from C++ +proc getConfig*(): ptr ConfigOption {.importcFunc, importc: "br_get_config", + headerFunc.} diff --git a/vendor/nim-bearssl/bearssl/abi/csources.nim b/vendor/nim-bearssl/bearssl/abi/csources.nim new file mode 100644 index 000000000..cfca74af2 --- /dev/null +++ b/vendor/nim-bearssl/bearssl/abi/csources.nim @@ -0,0 +1,63 @@ +## Nim-BearSSL +## Copyright (c) 2018-2022 Status Research & Development GmbH +## Licensed under either of +## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +## * MIT license ([LICENSE-MIT](LICENSE-MIT)) +## at your option. +## This file may not be copied, modified, or distributed except according to +## those terms. + +import + std/[os, strutils] + +export os + +# For each bearssl header file, we create one nim module that compilers the +# C file related to that module. Some C "modules" have dependencies - the Nim +# modules make sure to import these dependencies so that the correct C source +# files get compiled transitively. +# +# Most of the header-like content was generated with c2nim, then hand-edited. +# +# For historical reasons, some functions and types are exposed with a "Br" +# prefix - these have been marked deprecated. +# +# Some functions take a length as input - in bearssl, `csize_t` is used for this +# purpose - wrappers do the same + +static: doAssert sizeof(csize_t) == sizeof(int) +const + bearPath* = currentSourcePath.rsplit({DirSep, AltSep}, 1)[0] & "/../" & + "csources" & "/" + bearIncPath* = bearPath & "inc/" + bearSrcPath* = bearPath & "src/" + bearToolsPath* = bearPath & "tools/" + +# TODO https://github.com/nim-lang/Nim/issues/19864 + +{.passc: "-I" & quoteShell(bearSrcPath)} +{.passc: "-I" & quoteShell(bearIncPath)} +{.passc: "-I" & quoteShell(bearToolsPath)} + +when defined(windows): + {.passc: "-DBR_USE_WIN32_TIME=1".} + {.passc: "-DBR_USE_WIN32_RAND=1".} +else: + {.passc: "-DBR_USE_UNIX_TIME=1".} + {.passc: "-DBR_USE_URANDOM=1".} + +when defined(i386) or defined(amd64) or defined(arm64): + {.passc: "-DBR_LE_UNALIGNED=1".} +elif defined(powerpc) or defined(powerpc64): + {.passc: "-DBR_BE_UNALIGNED=1".} +elif defined(powerpc64el): + {.passc: "-DBR_LE_UNALIGNED=1".} + +when sizeof(int) == 8: + {.passc: "-DBR_64=1".} + when hostCPU == "amd64": + {.passc:" -DBR_amd64=1".} + when defined(vcc): + {.passc: "-DBR_UMUL128=1".} + else: + {.passc: "-DBR_INT128=1".} diff --git a/vendor/nim-bearssl/bearssl/abi/inner.nim b/vendor/nim-bearssl/bearssl/abi/inner.nim new file mode 100644 index 000000000..1112a80dc --- /dev/null +++ b/vendor/nim-bearssl/bearssl/abi/inner.nim @@ -0,0 +1,21 @@ +import + "."/[csources] + +{.used.} + +const + bearCodecPath = bearSrcPath & "codec/" + +{.compile: bearCodecPath & "ccopy.c".} +{.compile: bearCodecPath & "dec16be.c".} +{.compile: bearCodecPath & "dec16le.c".} +{.compile: bearCodecPath & "dec32be.c".} +{.compile: bearCodecPath & "dec32le.c".} +{.compile: bearCodecPath & "dec64be.c".} +{.compile: bearCodecPath & "dec64le.c".} +{.compile: bearCodecPath & "enc16be.c".} +{.compile: bearCodecPath & "enc16le.c".} +{.compile: bearCodecPath & "enc32be.c".} +{.compile: bearCodecPath & "enc32le.c".} +{.compile: bearCodecPath & "enc64be.c".} +{.compile: bearCodecPath & "enc64le.c".} diff --git a/vendor/nim-bearssl/bearssl/abi/intx.nim b/vendor/nim-bearssl/bearssl/abi/intx.nim new file mode 100644 index 000000000..80cea5307 --- /dev/null +++ b/vendor/nim-bearssl/bearssl/abi/intx.nim @@ -0,0 +1,64 @@ +import + "."/[csources] + +{.used.} + +const + bearIntPath = bearSrcPath & "int/" + +{.compile: bearIntPath & "i15_add.c".} +{.compile: bearIntPath & "i15_bitlen.c".} +{.compile: bearIntPath & "i15_decmod.c".} +{.compile: bearIntPath & "i15_decode.c".} +{.compile: bearIntPath & "i15_decred.c".} +{.compile: bearIntPath & "i15_encode.c".} +{.compile: bearIntPath & "i15_fmont.c".} +{.compile: bearIntPath & "i15_iszero.c".} +{.compile: bearIntPath & "i15_moddiv.c".} +{.compile: bearIntPath & "i15_modpow.c".} +{.compile: bearIntPath & "i15_modpow2.c".} +{.compile: bearIntPath & "i15_montmul.c".} +{.compile: bearIntPath & "i15_mulacc.c".} +{.compile: bearIntPath & "i15_muladd.c".} +{.compile: bearIntPath & "i15_ninv15.c".} +{.compile: bearIntPath & "i15_reduce.c".} +{.compile: bearIntPath & "i15_rshift.c".} +{.compile: bearIntPath & "i15_sub.c".} +{.compile: bearIntPath & "i15_tmont.c".} +{.compile: bearIntPath & "i31_add.c".} +{.compile: bearIntPath & "i31_bitlen.c".} +{.compile: bearIntPath & "i31_decmod.c".} +{.compile: bearIntPath & "i31_decode.c".} +{.compile: bearIntPath & "i31_decred.c".} +{.compile: bearIntPath & "i31_encode.c".} +{.compile: bearIntPath & "i31_fmont.c".} +{.compile: bearIntPath & "i31_iszero.c".} +{.compile: bearIntPath & "i31_moddiv.c".} +{.compile: bearIntPath & "i31_modpow.c".} +{.compile: bearIntPath & "i31_modpow2.c".} +{.compile: bearIntPath & "i31_montmul.c".} +{.compile: bearIntPath & "i31_mulacc.c".} +{.compile: bearIntPath & "i31_muladd.c".} +{.compile: bearIntPath & "i31_ninv31.c".} +{.compile: bearIntPath & "i31_reduce.c".} +{.compile: bearIntPath & "i31_rshift.c".} +{.compile: bearIntPath & "i31_sub.c".} +{.compile: bearIntPath & "i31_tmont.c".} +{.compile: bearIntPath & "i32_add.c".} +{.compile: bearIntPath & "i32_bitlen.c".} +{.compile: bearIntPath & "i32_decmod.c".} +{.compile: bearIntPath & "i32_decode.c".} +{.compile: bearIntPath & "i32_decred.c".} +{.compile: bearIntPath & "i32_div32.c".} +{.compile: bearIntPath & "i32_encode.c".} +{.compile: bearIntPath & "i32_fmont.c".} +{.compile: bearIntPath & "i32_iszero.c".} +{.compile: bearIntPath & "i32_modpow.c".} +{.compile: bearIntPath & "i32_montmul.c".} +{.compile: bearIntPath & "i32_mulacc.c".} +{.compile: bearIntPath & "i32_muladd.c".} +{.compile: bearIntPath & "i32_ninv32.c".} +{.compile: bearIntPath & "i32_reduce.c".} +{.compile: bearIntPath & "i32_sub.c".} +{.compile: bearIntPath & "i32_tmont.c".} +{.compile: bearIntPath & "i62_modpow2.c".} diff --git a/vendor/nim-bearssl/bearssl/aead.nim b/vendor/nim-bearssl/bearssl/aead.nim new file mode 100644 index 000000000..5438fa8ac --- /dev/null +++ b/vendor/nim-bearssl/bearssl/aead.nim @@ -0,0 +1,4 @@ +import + ./abi/bearssl_aead + +export bearssl_aead diff --git a/vendor/nim-bearssl/bearssl/blockx.nim b/vendor/nim-bearssl/bearssl/blockx.nim new file mode 100644 index 000000000..17924ab32 --- /dev/null +++ b/vendor/nim-bearssl/bearssl/blockx.nim @@ -0,0 +1,4 @@ +import + ./abi/bearssl_block + +export bearssl_block diff --git a/vendor/nim-bearssl/bearssl/brssl.nim b/vendor/nim-bearssl/bearssl/brssl.nim new file mode 100644 index 000000000..b89aa7862 --- /dev/null +++ b/vendor/nim-bearssl/bearssl/brssl.nim @@ -0,0 +1,4 @@ +import + ./abi/brssl + +export brssl diff --git a/vendor/nim-bearssl/bearssl/decls.nim b/vendor/nim-bearssl/bearssl/decls.nim index 205a6556b..bad6f4ab4 100644 --- a/vendor/nim-bearssl/bearssl/decls.nim +++ b/vendor/nim-bearssl/bearssl/decls.nim @@ -6,377 +6,24 @@ ## at your option. ## This file may not be copied, modified, or distributed except according to ## those terms. -## This module implements interface with BearSSL library sources. -import strutils -from os import quoteShell, DirSep, AltSep +## +## This module reexports the whole raw beassl C api, as found in the api/ +## directory as well as some legacy helpers. It should not be used in new +## projects (either import `bearssl` or individual abi modules) -const - bearPath = currentSourcePath.rsplit({DirSep, AltSep}, 1)[0] & "/" & - "csources" & "/" +import + "."/[aead, blockx, ec, hash, hmac, kdf, pem, prf, rand, rsa, ssl, x509], + ./abi/[brssl, config] - bearSrcPath = bearPath & "src" - bearIncPath = bearPath & "inc" - bearIntPath = bearSrcPath & "/" & "int" & "/" - bearCodecPath = bearSrcPath & "/" & "codec" & "/" - bearRandPath = bearSrcPath & "/" & "rand" & "/" - bearRsaPath = bearSrcPath & "/" & "rsa" & "/" - bearEcPath = bearSrcPath & "/" & "ec" & "/" - bearX509Path = bearSrcPath & "/" & "x509" & "/" - bearSslPath = bearSrcPath & "/" & "ssl" & "/" - bearMacPath = bearSrcPath & "/" & "mac" & "/" - bearKdfPath = bearSrcPath & "/" & "kdf" & "/" - bearHashPath = bearSrcPath & "/" & "hash" & "/" - bearSymcPath = bearSrcPath & "/" & "symcipher" & "/" - bearAeadPath = bearSrcPath & "/" & "aead" & "/" - bearToolsPath = bearPath & "tools" & "/" - bearRootPath = bearSrcPath & "/" - -{.passc: "-I" & quoteShell(bearSrcPath)} -{.passc: "-I" & quoteShell(bearIncPath)} -{.passc: "-I" & quoteShell(bearPath & "tools")} - -when defined(windows): - {.passc: "-DBR_USE_WIN32_TIME=1".} - {.passc: "-DBR_USE_WIN32_RAND=1".} -else: - {.passc: "-DBR_USE_UNIX_TIME=1".} - {.passc: "-DBR_USE_URANDOM=1".} - -when defined(i386) or defined(amd64) or defined(arm64): - {.passc: "-DBR_LE_UNALIGNED=1".} -elif defined(powerpc) or defined(powerpc64): - {.passc: "-DBR_BE_UNALIGNED=1".} -elif defined(powerpc64el): - {.passc: "-DBR_LE_UNALIGNED=1".} - -when sizeof(int) == 8: - {.passc: "-DBR_64=1".} - when hostCPU == "amd64": - {.passc:" -DBR_amd64=1".} - when defined(vcc): - {.passc: "-DBR_UMUL128=1".} - else: - {.passc: "-DBR_INT128=1".} - -{.compile: bearCodecPath & "ccopy.c".} -{.compile: bearCodecPath & "dec16be.c".} -{.compile: bearCodecPath & "dec16le.c".} -{.compile: bearCodecPath & "dec32be.c".} -{.compile: bearCodecPath & "dec32le.c".} -{.compile: bearCodecPath & "dec64be.c".} -{.compile: bearCodecPath & "dec64le.c".} -{.compile: bearCodecPath & "enc16be.c".} -{.compile: bearCodecPath & "enc16le.c".} -{.compile: bearCodecPath & "enc32be.c".} -{.compile: bearCodecPath & "enc32le.c".} -{.compile: bearCodecPath & "enc64be.c".} -{.compile: bearCodecPath & "enc64le.c".} -{.compile: bearCodecPath & "pemdec.c".} -{.compile: bearCodecPath & "pemenc.c".} - -{.compile: bearEcPath & "ecdsa_atr.c".} -{.compile: bearEcPath & "ecdsa_default_sign_asn1.c".} -{.compile: bearEcPath & "ecdsa_default_sign_raw.c".} -{.compile: bearEcPath & "ecdsa_default_vrfy_asn1.c".} -{.compile: bearEcPath & "ecdsa_default_vrfy_raw.c".} -{.compile: bearEcPath & "ecdsa_i15_bits.c".} -{.compile: bearEcPath & "ecdsa_i15_sign_asn1.c".} -{.compile: bearEcPath & "ecdsa_i15_sign_raw.c".} -{.compile: bearEcPath & "ecdsa_i15_vrfy_asn1.c".} -{.compile: bearEcPath & "ecdsa_i15_vrfy_raw.c".} -{.compile: bearEcPath & "ecdsa_i31_bits.c".} -{.compile: bearEcPath & "ecdsa_i31_sign_asn1.c".} -{.compile: bearEcPath & "ecdsa_i31_sign_raw.c".} -{.compile: bearEcPath & "ecdsa_i31_vrfy_asn1.c".} -{.compile: bearEcPath & "ecdsa_i31_vrfy_raw.c".} -{.compile: bearEcPath & "ecdsa_rta.c".} -{.compile: bearEcPath & "ec_all_m15.c".} -{.compile: bearEcPath & "ec_all_m31.c".} -{.compile: bearEcPath & "ec_c25519_i15.c".} -{.compile: bearEcPath & "ec_c25519_i31.c".} -{.compile: bearEcPath & "ec_c25519_m15.c".} -{.compile: bearEcPath & "ec_c25519_m31.c".} -{.compile: bearEcPath & "ec_c25519_m62.c".} -{.compile: bearEcPath & "ec_c25519_m64.c".} -{.compile: bearEcPath & "ec_curve25519.c".} -{.compile: bearEcPath & "ec_default.c".} -{.compile: bearEcPath & "ec_keygen.c".} -{.compile: bearEcPath & "ec_p256_m15.c".} -{.compile: bearEcPath & "ec_p256_m31.c".} -{.compile: bearEcPath & "ec_p256_m62.c".} -{.compile: bearEcPath & "ec_p256_m64.c".} -{.compile: bearEcPath & "ec_prime_i15.c".} -{.compile: bearEcPath & "ec_prime_i31.c".} -{.compile: bearEcPath & "ec_pubkey.c".} -{.compile: bearEcPath & "ec_secp256r1.c".} -{.compile: bearEcPath & "ec_secp384r1.c".} -{.compile: bearEcPath & "ec_secp521r1.c".} - -{.compile: bearHashPath & "dig_oid.c".} -{.compile: bearHashPath & "dig_size.c".} -{.compile: bearHashPath & "ghash_ctmul.c".} -{.compile: bearHashPath & "ghash_ctmul32.c".} -{.compile: bearHashPath & "ghash_ctmul64.c".} -{.compile: bearHashPath & "ghash_pclmul.c".} -{.compile: bearHashPath & "ghash_pwr8.c".} -{.compile: bearHashPath & "md5.c".} -{.compile: bearHashPath & "md5sha1.c".} -{.compile: bearHashPath & "mgf1.c".} -{.compile: bearHashPath & "multihash.c".} -{.compile: bearHashPath & "sha1.c".} -{.compile: bearHashPath & "sha2big.c".} -{.compile: bearHashPath & "sha2small.c".} - -{.compile: bearIntPath & "i15_add.c".} -{.compile: bearIntPath & "i15_bitlen.c".} -{.compile: bearIntPath & "i15_decmod.c".} -{.compile: bearIntPath & "i15_decode.c".} -{.compile: bearIntPath & "i15_decred.c".} -{.compile: bearIntPath & "i15_encode.c".} -{.compile: bearIntPath & "i15_fmont.c".} -{.compile: bearIntPath & "i15_iszero.c".} -{.compile: bearIntPath & "i15_moddiv.c".} -{.compile: bearIntPath & "i15_modpow.c".} -{.compile: bearIntPath & "i15_modpow2.c".} -{.compile: bearIntPath & "i15_montmul.c".} -{.compile: bearIntPath & "i15_mulacc.c".} -{.compile: bearIntPath & "i15_muladd.c".} -{.compile: bearIntPath & "i15_ninv15.c".} -{.compile: bearIntPath & "i15_reduce.c".} -{.compile: bearIntPath & "i15_rshift.c".} -{.compile: bearIntPath & "i15_sub.c".} -{.compile: bearIntPath & "i15_tmont.c".} -{.compile: bearIntPath & "i31_add.c".} -{.compile: bearIntPath & "i31_bitlen.c".} -{.compile: bearIntPath & "i31_decmod.c".} -{.compile: bearIntPath & "i31_decode.c".} -{.compile: bearIntPath & "i31_decred.c".} -{.compile: bearIntPath & "i31_encode.c".} -{.compile: bearIntPath & "i31_fmont.c".} -{.compile: bearIntPath & "i31_iszero.c".} -{.compile: bearIntPath & "i31_moddiv.c".} -{.compile: bearIntPath & "i31_modpow.c".} -{.compile: bearIntPath & "i31_modpow2.c".} -{.compile: bearIntPath & "i31_montmul.c".} -{.compile: bearIntPath & "i31_mulacc.c".} -{.compile: bearIntPath & "i31_muladd.c".} -{.compile: bearIntPath & "i31_ninv31.c".} -{.compile: bearIntPath & "i31_reduce.c".} -{.compile: bearIntPath & "i31_rshift.c".} -{.compile: bearIntPath & "i31_sub.c".} -{.compile: bearIntPath & "i31_tmont.c".} -{.compile: bearIntPath & "i32_add.c".} -{.compile: bearIntPath & "i32_bitlen.c".} -{.compile: bearIntPath & "i32_decmod.c".} -{.compile: bearIntPath & "i32_decode.c".} -{.compile: bearIntPath & "i32_decred.c".} -{.compile: bearIntPath & "i32_div32.c".} -{.compile: bearIntPath & "i32_encode.c".} -{.compile: bearIntPath & "i32_fmont.c".} -{.compile: bearIntPath & "i32_iszero.c".} -{.compile: bearIntPath & "i32_modpow.c".} -{.compile: bearIntPath & "i32_montmul.c".} -{.compile: bearIntPath & "i32_mulacc.c".} -{.compile: bearIntPath & "i32_muladd.c".} -{.compile: bearIntPath & "i32_ninv32.c".} -{.compile: bearIntPath & "i32_reduce.c".} -{.compile: bearIntPath & "i32_sub.c".} -{.compile: bearIntPath & "i32_tmont.c".} -{.compile: bearIntPath & "i62_modpow2.c".} - -{.compile: bearKdfPath & "hkdf.c".} -{.compile: bearKdfPath & "shake.c".} - -{.compile: bearMacPath & "hmac.c".} -{.compile: bearMacPath & "hmac_ct.c".} - -{.compile: bearRandPath & "aesctr_drbg.c".} -{.compile: bearRandPath & "hmac_drbg.c".} -{.compile: bearRandPath & "sysrng.c".} - -{.compile: bearRsaPath & "rsa_default_keygen.c".} -{.compile: bearRsaPath & "rsa_default_modulus.c".} -{.compile: bearRsaPath & "rsa_default_oaep_decrypt.c".} -{.compile: bearRsaPath & "rsa_default_oaep_encrypt.c".} -{.compile: bearRsaPath & "rsa_default_pkcs1_sign.c".} -{.compile: bearRsaPath & "rsa_default_pkcs1_vrfy.c".} -{.compile: bearRsaPath & "rsa_default_priv.c".} -{.compile: bearRsaPath & "rsa_default_privexp.c".} -{.compile: bearRsaPath & "rsa_default_pss_sign.c".} -{.compile: bearRsaPath & "rsa_default_pss_vrfy.c".} -{.compile: bearRsaPath & "rsa_default_pub.c".} -{.compile: bearRsaPath & "rsa_default_pubexp.c".} -{.compile: bearRsaPath & "rsa_i15_keygen.c".} -{.compile: bearRsaPath & "rsa_i15_modulus.c".} -{.compile: bearRsaPath & "rsa_i15_oaep_decrypt.c".} -{.compile: bearRsaPath & "rsa_i15_oaep_encrypt.c".} -{.compile: bearRsaPath & "rsa_i15_pkcs1_sign.c".} -{.compile: bearRsaPath & "rsa_i15_pkcs1_vrfy.c".} -{.compile: bearRsaPath & "rsa_i15_priv.c".} -{.compile: bearRsaPath & "rsa_i15_privexp.c".} -{.compile: bearRsaPath & "rsa_i15_pss_sign.c".} -{.compile: bearRsaPath & "rsa_i15_pss_vrfy.c".} -{.compile: bearRsaPath & "rsa_i15_pub.c".} -{.compile: bearRsaPath & "rsa_i15_pubexp.c".} -{.compile: bearRsaPath & "rsa_i31_keygen.c".} -{.compile: bearRsaPath & "rsa_i31_keygen_inner.c".} -{.compile: bearRsaPath & "rsa_i31_modulus.c".} -{.compile: bearRsaPath & "rsa_i31_oaep_decrypt.c".} -{.compile: bearRsaPath & "rsa_i31_oaep_encrypt.c".} -{.compile: bearRsaPath & "rsa_i31_pkcs1_sign.c".} -{.compile: bearRsaPath & "rsa_i31_pkcs1_vrfy.c".} -{.compile: bearRsaPath & "rsa_i31_priv.c".} -{.compile: bearRsaPath & "rsa_i31_privexp.c".} -{.compile: bearRsaPath & "rsa_i31_pss_sign.c".} -{.compile: bearRsaPath & "rsa_i31_pss_vrfy.c".} -{.compile: bearRsaPath & "rsa_i31_pub.c".} -{.compile: bearRsaPath & "rsa_i31_pubexp.c".} -{.compile: bearRsaPath & "rsa_i32_oaep_decrypt.c".} -{.compile: bearRsaPath & "rsa_i32_oaep_encrypt.c".} -{.compile: bearRsaPath & "rsa_i32_pkcs1_sign.c".} -{.compile: bearRsaPath & "rsa_i32_pkcs1_vrfy.c".} -{.compile: bearRsaPath & "rsa_i32_priv.c".} -{.compile: bearRsaPath & "rsa_i32_pss_sign.c".} -{.compile: bearRsaPath & "rsa_i32_pss_vrfy.c".} -{.compile: bearRsaPath & "rsa_i32_pub.c".} -{.compile: bearRsaPath & "rsa_i62_keygen.c".} -{.compile: bearRsaPath & "rsa_i62_oaep_decrypt.c".} -{.compile: bearRsaPath & "rsa_i62_oaep_encrypt.c".} -{.compile: bearRsaPath & "rsa_i62_pkcs1_sign.c".} -{.compile: bearRsaPath & "rsa_i62_pkcs1_vrfy.c".} -{.compile: bearRsaPath & "rsa_i62_priv.c".} -{.compile: bearRsaPath & "rsa_i62_pss_sign.c".} -{.compile: bearRsaPath & "rsa_i62_pss_vrfy.c".} -{.compile: bearRsaPath & "rsa_i62_pub.c".} -{.compile: bearRsaPath & "rsa_oaep_pad.c".} -{.compile: bearRsaPath & "rsa_oaep_unpad.c".} -{.compile: bearRsaPath & "rsa_pkcs1_sig_pad.c".} -{.compile: bearRsaPath & "rsa_pkcs1_sig_unpad.c".} -{.compile: bearRsaPath & "rsa_pss_sig_pad.c".} -{.compile: bearRsaPath & "rsa_pss_sig_unpad.c".} -{.compile: bearRsaPath & "rsa_ssl_decrypt.c".} - -{.compile: bearSslPath & "prf.c".} -{.compile: bearSslPath & "prf_md5sha1.c".} -{.compile: bearSslPath & "prf_sha256.c".} -{.compile: bearSslPath & "prf_sha384.c".} -{.compile: bearSslPath & "ssl_ccert_single_ec.c".} -{.compile: bearSslPath & "ssl_ccert_single_rsa.c".} -{.compile: bearSslPath & "ssl_client.c".} -{.compile: bearSslPath & "ssl_client_default_rsapub.c".} -{.compile: bearSslPath & "ssl_client_full.c".} -{.compile: bearSslPath & "ssl_engine.c".} -{.compile: bearSslPath & "ssl_engine_default_aescbc.c".} -{.compile: bearSslPath & "ssl_engine_default_aesccm.c".} -{.compile: bearSslPath & "ssl_engine_default_aesgcm.c".} -{.compile: bearSslPath & "ssl_engine_default_chapol.c".} -{.compile: bearSslPath & "ssl_engine_default_descbc.c".} -{.compile: bearSslPath & "ssl_engine_default_ec.c".} -{.compile: bearSslPath & "ssl_engine_default_ecdsa.c".} -{.compile: bearSslPath & "ssl_engine_default_rsavrfy.c".} -{.compile: bearSslPath & "ssl_hashes.c".} -{.compile: bearSslPath & "ssl_hs_client.c".} -{.compile: bearSslPath & "ssl_hs_server.c".} -{.compile: bearSslPath & "ssl_io.c".} -{.compile: bearSslPath & "ssl_keyexport.c".} -{.compile: bearSslPath & "ssl_lru.c".} -{.compile: bearSslPath & "ssl_rec_cbc.c".} -{.compile: bearSslPath & "ssl_rec_ccm.c".} -{.compile: bearSslPath & "ssl_rec_chapol.c".} -{.compile: bearSslPath & "ssl_rec_gcm.c".} -{.compile: bearSslPath & "ssl_scert_single_ec.c".} -{.compile: bearSslPath & "ssl_scert_single_rsa.c".} -{.compile: bearSslPath & "ssl_server.c".} -{.compile: bearSslPath & "ssl_server_full_ec.c".} -{.compile: bearSslPath & "ssl_server_full_rsa.c".} -{.compile: bearSslPath & "ssl_server_mine2c.c".} -{.compile: bearSslPath & "ssl_server_mine2g.c".} -{.compile: bearSslPath & "ssl_server_minf2c.c".} -{.compile: bearSslPath & "ssl_server_minf2g.c".} -{.compile: bearSslPath & "ssl_server_minr2g.c".} -{.compile: bearSslPath & "ssl_server_minu2g.c".} -{.compile: bearSslPath & "ssl_server_minv2g.c".} - -{.compile: bearSymcPath & "aes_big_cbcdec.c".} -{.compile: bearSymcPath & "aes_big_cbcenc.c".} -{.compile: bearSymcPath & "aes_big_ctr.c".} -{.compile: bearSymcPath & "aes_big_ctrcbc.c".} -{.compile: bearSymcPath & "aes_big_dec.c".} -{.compile: bearSymcPath & "aes_big_enc.c".} -{.compile: bearSymcPath & "aes_common.c".} -{.compile: bearSymcPath & "aes_ct.c".} -{.compile: bearSymcPath & "aes_ct64.c".} -{.compile: bearSymcPath & "aes_ct64_cbcdec.c".} -{.compile: bearSymcPath & "aes_ct64_cbcenc.c".} -{.compile: bearSymcPath & "aes_ct64_ctr.c".} -{.compile: bearSymcPath & "aes_ct64_ctrcbc.c".} -{.compile: bearSymcPath & "aes_ct64_dec.c".} -{.compile: bearSymcPath & "aes_ct64_enc.c".} -{.compile: bearSymcPath & "aes_ct_cbcdec.c".} -{.compile: bearSymcPath & "aes_ct_cbcenc.c".} -{.compile: bearSymcPath & "aes_ct_ctr.c".} -{.compile: bearSymcPath & "aes_ct_ctrcbc.c".} -{.compile: bearSymcPath & "aes_ct_dec.c".} -{.compile: bearSymcPath & "aes_ct_enc.c".} -{.compile: bearSymcPath & "aes_pwr8.c".} -{.compile: bearSymcPath & "aes_pwr8_cbcdec.c".} -{.compile: bearSymcPath & "aes_pwr8_cbcenc.c".} -{.compile: bearSymcPath & "aes_pwr8_ctr.c".} -{.compile: bearSymcPath & "aes_pwr8_ctrcbc.c".} -{.compile: bearSymcPath & "aes_small_cbcdec.c".} -{.compile: bearSymcPath & "aes_small_cbcenc.c".} -{.compile: bearSymcPath & "aes_small_ctr.c".} -{.compile: bearSymcPath & "aes_small_ctrcbc.c".} -{.compile: bearSymcPath & "aes_small_dec.c".} -{.compile: bearSymcPath & "aes_small_enc.c".} -{.compile: bearSymcPath & "aes_x86ni.c".} -{.compile: bearSymcPath & "aes_x86ni_cbcdec.c".} -{.compile: bearSymcPath & "aes_x86ni_cbcenc.c".} -{.compile: bearSymcPath & "aes_x86ni_ctr.c".} -{.compile: bearSymcPath & "aes_x86ni_ctrcbc.c".} -{.compile: bearSymcPath & "chacha20_ct.c".} -{.compile: bearSymcPath & "chacha20_sse2.c".} -{.compile: bearSymcPath & "des_ct.c".} -{.compile: bearSymcPath & "des_ct_cbcdec.c".} -{.compile: bearSymcPath & "des_ct_cbcenc.c".} -{.compile: bearSymcPath & "des_support.c".} -{.compile: bearSymcPath & "des_tab.c".} -{.compile: bearSymcPath & "des_tab_cbcdec.c".} -{.compile: bearSymcPath & "des_tab_cbcenc.c".} -{.compile: bearSymcPath & "poly1305_ctmul.c".} -{.compile: bearSymcPath & "poly1305_ctmul32.c".} -{.compile: bearSymcPath & "poly1305_ctmulq.c".} -{.compile: bearSymcPath & "poly1305_i15.c".} - -{.compile: bearAeadPath & "ccm.c".} -{.compile: bearAeadPath & "eax.c".} -{.compile: bearAeadPath & "gcm.c".} - -{.compile: bearX509Path & "asn1enc.c".} -{.compile: bearX509Path & "encode_ec_pk8der.c".} -{.compile: bearX509Path & "encode_ec_rawder.c".} -{.compile: bearX509Path & "encode_rsa_pk8der.c".} -{.compile: bearX509Path & "encode_rsa_rawder.c".} -{.compile: bearX509Path & "skey_decoder.c".} -{.compile: bearX509Path & "x509_decoder.c".} -{.compile: bearX509Path & "x509_knownkey.c".} -{.compile: bearX509Path & "x509_minimal.c".} -{.compile: bearX509Path & "x509_minimal_full.c".} - -{.compile: bearRootPath & "settings.c".} - -# This modules must be reimplemented using Nim, because it can be changed -# freely. -{.compile: bearToolsPath & "xmem.c".} -{.compile: bearToolsPath & "vector.c".} -{.compile: bearToolsPath & "names.c".} -{.compile: bearToolsPath & "certs.c".} -{.compile: bearToolsPath & "files.c".} +# The bearssl wrappers over time started using different styles for `Br` prefixes, +# `uint` vs `int`, `ptr` vs `var`, etc - the new split modules offer a +# consistent set of exports as well as new convenience functions that should be +# used instead - this whole module is deprecated {.pragma: bearSslFunc, cdecl, gcsafe, noSideEffect, raises: [].} type - HashClass* {.importc: "br_hash_class", header: "bearssl_hash.h", bycopy.} = object + HashClass* {.importc: "br_hash_class", header: "bearssl_hash.h", bycopy, deprecated.} = object contextSize* {.importc: "context_size".}: int desc* {.importc: "desc".}: uint32 init* {.importc: "init".}: proc (ctx: ptr ptr HashClass) {.bearSslFunc.} @@ -428,7 +75,7 @@ const var md5Vtable* {.importc: "br_md5_vtable", header: "bearssl_hash.h".}: HashClass type - Md5Context* {.importc: "br_md5_context", header: "bearssl_hash.h", bycopy.} = object + Md5Context* {.importc: "br_md5_context", header: "bearssl_hash.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr HashClass buf* {.importc: "buf".}: array[64, cuchar] count* {.importc: "count".}: uint64 @@ -436,19 +83,19 @@ type proc md5Init*(ctx: ptr Md5Context) {. - bearSslFunc, importc: "br_md5_init", header: "bearssl_hash.h".} + bearSslFunc, deprecated, importc: "br_md5_init", header: "bearssl_hash.h".} proc md5Update*(ctx: ptr Md5Context; data: pointer; len: int) {. - bearSslFunc, importc: "br_md5_update", header: "bearssl_hash.h".} + bearSslFunc, deprecated, importc: "br_md5_update", header: "bearssl_hash.h".} proc md5Out*(ctx: ptr Md5Context; `out`: pointer) {. - bearSslFunc, importc: "br_md5_out", header: "bearssl_hash.h".} + bearSslFunc, deprecated, importc: "br_md5_out", header: "bearssl_hash.h".} proc md5State*(ctx: ptr Md5Context; `out`: pointer): uint64 {. - bearSslFunc, importc: "br_md5_state", header: "bearssl_hash.h".} + bearSslFunc, deprecated, importc: "br_md5_state", header: "bearssl_hash.h".} proc md5SetState*(ctx: ptr Md5Context; stb: pointer; count: uint64) {. - bearSslFunc, importc: "br_md5_set_state", header: "bearssl_hash.h".} + bearSslFunc, deprecated, importc: "br_md5_set_state", header: "bearssl_hash.h".} const sha1ID* = 2 @@ -459,7 +106,7 @@ const var sha1Vtable* {.importc: "br_sha1_vtable", header: "bearssl_hash.h".}: HashClass type - Sha1Context* {.importc: "br_sha1_context", header: "bearssl_hash.h", bycopy.} = object + Sha1Context* {.importc: "br_sha1_context", header: "bearssl_hash.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr HashClass buf* {.importc: "buf".}: array[64, cuchar] count* {.importc: "count".}: uint64 @@ -467,19 +114,19 @@ type proc sha1Init*(ctx: ptr Sha1Context) {. - bearSslFunc, importc: "br_sha1_init", header: "bearssl_hash.h".} + bearSslFunc, deprecated, importc: "br_sha1_init", header: "bearssl_hash.h".} proc sha1Update*(ctx: ptr Sha1Context; data: pointer; len: int) {. - bearSslFunc, importc: "br_sha1_update", header: "bearssl_hash.h".} + bearSslFunc, deprecated, importc: "br_sha1_update", header: "bearssl_hash.h".} proc sha1Out*(ctx: ptr Sha1Context; `out`: pointer) {. - bearSslFunc, importc: "br_sha1_out", header: "bearssl_hash.h".} + bearSslFunc, deprecated, importc: "br_sha1_out", header: "bearssl_hash.h".} proc sha1State*(ctx: ptr Sha1Context; `out`: pointer): uint64 {. - bearSslFunc, importc: "br_sha1_state", header: "bearssl_hash.h".} + bearSslFunc, deprecated, importc: "br_sha1_state", header: "bearssl_hash.h".} proc sha1SetState*(ctx: ptr Sha1Context; stb: pointer; count: uint64) {. - bearSslFunc, importc: "br_sha1_set_state", header: "bearssl_hash.h".} + bearSslFunc, deprecated, importc: "br_sha1_set_state", header: "bearssl_hash.h".} const sha224ID* = 3 @@ -491,7 +138,7 @@ var sha224Vtable* {.importc: "br_sha224_vtable", header: "bearssl_hash.h".}: Has type Sha256Context* = Sha224Context - Sha224Context* {.importc: "br_sha224_context", header: "bearssl_hash.h", bycopy.} = object + Sha224Context* {.importc: "br_sha224_context", header: "bearssl_hash.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr HashClass buf* {.importc: "buf".}: array[64, cuchar] count* {.importc: "count".}: uint64 @@ -499,19 +146,19 @@ type proc sha224Init*(ctx: ptr Sha224Context) {. - bearSslFunc, importc: "br_sha224_init", header: "bearssl_hash.h".} + bearSslFunc, deprecated, importc: "br_sha224_init", header: "bearssl_hash.h".} proc sha224Update*(ctx: ptr Sha224Context; data: pointer; len: int) {. - bearSslFunc, importc: "br_sha224_update", header: "bearssl_hash.h".} + bearSslFunc, deprecated, importc: "br_sha224_update", header: "bearssl_hash.h".} proc sha224Out*(ctx: ptr Sha224Context; `out`: pointer) {. - bearSslFunc, importc: "br_sha224_out", header: "bearssl_hash.h".} + bearSslFunc, deprecated, importc: "br_sha224_out", header: "bearssl_hash.h".} proc sha224State*(ctx: ptr Sha224Context; `out`: pointer): uint64 {. - bearSslFunc, importc: "br_sha224_state", header: "bearssl_hash.h".} + bearSslFunc, deprecated, importc: "br_sha224_state", header: "bearssl_hash.h".} proc sha224SetState*(ctx: ptr Sha224Context; stb: pointer; count: uint64) {. - bearSslFunc, importc: "br_sha224_set_state", header: "bearssl_hash.h".} + bearSslFunc, deprecated, importc: "br_sha224_set_state", header: "bearssl_hash.h".} const sha256ID* = 4 @@ -522,24 +169,17 @@ const var sha256Vtable* {.importc: "br_sha256_vtable", header: "bearssl_hash.h".}: HashClass proc sha256Init*(ctx: ptr Sha256Context) {. - bearSslFunc, importc: "br_sha256_init", header: "bearssl_hash.h".} + bearSslFunc, deprecated, importc: "br_sha256_init", header: "bearssl_hash.h".} proc sha256Out*(ctx: ptr Sha256Context; `out`: pointer) {. - bearSslFunc, importc: "br_sha256_out", header: "bearssl_hash.h".} + bearSslFunc, deprecated, importc: "br_sha256_out", header: "bearssl_hash.h".} when false: proc sha256State*(ctx: ptr Sha256Context; `out`: pointer): uint64 {. - bearSslFunc, importc: "br_sha256_state", header: "bearssl_hash.h".} -else: - const - sha256State* = sha224State - + bearSslFunc, deprecated, importc: "br_sha256_state", header: "bearssl_hash.h".} when false: proc sha256SetState*(ctx: ptr Sha256Context; stb: pointer; count: uint64) {. - bearSslFunc, importc: "br_sha256_set_state", header: "bearssl_hash.h".} -else: - const - sha256SetState* = sha224SetState + bearSslFunc, deprecated, importc: "br_sha256_set_state", header: "bearssl_hash.h".} const sha384ID* = 5 @@ -550,7 +190,7 @@ const var sha384Vtable* {.importc: "br_sha384_vtable", header: "bearssl_hash.h".}: HashClass type - Sha384Context* {.importc: "br_sha384_context", header: "bearssl_hash.h", bycopy.} = object + Sha384Context* {.importc: "br_sha384_context", header: "bearssl_hash.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr HashClass buf* {.importc: "buf".}: array[128, cuchar] count* {.importc: "count".}: uint64 @@ -558,19 +198,19 @@ type proc sha384Init*(ctx: ptr Sha384Context) {. - bearSslFunc, importc: "br_sha384_init", header: "bearssl_hash.h".} + bearSslFunc, deprecated, importc: "br_sha384_init", header: "bearssl_hash.h".} proc sha384Update*(ctx: ptr Sha384Context; data: pointer; len: int) {. - bearSslFunc, importc: "br_sha384_update", header: "bearssl_hash.h".} + bearSslFunc, deprecated, importc: "br_sha384_update", header: "bearssl_hash.h".} proc sha384Out*(ctx: ptr Sha384Context; `out`: pointer) {. - bearSslFunc, importc: "br_sha384_out", header: "bearssl_hash.h".} + bearSslFunc, deprecated, importc: "br_sha384_out", header: "bearssl_hash.h".} proc sha384State*(ctx: ptr Sha384Context; `out`: pointer): uint64 {. - bearSslFunc, importc: "br_sha384_state", header: "bearssl_hash.h".} + bearSslFunc, deprecated, importc: "br_sha384_state", header: "bearssl_hash.h".} proc sha384SetState*(ctx: ptr Sha384Context; stb: pointer; count: uint64) {. - bearSslFunc, importc: "br_sha384_set_state", header: "bearssl_hash.h".} + bearSslFunc, deprecated, importc: "br_sha384_set_state", header: "bearssl_hash.h".} const sha512ID* = 6 @@ -584,13 +224,10 @@ type Sha512Context* = Sha384Context proc sha512Init*(ctx: ptr Sha512Context) {. - bearSslFunc, importc: "br_sha512_init", header: "bearssl_hash.h".} - -const - sha512Update* = sha384Update + bearSslFunc, deprecated, importc: "br_sha512_init", header: "bearssl_hash.h".} proc sha512Out*(ctx: ptr Sha512Context; `out`: pointer) {. - bearSslFunc, importc: "br_sha512_out", header: "bearssl_hash.h".} + bearSslFunc, deprecated, importc: "br_sha512_out", header: "bearssl_hash.h".} const md5sha1ID* = 0 @@ -601,7 +238,7 @@ const var md5sha1Vtable* {.importc: "br_md5sha1_vtable", header: "bearssl_hash.h".}: HashClass type - Md5sha1Context* {.importc: "br_md5sha1_context", header: "bearssl_hash.h", bycopy.} = object + Md5sha1Context* {.importc: "br_md5sha1_context", header: "bearssl_hash.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr HashClass buf* {.importc: "buf".}: array[64, cuchar] count* {.importc: "count".}: uint64 @@ -609,24 +246,24 @@ type valSha1* {.importc: "val_sha1".}: array[5, uint32] -proc md5sha1Init*(ctx: ptr Md5sha1Context) {.bearSslFunc, importc: "br_md5sha1_init", +proc md5sha1Init*(ctx: ptr Md5sha1Context) {.bearSslFunc, deprecated, importc: "br_md5sha1_init", header: "bearssl_hash.h".} -proc md5sha1Update*(ctx: ptr Md5sha1Context; data: pointer; len: int) {.bearSslFunc, +proc md5sha1Update*(ctx: ptr Md5sha1Context; data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_md5sha1_update", header: "bearssl_hash.h".} -proc md5sha1Out*(ctx: ptr Md5sha1Context; `out`: pointer) {.bearSslFunc, +proc md5sha1Out*(ctx: ptr Md5sha1Context; `out`: pointer) {.bearSslFunc, deprecated, importc: "br_md5sha1_out", header: "bearssl_hash.h".} -proc md5sha1State*(ctx: ptr Md5sha1Context; `out`: pointer): uint64 {.bearSslFunc, +proc md5sha1State*(ctx: ptr Md5sha1Context; `out`: pointer): uint64 {.bearSslFunc, deprecated, importc: "br_md5sha1_state", header: "bearssl_hash.h".} -proc md5sha1SetState*(ctx: ptr Md5sha1Context; stb: pointer; count: uint64) {.bearSslFunc, +proc md5sha1SetState*(ctx: ptr Md5sha1Context; stb: pointer; count: uint64) {.bearSslFunc, deprecated, importc: "br_md5sha1_set_state", header: "bearssl_hash.h".} type HashCompatContext* {.importc: "br_hash_compat_context", header: "bearssl_hash.h", - union, bycopy.} = object + union, bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr HashClass md5* {.importc: "md5".}: Md5Context sha1* {.importc: "sha1".}: Sha1Context @@ -647,7 +284,7 @@ type impl* {.importc: "impl".}: array[6, ptr HashClass] -proc multihashZero*(ctx: ptr MultihashContext) {.bearSslFunc, importc: "br_multihash_zero", +proc multihashZero*(ctx: ptr MultihashContext) {.bearSslFunc, deprecated, importc: "br_multihash_zero", header: "bearssl_hash.h".} proc multihashSetimpl*(ctx: ptr MultihashContext; id: cint; impl: ptr HashClass) {. @@ -655,78 +292,78 @@ proc multihashSetimpl*(ctx: ptr MultihashContext; id: cint; impl: ptr HashClass) ctx.impl[id - 1] = impl proc multihashGetimpl*(ctx: ptr MultihashContext; id: cint): ptr HashClass {.inline, - bearSslFunc.} = + bearSslFunc, deprecated.} = return ctx.impl[id - 1] -proc multihashInit*(ctx: ptr MultihashContext) {.bearSslFunc, importc: "br_multihash_init", +proc multihashInit*(ctx: ptr MultihashContext) {.bearSslFunc, deprecated, importc: "br_multihash_init", header: "bearssl_hash.h".} -proc multihashUpdate*(ctx: ptr MultihashContext; data: pointer; len: int) {.bearSslFunc, +proc multihashUpdate*(ctx: ptr MultihashContext; data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_multihash_update", header: "bearssl_hash.h".} -proc multihashOut*(ctx: ptr MultihashContext; id: cint; dst: pointer): int {.bearSslFunc, +proc multihashOut*(ctx: ptr MultihashContext; id: cint; dst: pointer): int {.bearSslFunc, deprecated, importc: "br_multihash_out", header: "bearssl_hash.h".} type - Ghash* = proc (y: pointer; h: pointer; data: pointer; len: int) {.bearSslFunc.} + Ghash* {.deprecated.} = proc (y: pointer; h: pointer; data: pointer; len: int) {.bearSslFunc.} -proc ghashCtmul*(y: pointer; h: pointer; data: pointer; len: int) {.bearSslFunc, +proc ghashCtmul*(y: pointer; h: pointer; data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_ghash_ctmul", header: "bearssl_hash.h".} -proc ghashCtmul32*(y: pointer; h: pointer; data: pointer; len: int) {.bearSslFunc, +proc ghashCtmul32*(y: pointer; h: pointer; data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_ghash_ctmul32", header: "bearssl_hash.h".} -proc ghashCtmul64*(y: pointer; h: pointer; data: pointer; len: int) {.bearSslFunc, +proc ghashCtmul64*(y: pointer; h: pointer; data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_ghash_ctmul64", header: "bearssl_hash.h".} -proc ghashPclmul*(y: pointer; h: pointer; data: pointer; len: int) {.bearSslFunc, +proc ghashPclmul*(y: pointer; h: pointer; data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_ghash_pclmul", header: "bearssl_hash.h".} -proc ghashPclmulGet*(): Ghash {.bearSslFunc, importc: "br_ghash_pclmul_get", +proc ghashPclmulGet*(): Ghash {.bearSslFunc, deprecated, importc: "br_ghash_pclmul_get", header: "bearssl_hash.h".} -proc ghashPwr8*(y: pointer; h: pointer; data: pointer; len: int) {.bearSslFunc, +proc ghashPwr8*(y: pointer; h: pointer; data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_ghash_pwr8", header: "bearssl_hash.h".} -proc ghashPwr8Get*(): Ghash {.bearSslFunc, importc: "br_ghash_pwr8_get", +proc ghashPwr8Get*(): Ghash {.bearSslFunc, deprecated, importc: "br_ghash_pwr8_get", header: "bearssl_hash.h".} type - HmacKeyContext* {.importc: "br_hmac_key_context", header: "bearssl_hmac.h", bycopy.} = object + HmacKeyContext* {.importc: "br_hmac_key_context", header: "bearssl_hmac.h", bycopy, deprecated.} = object digVtable* {.importc: "dig_vtable".}: ptr HashClass ksi* {.importc: "ksi".}: array[64, cuchar] kso* {.importc: "kso".}: array[64, cuchar] proc hmacKeyInit*(kc: ptr HmacKeyContext; digestVtable: ptr HashClass; key: pointer; - keyLen: int) {.bearSslFunc, importc: "br_hmac_key_init", + keyLen: int) {.bearSslFunc, deprecated, importc: "br_hmac_key_init", header: "bearssl_hmac.h".} type - HmacContext* {.importc: "br_hmac_context", header: "bearssl_hmac.h", bycopy.} = object + HmacContext* {.importc: "br_hmac_context", header: "bearssl_hmac.h", bycopy, deprecated.} = object dig* {.importc: "dig".}: HashCompatContext kso* {.importc: "kso".}: array[64, cuchar] outLen* {.importc: "out_len".}: int -proc hmacInit*(ctx: ptr HmacContext; kc: ptr HmacKeyContext; outLen: int) {.bearSslFunc, +proc hmacInit*(ctx: ptr HmacContext; kc: ptr HmacKeyContext; outLen: int) {.bearSslFunc, deprecated, importc: "br_hmac_init", header: "bearssl_hmac.h".} -proc hmacSize*(ctx: ptr HmacContext): int {.inline.} = +proc hmacSize*(ctx: ptr HmacContext): int {.inline, deprecated.} = return ctx.outLen -proc hmacUpdate*(ctx: ptr HmacContext; data: pointer; len: int) {.bearSslFunc, +proc hmacUpdate*(ctx: ptr HmacContext; data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_hmac_update", header: "bearssl_hmac.h".} -proc hmacOut*(ctx: ptr HmacContext; `out`: pointer): int {.bearSslFunc, +proc hmacOut*(ctx: ptr HmacContext; `out`: pointer): int {.bearSslFunc, deprecated, importc: "br_hmac_out", header: "bearssl_hmac.h".} proc hmacOutCT*(ctx: ptr HmacContext; data: pointer; len: int; minLen: int; - maxLen: int; `out`: pointer): int {.bearSslFunc, + maxLen: int; `out`: pointer): int {.bearSslFunc, deprecated, importc: "br_hmac_outCT", header: "bearssl_hmac.h".} type - PrngClass* {.importc: "br_prng_class", header: "bearssl_rand.h", bycopy.} = object + PrngClass* {.importc: "br_prng_class", header: "bearssl_rand.h", bycopy, deprecated.} = object contextSize* {.importc: "context_size".}: int init* {.importc: "init".}: proc (ctx: ptr ptr PrngClass; params: pointer; seed: pointer; seedLen: int) {.bearSslFunc.} @@ -747,22 +384,22 @@ type var hmacDrbgVtable* {.importc: "br_hmac_drbg_vtable", header: "bearssl_rand.h".}: PrngClass proc hmacDrbgInit*(ctx: ptr HmacDrbgContext; digestClass: ptr HashClass; seed: pointer; - seedLen: int) {.bearSslFunc, importc: "br_hmac_drbg_init", + seedLen: int) {.bearSslFunc, deprecated, importc: "br_hmac_drbg_init", header: "bearssl_rand.h".} -proc hmacDrbgGenerate*(ctx: ptr HmacDrbgContext; `out`: pointer; len: int) {.bearSslFunc, +proc hmacDrbgGenerate*(ctx: ptr HmacDrbgContext; `out`: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_hmac_drbg_generate", header: "bearssl_rand.h".} -proc hmacDrbgUpdate*(ctx: ptr HmacDrbgContext; seed: pointer; seedLen: int) {.bearSslFunc, +proc hmacDrbgUpdate*(ctx: ptr HmacDrbgContext; seed: pointer; seedLen: int) {.bearSslFunc, deprecated, importc: "br_hmac_drbg_update", header: "bearssl_rand.h".} -proc hmacDrbgGetHash*(ctx: ptr HmacDrbgContext): ptr HashClass {.inline.} = +proc hmacDrbgGetHash*(ctx: ptr HmacDrbgContext): ptr HashClass {.inline, deprecated.} = return ctx.digestClass type - PrngSeeder* = proc (ctx: ptr ptr PrngClass): cint {.bearSslFunc.} + PrngSeeder* {.deprecated.} = proc (ctx: ptr ptr PrngClass): cint {.bearSslFunc.} -proc prngSeederSystem*(name: cstringArray): PrngSeeder {.bearSslFunc, +proc prngSeederSystem*(name: cstringArray): PrngSeeder {.bearSslFunc, deprecated, importc: "br_prng_seeder_system", header: "bearssl_rand.h".} type @@ -773,19 +410,19 @@ type proc tls10Prf*(dst: pointer; len: int; secret: pointer; secretLen: int; - label: cstring; seedNum: int; seed: ptr TlsPrfSeedChunk) {.bearSslFunc, + label: cstring; seedNum: int; seed: ptr TlsPrfSeedChunk) {.bearSslFunc, deprecated, importc: "br_tls10_prf", header: "bearssl_prf.h".} proc tls12Sha256Prf*(dst: pointer; len: int; secret: pointer; secretLen: int; - label: cstring; seedNum: int; seed: ptr TlsPrfSeedChunk) {.bearSslFunc, + label: cstring; seedNum: int; seed: ptr TlsPrfSeedChunk) {.bearSslFunc, deprecated, importc: "br_tls12_sha256_prf", header: "bearssl_prf.h".} proc tls12Sha384Prf*(dst: pointer; len: int; secret: pointer; secretLen: int; - label: cstring; seedNum: int; seed: ptr TlsPrfSeedChunk) {.bearSslFunc, + label: cstring; seedNum: int; seed: ptr TlsPrfSeedChunk) {.bearSslFunc, deprecated, importc: "br_tls12_sha384_prf", header: "bearssl_prf.h".} type - TlsPrfImpl* = proc (dst: pointer; len: int; secret: pointer; secretLen: int; + TlsPrfImpl* {.deprecated.} = proc (dst: pointer; len: int; secret: pointer; secretLen: int; label: cstring; seedNum: int; seed: ptr TlsPrfSeedChunk) {.bearSslFunc.} type @@ -811,7 +448,7 @@ type data: pointer; len: int) {.bearSslFunc.} type - BlockCtrClass* {.importc: "br_block_ctr_class", header: "bearssl_block.h", bycopy.} = object + BlockCtrClass* {.importc: "br_block_ctr_class", header: "bearssl_block.h", bycopy, deprecated.} = object contextSize* {.importc: "context_size".}: int blockSize* {.importc: "block_size".}: cuint logBlockSize* {.importc: "log_block_size".}: cuint @@ -859,7 +496,7 @@ type type - AesBigCtrKeys* {.importc: "br_aes_big_ctr_keys", header: "bearssl_block.h", bycopy.} = object + AesBigCtrKeys* {.importc: "br_aes_big_ctr_keys", header: "bearssl_block.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr BlockCtrClass skey* {.importc: "skey".}: array[60, uint32] numRounds* {.importc: "num_rounds".}: cuint @@ -884,41 +521,41 @@ var aesBigCtrVtable* {.importc: "br_aes_big_ctr_vtable", header: "bearssl_block. var aesBigCtrcbcVtable* {.importc: "br_aes_big_ctrcbc_vtable", header: "bearssl_block.h".}: BlockCtrcbcClass -proc aesBigCbcencInit*(ctx: ptr AesBigCbcencKeys; key: pointer; len: int) {.bearSslFunc, +proc aesBigCbcencInit*(ctx: ptr AesBigCbcencKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_big_cbcenc_init", header: "bearssl_block.h".} -proc aesBigCbcdecInit*(ctx: ptr AesBigCbcdecKeys; key: pointer; len: int) {.bearSslFunc, +proc aesBigCbcdecInit*(ctx: ptr AesBigCbcdecKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_big_cbcdec_init", header: "bearssl_block.h".} -proc aesBigCtrInit*(ctx: ptr AesBigCtrKeys; key: pointer; len: int) {.bearSslFunc, +proc aesBigCtrInit*(ctx: ptr AesBigCtrKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_big_ctr_init", header: "bearssl_block.h".} -proc aesBigCtrcbcInit*(ctx: ptr AesBigCtrcbcKeys; key: pointer; len: int) {.bearSslFunc, +proc aesBigCtrcbcInit*(ctx: ptr AesBigCtrcbcKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_big_ctrcbc_init", header: "bearssl_block.h".} proc aesBigCbcencRun*(ctx: ptr AesBigCbcencKeys; iv: pointer; data: pointer; len: int) {. - bearSslFunc, importc: "br_aes_big_cbcenc_run", header: "bearssl_block.h".} + bearSslFunc, deprecated, importc: "br_aes_big_cbcenc_run", header: "bearssl_block.h".} proc aesBigCbcdecRun*(ctx: ptr AesBigCbcdecKeys; iv: pointer; data: pointer; len: int) {. - bearSslFunc, importc: "br_aes_big_cbcdec_run", header: "bearssl_block.h".} + bearSslFunc, deprecated, importc: "br_aes_big_cbcdec_run", header: "bearssl_block.h".} proc aesBigCtrRun*(ctx: ptr AesBigCtrKeys; iv: pointer; cc: uint32; data: pointer; - len: int): uint32 {.bearSslFunc, importc: "br_aes_big_ctr_run", + len: int): uint32 {.bearSslFunc, deprecated, importc: "br_aes_big_ctr_run", header: "bearssl_block.h".} proc aesBigCtrcbcEncrypt*(ctx: ptr AesBigCtrcbcKeys; ctr: pointer; cbcmac: pointer; - data: pointer; len: int) {.bearSslFunc, + data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_big_ctrcbc_encrypt", header: "bearssl_block.h".} proc aesBigCtrcbcDecrypt*(ctx: ptr AesBigCtrcbcKeys; ctr: pointer; cbcmac: pointer; - data: pointer; len: int) {.bearSslFunc, + data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_big_ctrcbc_decrypt", header: "bearssl_block.h".} proc aesBigCtrcbcCtr*(ctx: ptr AesBigCtrcbcKeys; ctr: pointer; data: pointer; len: int) {. - bearSslFunc, importc: "br_aes_big_ctrcbc_ctr", header: "bearssl_block.h".} + bearSslFunc, deprecated, importc: "br_aes_big_ctrcbc_ctr", header: "bearssl_block.h".} proc aesBigCtrcbcMac*(ctx: ptr AesBigCtrcbcKeys; cbcmac: pointer; data: pointer; - len: int) {.bearSslFunc, importc: "br_aes_big_ctrcbc_mac", + len: int) {.bearSslFunc, deprecated, importc: "br_aes_big_ctrcbc_mac", header: "bearssl_block.h".} const @@ -926,7 +563,7 @@ const type AesSmallCbcencKeys* {.importc: "br_aes_small_cbcenc_keys", - header: "bearssl_block.h", bycopy.} = object + header: "bearssl_block.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr BlockCbcencClass skey* {.importc: "skey".}: array[60, uint32] numRounds* {.importc: "num_rounds".}: cuint @@ -934,7 +571,7 @@ type type AesSmallCbcdecKeys* {.importc: "br_aes_small_cbcdec_keys", - header: "bearssl_block.h", bycopy.} = object + header: "bearssl_block.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr BlockCbcdecClass skey* {.importc: "skey".}: array[60, uint32] numRounds* {.importc: "num_rounds".}: cuint @@ -950,7 +587,7 @@ type type AesSmallCtrcbcKeys* {.importc: "br_aes_small_ctrcbc_keys", - header: "bearssl_block.h", bycopy.} = object + header: "bearssl_block.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr BlockCtrcbcClass skey* {.importc: "skey".}: array[60, uint32] numRounds* {.importc: "num_rounds".}: cuint @@ -968,44 +605,44 @@ var aesSmallCtrVtable* {.importc: "br_aes_small_ctr_vtable", var aesSmallCtrcbcVtable* {.importc: "br_aes_small_ctrcbc_vtable", header: "bearssl_block.h".}: BlockCtrcbcClass -proc aesSmallCbcencInit*(ctx: ptr AesSmallCbcencKeys; key: pointer; len: int) {.bearSslFunc, +proc aesSmallCbcencInit*(ctx: ptr AesSmallCbcencKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_small_cbcenc_init", header: "bearssl_block.h".} -proc aesSmallCbcdecInit*(ctx: ptr AesSmallCbcdecKeys; key: pointer; len: int) {.bearSslFunc, +proc aesSmallCbcdecInit*(ctx: ptr AesSmallCbcdecKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_small_cbcdec_init", header: "bearssl_block.h".} -proc aesSmallCtrInit*(ctx: ptr AesSmallCtrKeys; key: pointer; len: int) {.bearSslFunc, +proc aesSmallCtrInit*(ctx: ptr AesSmallCtrKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_small_ctr_init", header: "bearssl_block.h".} -proc aesSmallCtrcbcInit*(ctx: ptr AesSmallCtrcbcKeys; key: pointer; len: int) {.bearSslFunc, +proc aesSmallCtrcbcInit*(ctx: ptr AesSmallCtrcbcKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_small_ctrcbc_init", header: "bearssl_block.h".} proc aesSmallCbcencRun*(ctx: ptr AesSmallCbcencKeys; iv: pointer; data: pointer; - len: int) {.bearSslFunc, importc: "br_aes_small_cbcenc_run", + len: int) {.bearSslFunc, deprecated, importc: "br_aes_small_cbcenc_run", header: "bearssl_block.h".} proc aesSmallCbcdecRun*(ctx: ptr AesSmallCbcdecKeys; iv: pointer; data: pointer; - len: int) {.bearSslFunc, importc: "br_aes_small_cbcdec_run", + len: int) {.bearSslFunc, deprecated, importc: "br_aes_small_cbcdec_run", header: "bearssl_block.h".} proc aesSmallCtrRun*(ctx: ptr AesSmallCtrKeys; iv: pointer; cc: uint32; data: pointer; - len: int): uint32 {.bearSslFunc, importc: "br_aes_small_ctr_run", + len: int): uint32 {.bearSslFunc, deprecated, importc: "br_aes_small_ctr_run", header: "bearssl_block.h".} proc aesSmallCtrcbcEncrypt*(ctx: ptr AesSmallCtrcbcKeys; ctr: pointer; - cbcmac: pointer; data: pointer; len: int) {.bearSslFunc, + cbcmac: pointer; data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_small_ctrcbc_encrypt", header: "bearssl_block.h".} proc aesSmallCtrcbcDecrypt*(ctx: ptr AesSmallCtrcbcKeys; ctr: pointer; - cbcmac: pointer; data: pointer; len: int) {.bearSslFunc, + cbcmac: pointer; data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_small_ctrcbc_decrypt", header: "bearssl_block.h".} proc aesSmallCtrcbcCtr*(ctx: ptr AesSmallCtrcbcKeys; ctr: pointer; data: pointer; - len: int) {.bearSslFunc, importc: "br_aes_small_ctrcbc_ctr", + len: int) {.bearSslFunc, deprecated, importc: "br_aes_small_ctrcbc_ctr", header: "bearssl_block.h".} proc aesSmallCtrcbcMac*(ctx: ptr AesSmallCtrcbcKeys; cbcmac: pointer; data: pointer; - len: int) {.bearSslFunc, importc: "br_aes_small_ctrcbc_mac", + len: int) {.bearSslFunc, deprecated, importc: "br_aes_small_ctrcbc_mac", header: "bearssl_block.h".} const @@ -1028,7 +665,7 @@ type type - AesCtCtrKeys* {.importc: "br_aes_ct_ctr_keys", header: "bearssl_block.h", bycopy.} = object + AesCtCtrKeys* {.importc: "br_aes_ct_ctr_keys", header: "bearssl_block.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr BlockCtrClass skey* {.importc: "skey".}: array[60, uint32] numRounds* {.importc: "num_rounds".}: cuint @@ -1053,41 +690,41 @@ var aesCtCtrVtable* {.importc: "br_aes_ct_ctr_vtable", header: "bearssl_block.h" var aesCtCtrcbcVtable* {.importc: "br_aes_ct_ctrcbc_vtable", header: "bearssl_block.h".}: BlockCtrcbcClass -proc aesCtCbcencInit*(ctx: ptr AesCtCbcencKeys; key: pointer; len: int) {.bearSslFunc, +proc aesCtCbcencInit*(ctx: ptr AesCtCbcencKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_ct_cbcenc_init", header: "bearssl_block.h".} -proc aesCtCbcdecInit*(ctx: ptr AesCtCbcdecKeys; key: pointer; len: int) {.bearSslFunc, +proc aesCtCbcdecInit*(ctx: ptr AesCtCbcdecKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_ct_cbcdec_init", header: "bearssl_block.h".} -proc aesCtCtrInit*(ctx: ptr AesCtCtrKeys; key: pointer; len: int) {.bearSslFunc, +proc aesCtCtrInit*(ctx: ptr AesCtCtrKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_ct_ctr_init", header: "bearssl_block.h".} -proc aesCtCtrcbcInit*(ctx: ptr AesCtCtrcbcKeys; key: pointer; len: int) {.bearSslFunc, +proc aesCtCtrcbcInit*(ctx: ptr AesCtCtrcbcKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_ct_ctrcbc_init", header: "bearssl_block.h".} proc aesCtCbcencRun*(ctx: ptr AesCtCbcencKeys; iv: pointer; data: pointer; len: int) {. - bearSslFunc, importc: "br_aes_ct_cbcenc_run", header: "bearssl_block.h".} + bearSslFunc, deprecated, importc: "br_aes_ct_cbcenc_run", header: "bearssl_block.h".} proc aesCtCbcdecRun*(ctx: ptr AesCtCbcdecKeys; iv: pointer; data: pointer; len: int) {. - bearSslFunc, importc: "br_aes_ct_cbcdec_run", header: "bearssl_block.h".} + bearSslFunc, deprecated, importc: "br_aes_ct_cbcdec_run", header: "bearssl_block.h".} proc aesCtCtrRun*(ctx: ptr AesCtCtrKeys; iv: pointer; cc: uint32; data: pointer; - len: int): uint32 {.bearSslFunc, importc: "br_aes_ct_ctr_run", + len: int): uint32 {.bearSslFunc, deprecated, importc: "br_aes_ct_ctr_run", header: "bearssl_block.h".} proc aesCtCtrcbcEncrypt*(ctx: ptr AesCtCtrcbcKeys; ctr: pointer; cbcmac: pointer; - data: pointer; len: int) {.bearSslFunc, + data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_ct_ctrcbc_encrypt", header: "bearssl_block.h".} proc aesCtCtrcbcDecrypt*(ctx: ptr AesCtCtrcbcKeys; ctr: pointer; cbcmac: pointer; - data: pointer; len: int) {.bearSslFunc, + data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_ct_ctrcbc_decrypt", header: "bearssl_block.h".} proc aesCtCtrcbcCtr*(ctx: ptr AesCtCtrcbcKeys; ctr: pointer; data: pointer; len: int) {. - bearSslFunc, importc: "br_aes_ct_ctrcbc_ctr", header: "bearssl_block.h".} + bearSslFunc, deprecated, importc: "br_aes_ct_ctrcbc_ctr", header: "bearssl_block.h".} proc aesCtCtrcbcMac*(ctx: ptr AesCtCtrcbcKeys; cbcmac: pointer; data: pointer; - len: int) {.bearSslFunc, importc: "br_aes_ct_ctrcbc_mac", + len: int) {.bearSslFunc, deprecated, importc: "br_aes_ct_ctrcbc_mac", header: "bearssl_block.h".} const @@ -1095,7 +732,7 @@ const type AesCt64CbcencKeys* {.importc: "br_aes_ct64_cbcenc_keys", - header: "bearssl_block.h", bycopy.} = object + header: "bearssl_block.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr BlockCbcencClass skey* {.importc: "skey".}: array[30, uint64] numRounds* {.importc: "num_rounds".}: cuint @@ -1103,7 +740,7 @@ type type AesCt64CbcdecKeys* {.importc: "br_aes_ct64_cbcdec_keys", - header: "bearssl_block.h", bycopy.} = object + header: "bearssl_block.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr BlockCbcdecClass skey* {.importc: "skey".}: array[30, uint64] numRounds* {.importc: "num_rounds".}: cuint @@ -1119,7 +756,7 @@ type type AesCt64CtrcbcKeys* {.importc: "br_aes_ct64_ctrcbc_keys", - header: "bearssl_block.h", bycopy.} = object + header: "bearssl_block.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr BlockCtrcbcClass skey* {.importc: "skey".}: array[30, uint64] numRounds* {.importc: "num_rounds".}: cuint @@ -1136,44 +773,44 @@ var aesCt64CtrVtable* {.importc: "br_aes_ct64_ctr_vtable", header: "bearssl_bloc var aesCt64CtrcbcVtable* {.importc: "br_aes_ct64_ctrcbc_vtable", header: "bearssl_block.h".}: BlockCtrcbcClass -proc aesCt64CbcencInit*(ctx: ptr AesCt64CbcencKeys; key: pointer; len: int) {.bearSslFunc, +proc aesCt64CbcencInit*(ctx: ptr AesCt64CbcencKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_ct64_cbcenc_init", header: "bearssl_block.h".} -proc aesCt64CbcdecInit*(ctx: ptr AesCt64CbcdecKeys; key: pointer; len: int) {.bearSslFunc, +proc aesCt64CbcdecInit*(ctx: ptr AesCt64CbcdecKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_ct64_cbcdec_init", header: "bearssl_block.h".} -proc aesCt64CtrInit*(ctx: ptr AesCt64CtrKeys; key: pointer; len: int) {.bearSslFunc, +proc aesCt64CtrInit*(ctx: ptr AesCt64CtrKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_ct64_ctr_init", header: "bearssl_block.h".} -proc aesCt64CtrcbcInit*(ctx: ptr AesCt64CtrcbcKeys; key: pointer; len: int) {.bearSslFunc, +proc aesCt64CtrcbcInit*(ctx: ptr AesCt64CtrcbcKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_ct64_ctrcbc_init", header: "bearssl_block.h".} proc aesCt64CbcencRun*(ctx: ptr AesCt64CbcencKeys; iv: pointer; data: pointer; - len: int) {.bearSslFunc, importc: "br_aes_ct64_cbcenc_run", + len: int) {.bearSslFunc, deprecated, importc: "br_aes_ct64_cbcenc_run", header: "bearssl_block.h".} proc aesCt64CbcdecRun*(ctx: ptr AesCt64CbcdecKeys; iv: pointer; data: pointer; - len: int) {.bearSslFunc, importc: "br_aes_ct64_cbcdec_run", + len: int) {.bearSslFunc, deprecated, importc: "br_aes_ct64_cbcdec_run", header: "bearssl_block.h".} proc aesCt64CtrRun*(ctx: ptr AesCt64CtrKeys; iv: pointer; cc: uint32; data: pointer; - len: int): uint32 {.bearSslFunc, importc: "br_aes_ct64_ctr_run", + len: int): uint32 {.bearSslFunc, deprecated, importc: "br_aes_ct64_ctr_run", header: "bearssl_block.h".} proc aesCt64CtrcbcEncrypt*(ctx: ptr AesCt64CtrcbcKeys; ctr: pointer; cbcmac: pointer; - data: pointer; len: int) {.bearSslFunc, + data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_ct64_ctrcbc_encrypt", header: "bearssl_block.h".} proc aesCt64CtrcbcDecrypt*(ctx: ptr AesCt64CtrcbcKeys; ctr: pointer; cbcmac: pointer; - data: pointer; len: int) {.bearSslFunc, + data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_ct64_ctrcbc_decrypt", header: "bearssl_block.h".} proc aesCt64CtrcbcCtr*(ctx: ptr AesCt64CtrcbcKeys; ctr: pointer; data: pointer; - len: int) {.bearSslFunc, importc: "br_aes_ct64_ctrcbc_ctr", + len: int) {.bearSslFunc, deprecated, importc: "br_aes_ct64_ctrcbc_ctr", header: "bearssl_block.h".} proc aesCt64CtrcbcMac*(ctx: ptr AesCt64CtrcbcKeys; cbcmac: pointer; data: pointer; - len: int) {.bearSslFunc, importc: "br_aes_ct64_ctrcbc_mac", + len: int) {.bearSslFunc, deprecated, importc: "br_aes_ct64_ctrcbc_mac", header: "bearssl_block.h".} const @@ -1185,7 +822,7 @@ type skni* {.importc: "skni".}: array[16 * 15, cuchar] AesX86niCbcencKeys* {.importc: "br_aes_x86ni_cbcenc_keys", - header: "bearssl_block.h", bycopy.} = object + header: "bearssl_block.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr BlockCbcencClass skey* {.importc: "skey".}: INNER_C_UNION_1159666335 numRounds* {.importc: "num_rounds".}: cuint @@ -1197,7 +834,7 @@ type skni* {.importc: "skni".}: array[16 * 15, cuchar] AesX86niCbcdecKeys* {.importc: "br_aes_x86ni_cbcdec_keys", - header: "bearssl_block.h", bycopy.} = object + header: "bearssl_block.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr BlockCbcdecClass skey* {.importc: "skey".}: INNER_C_UNION_3830826214 numRounds* {.importc: "num_rounds".}: cuint @@ -1221,7 +858,7 @@ type skni* {.importc: "skni".}: array[16 * 15, cuchar] AesX86niCtrcbcKeys* {.importc: "br_aes_x86ni_ctrcbc_keys", - header: "bearssl_block.h", bycopy.} = object + header: "bearssl_block.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr BlockCtrcbcClass skey* {.importc: "skey".}: INNER_C_UNION_220758887 numRounds* {.importc: "num_rounds".}: cuint @@ -1239,56 +876,56 @@ var aesX86niCtrVtable* {.importc: "br_aes_x86ni_ctr_vtable", var aesX86niCtrcbcVtable* {.importc: "br_aes_x86ni_ctrcbc_vtable", header: "bearssl_block.h".}: BlockCtrcbcClass -proc aesX86niCbcencInit*(ctx: ptr AesX86niCbcencKeys; key: pointer; len: int) {.bearSslFunc, +proc aesX86niCbcencInit*(ctx: ptr AesX86niCbcencKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_x86ni_cbcenc_init", header: "bearssl_block.h".} -proc aesX86niCbcdecInit*(ctx: ptr AesX86niCbcdecKeys; key: pointer; len: int) {.bearSslFunc, +proc aesX86niCbcdecInit*(ctx: ptr AesX86niCbcdecKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_x86ni_cbcdec_init", header: "bearssl_block.h".} -proc aesX86niCtrInit*(ctx: ptr AesX86niCtrKeys; key: pointer; len: int) {.bearSslFunc, +proc aesX86niCtrInit*(ctx: ptr AesX86niCtrKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_x86ni_ctr_init", header: "bearssl_block.h".} -proc aesX86niCtrcbcInit*(ctx: ptr AesX86niCtrcbcKeys; key: pointer; len: int) {.bearSslFunc, +proc aesX86niCtrcbcInit*(ctx: ptr AesX86niCtrcbcKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_x86ni_ctrcbc_init", header: "bearssl_block.h".} proc aesX86niCbcencRun*(ctx: ptr AesX86niCbcencKeys; iv: pointer; data: pointer; - len: int) {.bearSslFunc, importc: "br_aes_x86ni_cbcenc_run", + len: int) {.bearSslFunc, deprecated, importc: "br_aes_x86ni_cbcenc_run", header: "bearssl_block.h".} proc aesX86niCbcdecRun*(ctx: ptr AesX86niCbcdecKeys; iv: pointer; data: pointer; - len: int) {.bearSslFunc, importc: "br_aes_x86ni_cbcdec_run", + len: int) {.bearSslFunc, deprecated, importc: "br_aes_x86ni_cbcdec_run", header: "bearssl_block.h".} proc aesX86niCtrRun*(ctx: ptr AesX86niCtrKeys; iv: pointer; cc: uint32; data: pointer; - len: int): uint32 {.bearSslFunc, importc: "br_aes_x86ni_ctr_run", + len: int): uint32 {.bearSslFunc, deprecated, importc: "br_aes_x86ni_ctr_run", header: "bearssl_block.h".} proc aesX86niCtrcbcEncrypt*(ctx: ptr AesX86niCtrcbcKeys; ctr: pointer; - cbcmac: pointer; data: pointer; len: int) {.bearSslFunc, + cbcmac: pointer; data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_x86ni_ctrcbc_encrypt", header: "bearssl_block.h".} proc aesX86niCtrcbcDecrypt*(ctx: ptr AesX86niCtrcbcKeys; ctr: pointer; - cbcmac: pointer; data: pointer; len: int) {.bearSslFunc, + cbcmac: pointer; data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_x86ni_ctrcbc_decrypt", header: "bearssl_block.h".} proc aesX86niCtrcbcCtr*(ctx: ptr AesX86niCtrcbcKeys; ctr: pointer; data: pointer; - len: int) {.bearSslFunc, importc: "br_aes_x86ni_ctrcbc_ctr", + len: int) {.bearSslFunc, deprecated, importc: "br_aes_x86ni_ctrcbc_ctr", header: "bearssl_block.h".} proc aesX86niCtrcbcMac*(ctx: ptr AesX86niCtrcbcKeys; cbcmac: pointer; data: pointer; - len: int) {.bearSslFunc, importc: "br_aes_x86ni_ctrcbc_mac", + len: int) {.bearSslFunc, deprecated, importc: "br_aes_x86ni_ctrcbc_mac", header: "bearssl_block.h".} -proc aesX86niCbcencGetVtable*(): ptr BlockCbcencClass {.bearSslFunc, +proc aesX86niCbcencGetVtable*(): ptr BlockCbcencClass {.bearSslFunc, deprecated, importc: "br_aes_x86ni_cbcenc_get_vtable", header: "bearssl_block.h".} -proc aesX86niCbcdecGetVtable*(): ptr BlockCbcdecClass {.bearSslFunc, +proc aesX86niCbcdecGetVtable*(): ptr BlockCbcdecClass {.bearSslFunc, deprecated, importc: "br_aes_x86ni_cbcdec_get_vtable", header: "bearssl_block.h".} -proc aesX86niCtrGetVtable*(): ptr BlockCtrClass {.bearSslFunc, +proc aesX86niCtrGetVtable*(): ptr BlockCtrClass {.bearSslFunc, deprecated, importc: "br_aes_x86ni_ctr_get_vtable", header: "bearssl_block.h".} -proc aesX86niCtrcbcGetVtable*(): ptr BlockCtrcbcClass {.bearSslFunc, +proc aesX86niCtrcbcGetVtable*(): ptr BlockCtrcbcClass {.bearSslFunc, deprecated, importc: "br_aes_x86ni_ctrcbc_get_vtable", header: "bearssl_block.h".} const @@ -1300,7 +937,7 @@ type skni* {.importc: "skni".}: array[16 * 15, cuchar] AesPwr8CbcencKeys* {.importc: "br_aes_pwr8_cbcenc_keys", - header: "bearssl_block.h", bycopy.} = object + header: "bearssl_block.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr BlockCbcencClass skey* {.importc: "skey".}: INNER_C_UNION_2338321047 numRounds* {.importc: "num_rounds".}: cuint @@ -1312,7 +949,7 @@ type skni* {.importc: "skni".}: array[16 * 15, cuchar] AesPwr8CbcdecKeys* {.importc: "br_aes_pwr8_cbcdec_keys", - header: "bearssl_block.h", bycopy.} = object + header: "bearssl_block.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr BlockCbcdecClass skey* {.importc: "skey".}: INNER_C_UNION_714513630 numRounds* {.importc: "num_rounds".}: cuint @@ -1338,34 +975,34 @@ var aesPwr8CbcdecVtable* {.importc: "br_aes_pwr8_cbcdec_vtable", var aesPwr8CtrVtable* {.importc: "br_aes_pwr8_ctr_vtable", header: "bearssl_block.h".}: BlockCtrClass -proc aesPwr8CbcencInit*(ctx: ptr AesPwr8CbcencKeys; key: pointer; len: int) {.bearSslFunc, +proc aesPwr8CbcencInit*(ctx: ptr AesPwr8CbcencKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_pwr8_cbcenc_init", header: "bearssl_block.h".} -proc aesPwr8CbcdecInit*(ctx: ptr AesPwr8CbcdecKeys; key: pointer; len: int) {.bearSslFunc, +proc aesPwr8CbcdecInit*(ctx: ptr AesPwr8CbcdecKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_pwr8_cbcdec_init", header: "bearssl_block.h".} -proc aesPwr8CtrInit*(ctx: ptr AesPwr8CtrKeys; key: pointer; len: int) {.bearSslFunc, +proc aesPwr8CtrInit*(ctx: ptr AesPwr8CtrKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_aes_pwr8_ctr_init", header: "bearssl_block.h".} proc aesPwr8CbcencRun*(ctx: ptr AesPwr8CbcencKeys; iv: pointer; data: pointer; - len: int) {.bearSslFunc, importc: "br_aes_pwr8_cbcenc_run", + len: int) {.bearSslFunc, deprecated, importc: "br_aes_pwr8_cbcenc_run", header: "bearssl_block.h".} proc aesPwr8CbcdecRun*(ctx: ptr AesPwr8CbcdecKeys; iv: pointer; data: pointer; - len: int) {.bearSslFunc, importc: "br_aes_pwr8_cbcdec_run", + len: int) {.bearSslFunc, deprecated, importc: "br_aes_pwr8_cbcdec_run", header: "bearssl_block.h".} proc aesPwr8CtrRun*(ctx: ptr AesPwr8CtrKeys; iv: pointer; cc: uint32; data: pointer; - len: int): uint32 {.bearSslFunc, importc: "br_aes_pwr8_ctr_run", + len: int): uint32 {.bearSslFunc, deprecated, importc: "br_aes_pwr8_ctr_run", header: "bearssl_block.h".} -proc aesPwr8CbcencGetVtable*(): ptr BlockCbcencClass {.bearSslFunc, +proc aesPwr8CbcencGetVtable*(): ptr BlockCbcencClass {.bearSslFunc, deprecated, importc: "br_aes_pwr8_cbcenc_get_vtable", header: "bearssl_block.h".} -proc aesPwr8CbcdecGetVtable*(): ptr BlockCbcdecClass {.bearSslFunc, +proc aesPwr8CbcdecGetVtable*(): ptr BlockCbcdecClass {.bearSslFunc, deprecated, importc: "br_aes_pwr8_cbcdec_get_vtable", header: "bearssl_block.h".} -proc aesPwr8CtrGetVtable*(): ptr BlockCtrClass {.bearSslFunc, +proc aesPwr8CtrGetVtable*(): ptr BlockCtrClass {.bearSslFunc, deprecated, importc: "br_aes_pwr8_ctr_get_vtable", header: "bearssl_block.h".} type @@ -1406,7 +1043,7 @@ type type AesGenCtrcbcKeys* {.importc: "br_aes_gen_ctrcbc_keys", - header: "bearssl_block.h", bycopy, union.} = object + header: "bearssl_block.h", bycopy, deprecated, union.} = object vtable* {.importc: "vtable".}: ptr BlockCtrcbcClass cBig* {.importc: "c_big".}: AesBigCtrcbcKeys cSmall* {.importc: "c_small".}: AesSmallCtrcbcKeys @@ -1439,17 +1076,17 @@ var desTabCbcencVtable* {.importc: "br_des_tab_cbcenc_vtable", var desTabCbcdecVtable* {.importc: "br_des_tab_cbcdec_vtable", header: "bearssl_block.h".}: BlockCbcdecClass -proc desTabCbcencInit*(ctx: ptr DesTabCbcencKeys; key: pointer; len: int) {.bearSslFunc, +proc desTabCbcencInit*(ctx: ptr DesTabCbcencKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_des_tab_cbcenc_init", header: "bearssl_block.h".} -proc desTabCbcdecInit*(ctx: ptr DesTabCbcdecKeys; key: pointer; len: int) {.bearSslFunc, +proc desTabCbcdecInit*(ctx: ptr DesTabCbcdecKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_des_tab_cbcdec_init", header: "bearssl_block.h".} proc desTabCbcencRun*(ctx: ptr DesTabCbcencKeys; iv: pointer; data: pointer; len: int) {. - bearSslFunc, importc: "br_des_tab_cbcenc_run", header: "bearssl_block.h".} + bearSslFunc, deprecated, importc: "br_des_tab_cbcenc_run", header: "bearssl_block.h".} proc desTabCbcdecRun*(ctx: ptr DesTabCbcdecKeys; iv: pointer; data: pointer; len: int) {. - bearSslFunc, importc: "br_des_tab_cbcdec_run", header: "bearssl_block.h".} + bearSslFunc, deprecated, importc: "br_des_tab_cbcdec_run", header: "bearssl_block.h".} const desCtBLOCK_SIZE* = 8 @@ -1476,21 +1113,21 @@ var desCtCbcencVtable* {.importc: "br_des_ct_cbcenc_vtable", var desCtCbcdecVtable* {.importc: "br_des_ct_cbcdec_vtable", header: "bearssl_block.h".}: BlockCbcdecClass -proc desCtCbcencInit*(ctx: ptr DesCtCbcencKeys; key: pointer; len: int) {.bearSslFunc, +proc desCtCbcencInit*(ctx: ptr DesCtCbcencKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_des_ct_cbcenc_init", header: "bearssl_block.h".} -proc desCtCbcdecInit*(ctx: ptr DesCtCbcdecKeys; key: pointer; len: int) {.bearSslFunc, +proc desCtCbcdecInit*(ctx: ptr DesCtCbcdecKeys; key: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_des_ct_cbcdec_init", header: "bearssl_block.h".} proc desCtCbcencRun*(ctx: ptr DesCtCbcencKeys; iv: pointer; data: pointer; len: int) {. - bearSslFunc, importc: "br_des_ct_cbcenc_run", header: "bearssl_block.h".} + bearSslFunc, deprecated, importc: "br_des_ct_cbcenc_run", header: "bearssl_block.h".} proc desCtCbcdecRun*(ctx: ptr DesCtCbcdecKeys; iv: pointer; data: pointer; len: int) {. - bearSslFunc, importc: "br_des_ct_cbcdec_run", header: "bearssl_block.h".} + bearSslFunc, deprecated, importc: "br_des_ct_cbcdec_run", header: "bearssl_block.h".} type DesGenCbcencKeys* {.importc: "br_des_gen_cbcenc_keys", - header: "bearssl_block.h", bycopy, union.} = object + header: "bearssl_block.h", bycopy, deprecated, union.} = object vtable* {.importc: "vtable".}: ptr BlockCbcencClass tab* {.importc: "tab".}: DesTabCbcencKeys ct* {.importc: "ct".}: DesCtCbcencKeys @@ -1498,54 +1135,54 @@ type type DesGenCbcdecKeys* {.importc: "br_des_gen_cbcdec_keys", - header: "bearssl_block.h", bycopy, union.} = object + header: "bearssl_block.h", bycopy, deprecated, union.} = object vtable* {.importc: "vtable".}: ptr BlockCbcdecClass cTab* {.importc: "c_tab".}: DesTabCbcdecKeys cCt* {.importc: "c_ct".}: DesCtCbcdecKeys type - Chacha20Run* = proc (key: pointer; iv: pointer; cc: uint32; data: pointer; len: int): uint32 {. + Chacha20Run* {.deprecated.} = proc (key: pointer; iv: pointer; cc: uint32; data: pointer; len: int): uint32 {. bearSslFunc.} proc chacha20CtRun*(key: pointer; iv: pointer; cc: uint32; data: pointer; len: int): uint32 {. - bearSslFunc, importc: "br_chacha20_ct_run", header: "bearssl_block.h".} + bearSslFunc, deprecated, importc: "br_chacha20_ct_run", header: "bearssl_block.h".} proc chacha20Sse2Run*(key: pointer; iv: pointer; cc: uint32; data: pointer; len: int): uint32 {. - bearSslFunc, importc: "br_chacha20_sse2_run", header: "bearssl_block.h".} + bearSslFunc, deprecated, importc: "br_chacha20_sse2_run", header: "bearssl_block.h".} -proc chacha20Sse2Get*(): Chacha20Run {.bearSslFunc, importc: "br_chacha20_sse2_get", +proc chacha20Sse2Get*(): Chacha20Run {.bearSslFunc, deprecated, importc: "br_chacha20_sse2_get", header: "bearssl_block.h".} type - Poly1305Run* = proc (key: pointer; iv: pointer; data: pointer; len: int; aad: pointer; + Poly1305Run* {.deprecated.} = proc (key: pointer; iv: pointer; data: pointer; len: int; aad: pointer; aadLen: int; tag: pointer; ichacha: Chacha20Run; encrypt: cint) {. bearSslFunc.} proc poly1305CtmulRun*(key: pointer; iv: pointer; data: pointer; len: int; aad: pointer; aadLen: int; tag: pointer; ichacha: Chacha20Run; - encrypt: cint) {.bearSslFunc, importc: "br_poly1305_ctmul_run", + encrypt: cint) {.bearSslFunc, deprecated, importc: "br_poly1305_ctmul_run", header: "bearssl_block.h".} proc poly1305Ctmul32Run*(key: pointer; iv: pointer; data: pointer; len: int; aad: pointer; aadLen: int; tag: pointer; - ichacha: Chacha20Run; encrypt: cint) {.bearSslFunc, + ichacha: Chacha20Run; encrypt: cint) {.bearSslFunc, deprecated, importc: "br_poly1305_ctmul32_run", header: "bearssl_block.h".} proc poly1305I15Run*(key: pointer; iv: pointer; data: pointer; len: int; aad: pointer; aadLen: int; tag: pointer; ichacha: Chacha20Run; encrypt: cint) {. - bearSslFunc, importc: "br_poly1305_i15_run", header: "bearssl_block.h".} + bearSslFunc, deprecated, importc: "br_poly1305_i15_run", header: "bearssl_block.h".} proc poly1305CtmulqRun*(key: pointer; iv: pointer; data: pointer; len: int; aad: pointer; aadLen: int; tag: pointer; - ichacha: Chacha20Run; encrypt: cint) {.bearSslFunc, + ichacha: Chacha20Run; encrypt: cint) {.bearSslFunc, deprecated, importc: "br_poly1305_ctmulq_run", header: "bearssl_block.h".} -proc poly1305CtmulqGet*(): Poly1305Run {.bearSslFunc, importc: "br_poly1305_ctmulq_get", +proc poly1305CtmulqGet*(): Poly1305Run {.bearSslFunc, deprecated, importc: "br_poly1305_ctmulq_get", header: "bearssl_block.h".} type - AeadClass* {.importc: "br_aead_class", header: "bearssl_aead.h", bycopy.} = object + AeadClass* {.importc: "br_aead_class", header: "bearssl_aead.h", bycopy, deprecated.} = object tagSize* {.importc: "tag_size".}: int reset* {.importc: "reset".}: proc (cc: ptr ptr AeadClass; iv: pointer; len: int) {. bearSslFunc.} @@ -1563,7 +1200,7 @@ type tag: pointer; len: int): uint32 {.bearSslFunc.} type - GcmContext* {.importc: "br_gcm_context", header: "bearssl_aead.h", bycopy.} = object + GcmContext* {.importc: "br_gcm_context", header: "bearssl_aead.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr AeadClass bctx* {.importc: "bctx".}: ptr ptr BlockCtrClass gh* {.importc: "gh".}: Ghash @@ -1577,37 +1214,37 @@ type countCtr* {.importc: "count_ctr".}: uint64 -proc gcmInit*(ctx: ptr GcmContext; bctx: ptr ptr BlockCtrClass; gh: Ghash) {.bearSslFunc, +proc gcmInit*(ctx: ptr GcmContext; bctx: ptr ptr BlockCtrClass; gh: Ghash) {.bearSslFunc, deprecated, importc: "br_gcm_init", header: "bearssl_aead.h".} -proc gcmReset*(ctx: ptr GcmContext; iv: pointer; len: int) {.bearSslFunc, +proc gcmReset*(ctx: ptr GcmContext; iv: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_gcm_reset", header: "bearssl_aead.h".} -proc gcmAadInject*(ctx: ptr GcmContext; data: pointer; len: int) {.bearSslFunc, +proc gcmAadInject*(ctx: ptr GcmContext; data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_gcm_aad_inject", header: "bearssl_aead.h".} -proc gcmFlip*(ctx: ptr GcmContext) {.bearSslFunc, importc: "br_gcm_flip", +proc gcmFlip*(ctx: ptr GcmContext) {.bearSslFunc, deprecated, importc: "br_gcm_flip", header: "bearssl_aead.h".} -proc gcmRun*(ctx: ptr GcmContext; encrypt: cint; data: pointer; len: int) {.bearSslFunc, +proc gcmRun*(ctx: ptr GcmContext; encrypt: cint; data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_gcm_run", header: "bearssl_aead.h".} -proc gcmGetTag*(ctx: ptr GcmContext; tag: pointer) {.bearSslFunc, importc: "br_gcm_get_tag", +proc gcmGetTag*(ctx: ptr GcmContext; tag: pointer) {.bearSslFunc, deprecated, importc: "br_gcm_get_tag", header: "bearssl_aead.h".} -proc gcmCheckTag*(ctx: ptr GcmContext; tag: pointer): uint32 {.bearSslFunc, +proc gcmCheckTag*(ctx: ptr GcmContext; tag: pointer): uint32 {.bearSslFunc, deprecated, importc: "br_gcm_check_tag", header: "bearssl_aead.h".} -proc gcmGetTagTrunc*(ctx: ptr GcmContext; tag: pointer; len: int) {.bearSslFunc, +proc gcmGetTagTrunc*(ctx: ptr GcmContext; tag: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_gcm_get_tag_trunc", header: "bearssl_aead.h".} -proc gcmCheckTagTrunc*(ctx: ptr GcmContext; tag: pointer; len: int): uint32 {.bearSslFunc, +proc gcmCheckTagTrunc*(ctx: ptr GcmContext; tag: pointer; len: int): uint32 {.bearSslFunc, deprecated, importc: "br_gcm_check_tag_trunc", header: "bearssl_aead.h".} var gcmVtable* {.importc: "br_gcm_vtable", header: "bearssl_aead.h".}: AeadClass type - EaxContext* {.importc: "br_eax_context", header: "bearssl_aead.h", bycopy.} = object + EaxContext* {.importc: "br_eax_context", header: "bearssl_aead.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr AeadClass bctx* {.importc: "bctx".}: ptr ptr BlockCtrcbcClass l2* {.importc: "L2".}: array[16, cuchar] @@ -1621,53 +1258,53 @@ type type - EaxState* {.importc: "br_eax_state", header: "bearssl_aead.h", bycopy.} = object + EaxState* {.importc: "br_eax_state", header: "bearssl_aead.h", bycopy, deprecated.} = object st* {.importc: "st".}: array[3, array[16, cuchar]] -proc eaxInit*(ctx: ptr EaxContext; bctx: ptr ptr BlockCtrcbcClass) {.bearSslFunc, +proc eaxInit*(ctx: ptr EaxContext; bctx: ptr ptr BlockCtrcbcClass) {.bearSslFunc, deprecated, importc: "br_eax_init", header: "bearssl_aead.h".} -proc eaxCapture*(ctx: ptr EaxContext; st: ptr EaxState) {.bearSslFunc, +proc eaxCapture*(ctx: ptr EaxContext; st: ptr EaxState) {.bearSslFunc, deprecated, importc: "br_eax_capture", header: "bearssl_aead.h".} -proc eaxReset*(ctx: ptr EaxContext; nonce: pointer; len: int) {.bearSslFunc, +proc eaxReset*(ctx: ptr EaxContext; nonce: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_eax_reset", header: "bearssl_aead.h".} proc eaxResetPreAad*(ctx: ptr EaxContext; st: ptr EaxState; nonce: pointer; len: int) {. - bearSslFunc, importc: "br_eax_reset_pre_aad", header: "bearssl_aead.h".} + bearSslFunc, deprecated, importc: "br_eax_reset_pre_aad", header: "bearssl_aead.h".} proc eaxResetPostAad*(ctx: ptr EaxContext; st: ptr EaxState; nonce: pointer; len: int) {. - bearSslFunc, importc: "br_eax_reset_post_aad", header: "bearssl_aead.h".} + bearSslFunc, deprecated, importc: "br_eax_reset_post_aad", header: "bearssl_aead.h".} -proc eaxAadInject*(ctx: ptr EaxContext; data: pointer; len: int) {.bearSslFunc, +proc eaxAadInject*(ctx: ptr EaxContext; data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_eax_aad_inject", header: "bearssl_aead.h".} -proc eaxFlip*(ctx: ptr EaxContext) {.bearSslFunc, importc: "br_eax_flip", +proc eaxFlip*(ctx: ptr EaxContext) {.bearSslFunc, deprecated, importc: "br_eax_flip", header: "bearssl_aead.h".} -proc eaxGetAadMac*(ctx: ptr EaxContext; st: ptr EaxState) {.inline.} = +proc eaxGetAadMac*(ctx: ptr EaxContext; st: ptr EaxState) {.inline, deprecated.} = copyMem(unsafeAddr st.st[1], unsafeAddr ctx.head, sizeof(ctx.head)) -proc eaxRun*(ctx: ptr EaxContext; encrypt: cint; data: pointer; len: int) {.bearSslFunc, +proc eaxRun*(ctx: ptr EaxContext; encrypt: cint; data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_eax_run", header: "bearssl_aead.h".} -proc eaxGetTag*(ctx: ptr EaxContext; tag: pointer) {.bearSslFunc, importc: "br_eax_get_tag", +proc eaxGetTag*(ctx: ptr EaxContext; tag: pointer) {.bearSslFunc, deprecated, importc: "br_eax_get_tag", header: "bearssl_aead.h".} -proc eaxCheckTag*(ctx: ptr EaxContext; tag: pointer): uint32 {.bearSslFunc, +proc eaxCheckTag*(ctx: ptr EaxContext; tag: pointer): uint32 {.bearSslFunc, deprecated, importc: "br_eax_check_tag", header: "bearssl_aead.h".} -proc eaxGetTagTrunc*(ctx: ptr EaxContext; tag: pointer; len: int) {.bearSslFunc, +proc eaxGetTagTrunc*(ctx: ptr EaxContext; tag: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_eax_get_tag_trunc", header: "bearssl_aead.h".} -proc eaxCheckTagTrunc*(ctx: ptr EaxContext; tag: pointer; len: int): uint32 {.bearSslFunc, +proc eaxCheckTagTrunc*(ctx: ptr EaxContext; tag: pointer; len: int): uint32 {.bearSslFunc, deprecated, importc: "br_eax_check_tag_trunc", header: "bearssl_aead.h".} var eaxVtable* {.importc: "br_eax_vtable", header: "bearssl_aead.h".}: AeadClass type - CcmContext* {.importc: "br_ccm_context", header: "bearssl_aead.h", bycopy.} = object + CcmContext* {.importc: "br_ccm_context", header: "bearssl_aead.h", bycopy, deprecated.} = object bctx* {.importc: "bctx".}: ptr ptr BlockCtrcbcClass ctr* {.importc: "ctr".}: array[16, cuchar] cbcmac* {.importc: "cbcmac".}: array[16, cuchar] @@ -1677,30 +1314,30 @@ type tagLen* {.importc: "tag_len".}: int -proc ccmInit*(ctx: ptr CcmContext; bctx: ptr ptr BlockCtrcbcClass) {.bearSslFunc, +proc ccmInit*(ctx: ptr CcmContext; bctx: ptr ptr BlockCtrcbcClass) {.bearSslFunc, deprecated, importc: "br_ccm_init", header: "bearssl_aead.h".} proc ccmReset*(ctx: ptr CcmContext; nonce: pointer; nonceLen: int; aadLen: uint64; - dataLen: uint64; tagLen: int): cint {.bearSslFunc, importc: "br_ccm_reset", + dataLen: uint64; tagLen: int): cint {.bearSslFunc, deprecated, importc: "br_ccm_reset", header: "bearssl_aead.h".} -proc ccmAadInject*(ctx: ptr CcmContext; data: pointer; len: int) {.bearSslFunc, +proc ccmAadInject*(ctx: ptr CcmContext; data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_ccm_aad_inject", header: "bearssl_aead.h".} -proc ccmFlip*(ctx: ptr CcmContext) {.bearSslFunc, importc: "br_ccm_flip", +proc ccmFlip*(ctx: ptr CcmContext) {.bearSslFunc, deprecated, importc: "br_ccm_flip", header: "bearssl_aead.h".} -proc ccmRun*(ctx: ptr CcmContext; encrypt: cint; data: pointer; len: int) {.bearSslFunc, +proc ccmRun*(ctx: ptr CcmContext; encrypt: cint; data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_ccm_run", header: "bearssl_aead.h".} -proc ccmGetTag*(ctx: ptr CcmContext; tag: pointer): int {.bearSslFunc, +proc ccmGetTag*(ctx: ptr CcmContext; tag: pointer): int {.bearSslFunc, deprecated, importc: "br_ccm_get_tag", header: "bearssl_aead.h".} -proc ccmCheckTag*(ctx: ptr CcmContext; tag: pointer): uint32 {.bearSslFunc, +proc ccmCheckTag*(ctx: ptr CcmContext; tag: pointer): uint32 {.bearSslFunc, deprecated, importc: "br_ccm_check_tag", header: "bearssl_aead.h".} type - RsaPublicKey* {.importc: "br_rsa_public_key", header: "bearssl_rsa.h", bycopy.} = object + RsaPublicKey* {.importc: "br_rsa_public_key", header: "bearssl_rsa.h", bycopy, deprecated.} = object n* {.importc: "n".}: ptr cuchar nlen* {.importc: "nlen".}: int e* {.importc: "e".}: ptr cuchar @@ -1708,7 +1345,7 @@ type type - RsaPrivateKey* {.importc: "br_rsa_private_key", header: "bearssl_rsa.h", bycopy.} = object + RsaPrivateKey* {.importc: "br_rsa_private_key", header: "bearssl_rsa.h", bycopy, deprecated.} = object nBitlen* {.importc: "n_bitlen".}: uint32 p* {.importc: "p".}: ptr cuchar plen* {.importc: "plen".}: int @@ -1723,17 +1360,17 @@ type type - RsaPublic* = proc (x: ptr cuchar; xlen: int; pk: ptr RsaPublicKey): uint32 {.bearSslFunc.} + RsaPublic* {.deprecated.} = proc (x: ptr cuchar; xlen: int; pk: ptr RsaPublicKey): uint32 {.bearSslFunc.} type - RsaPkcs1Vrfy* = proc (x: ptr cuchar; xlen: int; hashOid: ptr cuchar; hashLen: int; + RsaPkcs1Vrfy* {.deprecated.} = proc (x: ptr cuchar; xlen: int; hashOid: ptr cuchar; hashLen: int; pk: ptr RsaPublicKey; hashOut: ptr cuchar): uint32 {.bearSslFunc.} type - RsaPrivate* = proc (x: ptr cuchar; sk: ptr RsaPrivateKey): uint32 {.bearSslFunc.} + RsaPrivate* {.deprecated.} = proc (x: ptr cuchar; sk: ptr RsaPrivateKey): uint32 {.bearSslFunc.} type - RsaPkcs1Sign* = proc (hashOid: ptr cuchar; hash: ptr cuchar; hashLen: int; + RsaPkcs1Sign* {.deprecated.} = proc (hashOid: ptr cuchar; hash: ptr cuchar; hashLen: int; sk: ptr RsaPrivateKey; x: ptr cuchar): uint32 {.bearSslFunc.} const @@ -1751,156 +1388,156 @@ const const HASH_OID_SHA512* = (("\t`\x86H\x01e\x03\x04\x02\x03")) -proc rsaI32Public*(x: ptr cuchar; xlen: int; pk: ptr RsaPublicKey): uint32 {.bearSslFunc, +proc rsaI32Public*(x: ptr cuchar; xlen: int; pk: ptr RsaPublicKey): uint32 {.bearSslFunc, deprecated, importc: "br_rsa_i32_public", header: "bearssl_rsa.h".} proc rsaI32Pkcs1Vrfy*(x: ptr cuchar; xlen: int; hashOid: ptr cuchar; hashLen: int; - pk: ptr RsaPublicKey; hashOut: ptr cuchar): uint32 {.bearSslFunc, + pk: ptr RsaPublicKey; hashOut: ptr cuchar): uint32 {.bearSslFunc, deprecated, importc: "br_rsa_i32_pkcs1_vrfy", header: "bearssl_rsa.h".} -proc rsaI32Private*(x: ptr cuchar; sk: ptr RsaPrivateKey): uint32 {.bearSslFunc, +proc rsaI32Private*(x: ptr cuchar; sk: ptr RsaPrivateKey): uint32 {.bearSslFunc, deprecated, importc: "br_rsa_i32_private", header: "bearssl_rsa.h".} proc rsaI32Pkcs1Sign*(hashOid: ptr cuchar; hash: ptr cuchar; hashLen: int; - sk: ptr RsaPrivateKey; x: ptr cuchar): uint32 {.bearSslFunc, + sk: ptr RsaPrivateKey; x: ptr cuchar): uint32 {.bearSslFunc, deprecated, importc: "br_rsa_i32_pkcs1_sign", header: "bearssl_rsa.h".} -proc rsaI31Public*(x: ptr cuchar; xlen: int; pk: ptr RsaPublicKey): uint32 {.bearSslFunc, +proc rsaI31Public*(x: ptr cuchar; xlen: int; pk: ptr RsaPublicKey): uint32 {.bearSslFunc, deprecated, importc: "br_rsa_i31_public", header: "bearssl_rsa.h".} proc rsaI31Pkcs1Vrfy*(x: ptr cuchar; xlen: int; hashOid: ptr cuchar; hashLen: int; - pk: ptr RsaPublicKey; hashOut: ptr cuchar): uint32 {.bearSslFunc, + pk: ptr RsaPublicKey; hashOut: ptr cuchar): uint32 {.bearSslFunc, deprecated, importc: "br_rsa_i31_pkcs1_vrfy", header: "bearssl_rsa.h".} -proc rsaI31Private*(x: ptr cuchar; sk: ptr RsaPrivateKey): uint32 {.bearSslFunc, +proc rsaI31Private*(x: ptr cuchar; sk: ptr RsaPrivateKey): uint32 {.bearSslFunc, deprecated, importc: "br_rsa_i31_private", header: "bearssl_rsa.h".} proc rsaI31Pkcs1Sign*(hashOid: ptr cuchar; hash: ptr cuchar; hashLen: int; - sk: ptr RsaPrivateKey; x: ptr cuchar): uint32 {.bearSslFunc, + sk: ptr RsaPrivateKey; x: ptr cuchar): uint32 {.bearSslFunc, deprecated, importc: "br_rsa_i31_pkcs1_sign", header: "bearssl_rsa.h".} -proc rsaI62Public*(x: ptr cuchar; xlen: int; pk: ptr RsaPublicKey): uint32 {.bearSslFunc, +proc rsaI62Public*(x: ptr cuchar; xlen: int; pk: ptr RsaPublicKey): uint32 {.bearSslFunc, deprecated, importc: "br_rsa_i62_public", header: "bearssl_rsa.h".} proc rsaI62Pkcs1Vrfy*(x: ptr cuchar; xlen: int; hashOid: ptr cuchar; hashLen: int; - pk: ptr RsaPublicKey; hashOut: ptr cuchar): uint32 {.bearSslFunc, + pk: ptr RsaPublicKey; hashOut: ptr cuchar): uint32 {.bearSslFunc, deprecated, importc: "br_rsa_i62_pkcs1_vrfy", header: "bearssl_rsa.h".} -proc rsaI62Private*(x: ptr cuchar; sk: ptr RsaPrivateKey): uint32 {.bearSslFunc, +proc rsaI62Private*(x: ptr cuchar; sk: ptr RsaPrivateKey): uint32 {.bearSslFunc, deprecated, importc: "br_rsa_i62_private", header: "bearssl_rsa.h".} proc rsaI62Pkcs1Sign*(hashOid: ptr cuchar; hash: ptr cuchar; hashLen: int; - sk: ptr RsaPrivateKey; x: ptr cuchar): uint32 {.bearSslFunc, + sk: ptr RsaPrivateKey; x: ptr cuchar): uint32 {.bearSslFunc, deprecated, importc: "br_rsa_i62_pkcs1_sign", header: "bearssl_rsa.h".} -proc rsaI62PublicGet*(): RsaPublic {.bearSslFunc, importc: "br_rsa_i62_public_get", +proc rsaI62PublicGet*(): RsaPublic {.bearSslFunc, deprecated, importc: "br_rsa_i62_public_get", header: "bearssl_rsa.h".} -proc rsaI62Pkcs1VrfyGet*(): RsaPkcs1Vrfy {.bearSslFunc, +proc rsaI62Pkcs1VrfyGet*(): RsaPkcs1Vrfy {.bearSslFunc, deprecated, importc: "br_rsa_i62_pkcs1_vrfy_get", header: "bearssl_rsa.h".} -proc rsaI62PrivateGet*(): RsaPrivate {.bearSslFunc, importc: "br_rsa_i62_private_get", +proc rsaI62PrivateGet*(): RsaPrivate {.bearSslFunc, deprecated, importc: "br_rsa_i62_private_get", header: "bearssl_rsa.h".} -proc rsaI62Pkcs1SignGet*(): RsaPkcs1Sign {.bearSslFunc, +proc rsaI62Pkcs1SignGet*(): RsaPkcs1Sign {.bearSslFunc, deprecated, importc: "br_rsa_i62_pkcs1_sign_get", header: "bearssl_rsa.h".} -proc rsaI15Public*(x: ptr cuchar; xlen: int; pk: ptr RsaPublicKey): uint32 {.bearSslFunc, +proc rsaI15Public*(x: ptr cuchar; xlen: int; pk: ptr RsaPublicKey): uint32 {.bearSslFunc, deprecated, importc: "br_rsa_i15_public", header: "bearssl_rsa.h".} proc rsaI15Pkcs1Vrfy*(x: ptr cuchar; xlen: int; hashOid: ptr cuchar; hashLen: int; - pk: ptr RsaPublicKey; hashOut: ptr cuchar): uint32 {.bearSslFunc, + pk: ptr RsaPublicKey; hashOut: ptr cuchar): uint32 {.bearSslFunc, deprecated, importc: "br_rsa_i15_pkcs1_vrfy", header: "bearssl_rsa.h".} -proc rsaI15Private*(x: ptr cuchar; sk: ptr RsaPrivateKey): uint32 {.bearSslFunc, +proc rsaI15Private*(x: ptr cuchar; sk: ptr RsaPrivateKey): uint32 {.bearSslFunc, deprecated, importc: "br_rsa_i15_private", header: "bearssl_rsa.h".} proc rsaI15Pkcs1Sign*(hashOid: ptr cuchar; hash: ptr cuchar; hashLen: int; - sk: ptr RsaPrivateKey; x: ptr cuchar): uint32 {.bearSslFunc, + sk: ptr RsaPrivateKey; x: ptr cuchar): uint32 {.bearSslFunc, deprecated, importc: "br_rsa_i15_pkcs1_sign", header: "bearssl_rsa.h".} -proc rsaPublicGetDefault*(): RsaPublic {.bearSslFunc, +proc rsaPublicGetDefault*(): RsaPublic {.bearSslFunc, deprecated, importc: "br_rsa_public_get_default", header: "bearssl_rsa.h".} -proc rsaPrivateGetDefault*(): RsaPrivate {.bearSslFunc, +proc rsaPrivateGetDefault*(): RsaPrivate {.bearSslFunc, deprecated, importc: "br_rsa_private_get_default", header: "bearssl_rsa.h".} -proc rsaPkcs1VrfyGetDefault*(): RsaPkcs1Vrfy {.bearSslFunc, +proc rsaPkcs1VrfyGetDefault*(): RsaPkcs1Vrfy {.bearSslFunc, deprecated, importc: "br_rsa_pkcs1_vrfy_get_default", header: "bearssl_rsa.h".} -proc rsaPkcs1SignGetDefault*(): RsaPkcs1Sign {.bearSslFunc, +proc rsaPkcs1SignGetDefault*(): RsaPkcs1Sign {.bearSslFunc, deprecated, importc: "br_rsa_pkcs1_sign_get_default", header: "bearssl_rsa.h".} proc rsaSslDecrypt*(core: RsaPrivate; sk: ptr RsaPrivateKey; data: ptr cuchar; len: int): uint32 {. - bearSslFunc, importc: "br_rsa_ssl_decrypt", header: "bearssl_rsa.h".} + bearSslFunc, deprecated, importc: "br_rsa_ssl_decrypt", header: "bearssl_rsa.h".} type - RsaPssSign* = proc(rng: ptr ptr PrngClass, + RsaPssSign* {.deprecated.} = proc(rng: ptr ptr PrngClass, hf_data, hf_mgf1: ptr HashClass, hash_value: ptr cuchar, salt_len: int, sk: ptr RsaPrivateKey, x: ptr cuchar): uint32 {.bearSslFunc.} - RsaPssVrfy* = proc(x: ptr cuchar, xlen: int, + RsaPssVrfy* {.deprecated.} = proc(x: ptr cuchar, xlen: int, hf_data, hf_mgf1: ptr HashClass, hash: ptr cuchar, salt_len: int, pk: ptr RsaPublicKey): uint32 {.bearSslFunc.} -proc rsaPssSignGetDefault*(): RsaPssSign {.bearSslFunc, +proc rsaPssSignGetDefault*(): RsaPssSign {.bearSslFunc, deprecated, importc: "br_rsa_pss_sign_get_default", header: "bearssl_rsa.h".} -proc rsaPssVrfyGetDefault*(): RsaPssVrfy {.bearSslFunc, +proc rsaPssVrfyGetDefault*(): RsaPssVrfy {.bearSslFunc, deprecated, importc: "br_rsa_pss_vrfy_get_default", header: "bearssl_rsa.h".} proc rsaI15PssSign*(rng: ptr ptr PrngClass, hf_data, hf_mgf1: ptr HashClass, hash_value: ptr cuchar, salt_len: int, - sk: ptr RsaPrivateKey, x: ptr cuchar): uint32 {.bearSslFunc, + sk: ptr RsaPrivateKey, x: ptr cuchar): uint32 {.bearSslFunc, deprecated, importc: "br_rsa_i15_pss_sign", header: "bearssl_rsa.h".} proc rsaI15PssVrfy*(x: ptr cuchar, xlen: int, hf_data, hf_mgf1: ptr HashClass, hash: ptr cuchar, salt_len: int, - pk: ptr RsaPublicKey): uint32 {.bearSslFunc, + pk: ptr RsaPublicKey): uint32 {.bearSslFunc, deprecated, importc: "br_rsa_i15_pss_vrfy", header: "bearssl_rsa.h".} proc rsaI31PssSign*(rng: ptr ptr PrngClass, hf_data, hf_mgf1: ptr HashClass, hash_value: ptr cuchar, salt_len: int, - sk: ptr RsaPrivateKey, x: ptr cuchar): uint32 {.bearSslFunc, + sk: ptr RsaPrivateKey, x: ptr cuchar): uint32 {.bearSslFunc, deprecated, importc: "br_rsa_i31_pss_sign", header: "bearssl_rsa.h".} proc rsaI31PssVrfy*(x: ptr cuchar, xlen: int, hf_data, hf_mgf1: ptr HashClass, hash: ptr cuchar, salt_len: int, - pk: ptr RsaPublicKey): uint32 {.bearSslFunc, + pk: ptr RsaPublicKey): uint32 {.bearSslFunc, deprecated, importc: "br_rsa_i31_pss_vrfy", header: "bearssl_rsa.h".} proc rsaI32PssSign*(rng: ptr ptr PrngClass, hf_data, hf_mgf1: ptr HashClass, hash_value: ptr cuchar, salt_len: int, - sk: ptr RsaPrivateKey, x: ptr cuchar): uint32 {.bearSslFunc, + sk: ptr RsaPrivateKey, x: ptr cuchar): uint32 {.bearSslFunc, deprecated, importc: "br_rsa_i32_pss_sign", header: "bearssl_rsa.h".} proc rsaI32PssVrfy*(x: ptr cuchar, xlen: int, hf_data, hf_mgf1: ptr HashClass, hash: ptr cuchar, salt_len: int, - pk: ptr RsaPublicKey): uint32 {.bearSslFunc, + pk: ptr RsaPublicKey): uint32 {.bearSslFunc, deprecated, importc: "br_rsa_i32_pss_vrfy", header: "bearssl_rsa.h".} proc rsaI62PssSign*(rng: ptr ptr PrngClass, hf_data, hf_mgf1: ptr HashClass, hash_value: ptr cuchar, salt_len: int, - sk: ptr RsaPrivateKey, x: ptr cuchar): uint32 {.bearSslFunc, + sk: ptr RsaPrivateKey, x: ptr cuchar): uint32 {.bearSslFunc, deprecated, importc: "br_rsa_i62_pss_sign", header: "bearssl_rsa.h".} proc rsaI62PssVrfy*(x: ptr cuchar, xlen: int, hf_data, hf_mgf1: ptr HashClass, hash: ptr cuchar, salt_len: int, - pk: ptr RsaPublicKey): uint32 {.bearSslFunc, + pk: ptr RsaPublicKey): uint32 {.bearSslFunc, deprecated, importc: "br_rsa_i62_pss_vrfy", header: "bearssl_rsa.h".} const @@ -1994,21 +1631,21 @@ const EC_curve448* = 30 type - EcPublicKey* {.importc: "br_ec_public_key", header: "bearssl_ec.h", bycopy.} = object + EcPublicKey* {.importc: "br_ec_public_key", header: "bearssl_ec.h", bycopy, deprecated.} = object curve* {.importc: "curve".}: cint q* {.importc: "q".}: ptr cuchar qlen* {.importc: "qlen".}: int type - EcPrivateKey* {.importc: "br_ec_private_key", header: "bearssl_ec.h", bycopy.} = object + EcPrivateKey* {.importc: "br_ec_private_key", header: "bearssl_ec.h", bycopy, deprecated.} = object curve* {.importc: "curve".}: cint x* {.importc: "x".}: ptr cuchar xlen* {.importc: "xlen".}: int type - EcImpl* {.importc: "br_ec_impl", header: "bearssl_ec.h", bycopy.} = object + EcImpl* {.importc: "br_ec_impl", header: "bearssl_ec.h", bycopy, deprecated.} = object supportedCurves* {.importc: "supported_curves".}: uint32 generator* {.importc: "generator".}: proc (curve: cint; len: ptr int): ptr cuchar {.bearSslFunc.} order* {.importc: "order".}: proc (curve: cint; len: ptr int): ptr cuchar {.bearSslFunc.} @@ -2042,65 +1679,65 @@ var ecAllM15* {.importc: "br_ec_all_m15", header: "bearssl_ec.h".}: EcImpl var ecAllM31* {.importc: "br_ec_all_m31", header: "bearssl_ec.h".}: EcImpl -proc ecGetDefault*(): ptr EcImpl {.bearSslFunc, importc: "br_ec_get_default", +proc ecGetDefault*(): ptr EcImpl {.bearSslFunc, deprecated, importc: "br_ec_get_default", header: "bearssl_ec.h".} -proc ecdsaRawToAsn1*(sig: pointer; sigLen: int): int {.bearSslFunc, +proc ecdsaRawToAsn1*(sig: pointer; sigLen: int): int {.bearSslFunc, deprecated, importc: "br_ecdsa_raw_to_asn1", header: "bearssl_ec.h".} -proc ecdsaAsn1ToRaw*(sig: pointer; sigLen: int): int {.bearSslFunc, +proc ecdsaAsn1ToRaw*(sig: pointer; sigLen: int): int {.bearSslFunc, deprecated, importc: "br_ecdsa_asn1_to_raw", header: "bearssl_ec.h".} type - EcdsaSign* = proc (impl: ptr EcImpl; hf: ptr HashClass; hashValue: pointer; + EcdsaSign* {.deprecated.} = proc (impl: ptr EcImpl; hf: ptr HashClass; hashValue: pointer; sk: ptr EcPrivateKey; sig: pointer): int {.bearSslFunc.} type - EcdsaVrfy* = proc (impl: ptr EcImpl; hash: pointer; hashLen: int; pk: ptr EcPublicKey; + EcdsaVrfy* {.deprecated.} = proc (impl: ptr EcImpl; hash: pointer; hashLen: int; pk: ptr EcPublicKey; sig: pointer; sigLen: int): uint32 {.bearSslFunc.} proc ecdsaI31SignAsn1*(impl: ptr EcImpl; hf: ptr HashClass; hashValue: pointer; - sk: ptr EcPrivateKey; sig: pointer): int {.bearSslFunc, + sk: ptr EcPrivateKey; sig: pointer): int {.bearSslFunc, deprecated, importc: "br_ecdsa_i31_sign_asn1", header: "bearssl_ec.h".} proc ecdsaI31SignRaw*(impl: ptr EcImpl; hf: ptr HashClass; hashValue: pointer; - sk: ptr EcPrivateKey; sig: pointer): int {.bearSslFunc, + sk: ptr EcPrivateKey; sig: pointer): int {.bearSslFunc, deprecated, importc: "br_ecdsa_i31_sign_raw", header: "bearssl_ec.h".} proc ecdsaI31VrfyAsn1*(impl: ptr EcImpl; hash: pointer; hashLen: int; pk: ptr EcPublicKey; sig: pointer; sigLen: int): uint32 {. - bearSslFunc, importc: "br_ecdsa_i31_vrfy_asn1", header: "bearssl_ec.h".} + bearSslFunc, deprecated, importc: "br_ecdsa_i31_vrfy_asn1", header: "bearssl_ec.h".} proc ecdsaI31VrfyRaw*(impl: ptr EcImpl; hash: pointer; hashLen: int; - pk: ptr EcPublicKey; sig: pointer; sigLen: int): uint32 {.bearSslFunc, + pk: ptr EcPublicKey; sig: pointer; sigLen: int): uint32 {.bearSslFunc, deprecated, importc: "br_ecdsa_i31_vrfy_raw", header: "bearssl_ec.h".} proc ecdsaI15SignAsn1*(impl: ptr EcImpl; hf: ptr HashClass; hashValue: pointer; - sk: ptr EcPrivateKey; sig: pointer): int {.bearSslFunc, + sk: ptr EcPrivateKey; sig: pointer): int {.bearSslFunc, deprecated, importc: "br_ecdsa_i15_sign_asn1", header: "bearssl_ec.h".} proc ecdsaI15SignRaw*(impl: ptr EcImpl; hf: ptr HashClass; hashValue: pointer; - sk: ptr EcPrivateKey; sig: pointer): int {.bearSslFunc, + sk: ptr EcPrivateKey; sig: pointer): int {.bearSslFunc, deprecated, importc: "br_ecdsa_i15_sign_raw", header: "bearssl_ec.h".} proc ecdsaI15VrfyAsn1*(impl: ptr EcImpl; hash: pointer; hashLen: int; pk: ptr EcPublicKey; sig: pointer; sigLen: int): uint32 {. - bearSslFunc, importc: "br_ecdsa_i15_vrfy_asn1", header: "bearssl_ec.h".} + bearSslFunc, deprecated, importc: "br_ecdsa_i15_vrfy_asn1", header: "bearssl_ec.h".} proc ecdsaI15VrfyRaw*(impl: ptr EcImpl; hash: pointer; hashLen: int; - pk: ptr EcPublicKey; sig: pointer; sigLen: int): uint32 {.bearSslFunc, + pk: ptr EcPublicKey; sig: pointer; sigLen: int): uint32 {.bearSslFunc, deprecated, importc: "br_ecdsa_i15_vrfy_raw", header: "bearssl_ec.h".} -proc ecdsaSignAsn1GetDefault*(): EcdsaSign {.bearSslFunc, +proc ecdsaSignAsn1GetDefault*(): EcdsaSign {.bearSslFunc, deprecated, importc: "br_ecdsa_sign_asn1_get_default", header: "bearssl_ec.h".} -proc ecdsaSignRawGetDefault*(): EcdsaSign {.bearSslFunc, +proc ecdsaSignRawGetDefault*(): EcdsaSign {.bearSslFunc, deprecated, importc: "br_ecdsa_sign_raw_get_default", header: "bearssl_ec.h".} -proc ecdsaVrfyAsn1GetDefault*(): EcdsaVrfy {.bearSslFunc, +proc ecdsaVrfyAsn1GetDefault*(): EcdsaVrfy {.bearSslFunc, deprecated, importc: "br_ecdsa_vrfy_asn1_get_default", header: "bearssl_ec.h".} -proc ecdsaVrfyRawGetDefault*(): EcdsaVrfy {.bearSslFunc, +proc ecdsaVrfyRawGetDefault*(): EcdsaVrfy {.bearSslFunc, deprecated, importc: "br_ecdsa_vrfy_raw_get_default", header: "bearssl_ec.h".} const @@ -2199,13 +1836,13 @@ type rsa* {.importc: "rsa".}: RsaPublicKey ec* {.importc: "ec".}: EcPublicKey - X509Pkey* {.importc: "br_x509_pkey", header: "bearssl_x509.h", bycopy.} = object + X509Pkey* {.importc: "br_x509_pkey", header: "bearssl_x509.h", bycopy, deprecated.} = object keyType* {.importc: "key_type".}: cuchar key* {.importc: "key".}: INNER_C_UNION_2211491720 type - X500Name* {.importc: "br_x500_name", header: "bearssl_x509.h", bycopy.} = object + X500Name* {.importc: "br_x500_name", header: "bearssl_x509.h", bycopy, deprecated.} = object data* {.importc: "data".}: ptr cuchar len* {.importc: "len".}: int @@ -2234,7 +1871,7 @@ const KEYTYPE_SIGN* = 0x00000020 type - X509Class* {.importc: "br_x509_class", header: "bearssl_x509.h", bycopy.} = object + X509Class* {.importc: "br_x509_class", header: "bearssl_x509.h", bycopy, deprecated.} = object contextSize* {.importc: "context_size".}: int startChain* {.importc: "start_chain".}: proc (ctx: ptr ptr X509Class; serverName: cstring) {.bearSslFunc.} @@ -2249,7 +1886,7 @@ type type X509KnownkeyContext* {.importc: "br_x509_knownkey_context", - header: "bearssl_x509.h", bycopy.} = object + header: "bearssl_x509.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr X509Class pkey* {.importc: "pkey".}: X509Pkey usages* {.importc: "usages".}: cuint @@ -2259,12 +1896,12 @@ var x509KnownkeyVtable* {.importc: "br_x509_knownkey_vtable", header: "bearssl_x509.h".}: X509Class proc x509KnownkeyInitRsa*(ctx: ptr X509KnownkeyContext; pk: ptr RsaPublicKey; - usages: cuint) {.bearSslFunc, + usages: cuint) {.bearSslFunc, deprecated, importc: "br_x509_knownkey_init_rsa", header: "bearssl_x509.h".} proc x509KnownkeyInitEc*(ctx: ptr X509KnownkeyContext; pk: ptr EcPublicKey; - usages: cuint) {.bearSslFunc, + usages: cuint) {.bearSslFunc, deprecated, importc: "br_x509_knownkey_init_ec", header: "bearssl_x509.h".} @@ -2273,7 +1910,7 @@ const X509_BUFSIZE_SIG* = 512 type - NameElement* {.importc: "br_name_element", header: "bearssl_x509.h", bycopy.} = object + NameElement* {.importc: "br_name_element", header: "bearssl_x509.h", bycopy, deprecated.} = object oid* {.importc: "oid".}: ptr cuchar buf* {.importc: "buf".}: cstring len* {.importc: "len".}: int @@ -2281,13 +1918,13 @@ type type - INNER_C_STRUCT_573696436* {.importc: "no_name", header: "bearssl_x509.h", bycopy.} = object + INNER_C_STRUCT_573696436* {.importc: "no_name", header: "bearssl_x509.h", bycopy, deprecated.} = object dp* {.importc: "dp".}: ptr uint32 rp* {.importc: "rp".}: ptr uint32 ip* {.importc: "ip".}: ptr cuchar X509MinimalContext* {.importc: "br_x509_minimal_context", - header: "bearssl_x509.h", bycopy.} = object + header: "bearssl_x509.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr X509Class pkey* {.importc: "pkey".}: X509Pkey cpu* {.importc: "cpu".}: INNER_C_STRUCT_573696436 @@ -2333,24 +1970,24 @@ var x509MinimalVtable* {.importc: "br_x509_minimal_vtable", header: "bearssl_x50 proc x509MinimalInit*(ctx: ptr X509MinimalContext; dnHashImpl: ptr HashClass; trustAnchors: ptr X509TrustAnchor; trustAnchorsNum: int) {. - bearSslFunc, importc: "br_x509_minimal_init", header: "bearssl_x509.h".} + bearSslFunc, deprecated, importc: "br_x509_minimal_init", header: "bearssl_x509.h".} proc x509MinimalSetHash*(ctx: ptr X509MinimalContext; id: cint; impl: ptr HashClass) {. inline.} = multihashSetimpl(addr(ctx.mhash), id, impl) proc x509MinimalSetRsa*(ctx: ptr X509MinimalContext; irsa: RsaPkcs1Vrfy) {.inline, - bearSslFunc.} = + bearSslFunc, deprecated.} = ctx.irsa = irsa proc x509MinimalSetEcdsa*(ctx: ptr X509MinimalContext; iec: ptr EcImpl; - iecdsa: EcdsaVrfy) {.inline.} = + iecdsa: EcdsaVrfy) {.inline, deprecated.} = ctx.iecdsa = iecdsa ctx.iec = iec proc x509MinimalInitFull*(ctx: ptr X509MinimalContext; trustAnchors: ptr X509TrustAnchor; trustAnchorsNum: int) {. - bearSslFunc, importc: "br_x509_minimal_init_full", header: "bearssl_x509.h".} + bearSslFunc, deprecated, importc: "br_x509_minimal_init_full", header: "bearssl_x509.h".} proc x509MinimalSetTime*(ctx: ptr X509MinimalContext; days: uint32; seconds: uint32) {. inline.} = @@ -2358,22 +1995,22 @@ proc x509MinimalSetTime*(ctx: ptr X509MinimalContext; days: uint32; seconds: uin ctx.seconds = seconds proc x509MinimalSetMinrsa*(ctx: ptr X509MinimalContext; byteLength: cint) {.inline, - bearSslFunc.} = + bearSslFunc, deprecated.} = ctx.minRsaSize = (int16)(byteLength - 128) proc x509MinimalSetNameElements*(ctx: ptr X509MinimalContext; elts: ptr NameElement; - numElts: int) {.inline.} = + numElts: int) {.inline, deprecated.} = ctx.nameElts = elts ctx.numNameElts = numElts type - INNER_C_STRUCT_161597942* {.importc: "no_name", header: "bearssl_x509.h", bycopy.} = object + INNER_C_STRUCT_161597942* {.importc: "no_name", header: "bearssl_x509.h", bycopy, deprecated.} = object dp* {.importc: "dp".}: ptr uint32 rp* {.importc: "rp".}: ptr uint32 ip* {.importc: "ip".}: ptr cuchar X509DecoderContext* {.importc: "br_x509_decoder_context", - header: "bearssl_x509.h", bycopy.} = object + header: "bearssl_x509.h", bycopy, deprecated.} = object pkey* {.importc: "pkey".}: X509Pkey cpu* {.importc: "cpu".}: INNER_C_STRUCT_161597942 dpStack* {.importc: "dp_stack".}: array[32, uint32] @@ -2398,36 +2035,36 @@ type proc x509DecoderInit*(ctx: ptr X509DecoderContext; appendDn: proc (ctx: pointer; - buf: pointer; len: int) {.bearSslFunc.}; appendDnCtx: pointer) {.bearSslFunc, + buf: pointer; len: int) {.bearSslFunc.}; appendDnCtx: pointer) {.bearSslFunc, deprecated, importc: "br_x509_decoder_init", header: "bearssl_x509.h".} -proc x509DecoderPush*(ctx: ptr X509DecoderContext; data: pointer; len: int) {.bearSslFunc, +proc x509DecoderPush*(ctx: ptr X509DecoderContext; data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_x509_decoder_push", header: "bearssl_x509.h".} -proc x509DecoderGetPkey*(ctx: ptr X509DecoderContext): ptr X509Pkey {.inline.} = +proc x509DecoderGetPkey*(ctx: ptr X509DecoderContext): ptr X509Pkey {.inline, deprecated.} = if ctx.decoded and ctx.err == 0: return addr(ctx.pkey) else: return nil -proc x509DecoderLastError*(ctx: ptr X509DecoderContext): cint {.inline.} = +proc x509DecoderLastError*(ctx: ptr X509DecoderContext): cint {.inline, deprecated.} = if ctx.err != 0: return ctx.err if not ctx.decoded: return ERR_X509_TRUNCATED return 0 -proc x509DecoderIsCA*(ctx: ptr X509DecoderContext): cint {.inline.} = +proc x509DecoderIsCA*(ctx: ptr X509DecoderContext): cint {.inline, deprecated.} = return cint ctx.isCA -proc x509DecoderGetSignerKeyType*(ctx: ptr X509DecoderContext): cint {.inline.} = +proc x509DecoderGetSignerKeyType*(ctx: ptr X509DecoderContext): cint {.inline, deprecated.} = return cint ctx.signerKeyType -proc x509DecoderGetSignerHashId*(ctx: ptr X509DecoderContext): cint {.inline.} = +proc x509DecoderGetSignerHashId*(ctx: ptr X509DecoderContext): cint {.inline, deprecated.} = return cint ctx.signerHashId type - X509Certificate* {.importc: "br_x509_certificate", header: "bearssl_x509.h", bycopy.} = object + X509Certificate* {.importc: "br_x509_certificate", header: "bearssl_x509.h", bycopy, deprecated.} = object data* {.importc: "data".}: ptr cuchar dataLen* {.importc: "data_len".}: int @@ -2445,7 +2082,7 @@ type ip* {.importc: "ip".}: ptr cuchar SkeyDecoderContext* {.importc: "br_skey_decoder_context", - header: "bearssl_x509.h", bycopy.} = object + header: "bearssl_x509.h", bycopy, deprecated.} = object key* {.importc: "key".}: INNER_C_UNION_3754611343 cpu* {.importc: "cpu".}: INNER_C_STRUCT_3633027466 dpStack* {.importc: "dp_stack".}: array[32, uint32] @@ -2458,20 +2095,20 @@ type keyData* {.importc: "key_data".}: array[3 * X509_BUFSIZE_SIG, cuchar] -proc skeyDecoderInit*(ctx: ptr SkeyDecoderContext) {.bearSslFunc, +proc skeyDecoderInit*(ctx: ptr SkeyDecoderContext) {.bearSslFunc, deprecated, importc: "br_skey_decoder_init", header: "bearssl_x509.h".} -proc skeyDecoderPush*(ctx: ptr SkeyDecoderContext; data: pointer; len: int) {.bearSslFunc, +proc skeyDecoderPush*(ctx: ptr SkeyDecoderContext; data: pointer; len: int) {.bearSslFunc, deprecated, importc: "br_skey_decoder_push", header: "bearssl_x509.h".} -proc skeyDecoderLastError*(ctx: ptr SkeyDecoderContext): cint {.inline.} = +proc skeyDecoderLastError*(ctx: ptr SkeyDecoderContext): cint {.inline, deprecated.} = if ctx.err != 0: return ctx.err if ctx.keyType == '\0'.cuchar: return ERR_X509_TRUNCATED return 0 -proc skeyDecoderKeyType*(ctx: ptr SkeyDecoderContext): cint {.inline.} = +proc skeyDecoderKeyType*(ctx: ptr SkeyDecoderContext): cint {.inline, deprecated.} = if ctx.err == 0: return cint ctx.keyType else: @@ -2598,7 +2235,7 @@ const ERR_SEND_FATAL_ALERT* = 512 type - SslrecInClass* {.importc: "br_sslrec_in_class", header: "bearssl_ssl.h", bycopy.} = object + SslrecInClass* {.importc: "br_sslrec_in_class", header: "bearssl_ssl.h", bycopy, deprecated.} = object contextSize* {.importc: "context_size".}: int checkLength* {.importc: "check_length".}: proc (ctx: ptr ptr SslrecInClass; recordLen: int): cint {.bearSslFunc.} @@ -2607,7 +2244,7 @@ type len: ptr int): ptr cuchar {.bearSslFunc.} type - SslrecOutClass* {.importc: "br_sslrec_out_class", header: "bearssl_ssl.h", bycopy.} = object + SslrecOutClass* {.importc: "br_sslrec_out_class", header: "bearssl_ssl.h", bycopy, deprecated.} = object contextSize* {.importc: "context_size".}: int maxPlaintext* {.importc: "max_plaintext".}: proc (ctx: ptr ptr SslrecOutClass; start: ptr int; `end`: ptr int) {.bearSslFunc.} @@ -2618,7 +2255,7 @@ type type SslrecOutClearContext* {.importc: "br_sslrec_out_clear_context", - header: "bearssl_ssl.h", bycopy.} = object + header: "bearssl_ssl.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr SslrecOutClass @@ -2637,7 +2274,7 @@ type type SslrecOutCbcClass* {.importc: "br_sslrec_out_cbc_class", - header: "bearssl_ssl.h", bycopy.} = object + header: "bearssl_ssl.h", bycopy, deprecated.} = object inner* {.importc: "inner".}: SslrecOutClass init* {.importc: "init".}: proc (ctx: ptr ptr SslrecOutCbcClass; bcImpl: ptr BlockCbcencClass; bcKey: pointer; @@ -2653,7 +2290,7 @@ type des* {.importc: "des".}: DesGenCbcdecKeys SslrecInCbcContext* {.importc: "br_sslrec_in_cbc_context", - header: "bearssl_ssl.h", bycopy.} = object + header: "bearssl_ssl.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr SslrecInCbcClass seq* {.importc: "seq".}: uint64 bc* {.importc: "bc".}: INNER_C_UNION_2105460304 @@ -2673,7 +2310,7 @@ type des* {.importc: "des".}: DesGenCbcencKeys SslrecOutCbcContext* {.importc: "br_sslrec_out_cbc_context", - header: "bearssl_ssl.h", bycopy.} = object + header: "bearssl_ssl.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr SslrecOutCbcClass seq* {.importc: "seq".}: uint64 bc* {.importc: "bc".}: INNER_C_UNION_3724465237 @@ -2696,7 +2333,7 @@ type type SslrecOutGcmClass* {.importc: "br_sslrec_out_gcm_class", - header: "bearssl_ssl.h", bycopy.} = object + header: "bearssl_ssl.h", bycopy, deprecated.} = object inner* {.importc: "inner".}: SslrecOutClass init* {.importc: "init".}: proc (ctx: ptr ptr SslrecOutGcmClass; bcImpl: ptr BlockCtrClass; key: pointer; @@ -2731,7 +2368,7 @@ var sslrecOutGcmVtable* {.importc: "br_sslrec_out_gcm_vtable", type SslrecInChapolClass* {.importc: "br_sslrec_in_chapol_class", - header: "bearssl_ssl.h", bycopy.} = object + header: "bearssl_ssl.h", bycopy, deprecated.} = object inner* {.importc: "inner".}: SslrecInClass init* {.importc: "init".}: proc (ctx: ptr ptr SslrecInChapolClass; ichacha: Chacha20Run; ipoly: Poly1305Run; @@ -2739,7 +2376,7 @@ type type SslrecOutChapolClass* {.importc: "br_sslrec_out_chapol_class", - header: "bearssl_ssl.h", bycopy.} = object + header: "bearssl_ssl.h", bycopy, deprecated.} = object inner* {.importc: "inner".}: SslrecOutClass init* {.importc: "init".}: proc (ctx: ptr ptr SslrecOutChapolClass; ichacha: Chacha20Run; ipoly: Poly1305Run; @@ -2753,7 +2390,7 @@ type `out`* {.importc: "out".}: ptr SslrecOutChapolClass SslrecChapolContext* {.importc: "br_sslrec_chapol_context", - header: "bearssl_ssl.h", bycopy.} = object + header: "bearssl_ssl.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: INNER_C_UNION_1683842004 seq* {.importc: "seq".}: uint64 key* {.importc: "key".}: array[32, cuchar] @@ -2770,7 +2407,7 @@ var sslrecOutChapolVtable* {.importc: "br_sslrec_out_chapol_vtable", type SslSessionParameters* {.importc: "br_ssl_session_parameters", - header: "bearssl_ssl.h", bycopy.} = object + header: "bearssl_ssl.h", bycopy, deprecated.} = object sessionId* {.importc: "session_id".}: array[32, cuchar] sessionIdLen* {.importc: "session_id_len".}: byte version* {.importc: "version".}: uint16 @@ -2797,7 +2434,7 @@ type gcm* {.importc: "gcm".}: SslrecGcmContext chapol* {.importc: "chapol".}: SslrecChapolContext - INNER_C_STRUCT_671658464* {.importc: "no_name", header: "bearssl_ssl.h", bycopy.} = object + INNER_C_STRUCT_671658464* {.importc: "no_name", header: "bearssl_ssl.h", bycopy, deprecated.} = object dp* {.importc: "dp".}: ptr uint32 rp* {.importc: "rp".}: ptr uint32 ip* {.importc: "ip".}: ptr cuchar @@ -2889,16 +2526,16 @@ type iecdsa* {.importc: "iecdsa".}: EcdsaVrfy -proc sslEngineGetFlags*(cc: ptr SslEngineContext): uint32 {.inline.} = +proc sslEngineGetFlags*(cc: ptr SslEngineContext): uint32 {.inline, deprecated.} = return cc.flags -proc sslEngineSetAllFlags*(cc: ptr SslEngineContext; flags: uint32) {.inline.} = +proc sslEngineSetAllFlags*(cc: ptr SslEngineContext; flags: uint32) {.inline, deprecated.} = cc.flags = flags -proc sslEngineAddFlags*(cc: ptr SslEngineContext; flags: uint32) {.inline.} = +proc sslEngineAddFlags*(cc: ptr SslEngineContext; flags: uint32) {.inline, deprecated.} = cc.flags = cc.flags or flags -proc sslEngineRemoveFlags*(cc: ptr SslEngineContext; flags: uint32) {.inline.} = +proc sslEngineRemoveFlags*(cc: ptr SslEngineContext; flags: uint32) {.inline, deprecated.} = cc.flags = cc.flags and not flags const @@ -2914,24 +2551,24 @@ const OPT_FAIL_ON_ALPN_MISMATCH* = (1'u32 shl 3) proc sslEngineSetVersions*(cc: ptr SslEngineContext; versionMin: uint16; - versionMax: uint16) {.inline.} = + versionMax: uint16) {.inline, deprecated.} = cc.versionMin = versionMin cc.versionMax = versionMax proc sslEngineSetSuites*(cc: ptr SslEngineContext; suites: ptr uint16; - suitesNum: int) {.bearSslFunc, + suitesNum: int) {.bearSslFunc, deprecated, importc: "br_ssl_engine_set_suites", header: "bearssl_ssl.h".} proc sslEngineSetX509*(cc: ptr SslEngineContext; x509ctx: ptr ptr X509Class) {.inline, - bearSslFunc.} = + bearSslFunc, deprecated.} = cc.x509ctx = x509ctx proc sslEngineSetProtocolNames*(ctx: ptr SslEngineContext; names: cstringArray; - num: int) {.inline.} = + num: int) {.inline, deprecated.} = ctx.protocolNames = names ctx.protocolNamesNum = uint16 num -proc sslEngineGetSelectedProtocol*(ctx: ptr SslEngineContext): cstring {.inline.} = +proc sslEngineGetSelectedProtocol*(ctx: ptr SslEngineContext): cstring {.inline, deprecated.} = var k: cuint k = ctx.selectedProtocol return if (k == 0 or k == 0x0000FFFF): nil else: ctx.protocolNames[k - 1] @@ -2941,127 +2578,127 @@ proc sslEngineSetHash*(ctx: ptr SslEngineContext; id: cint; impl: ptr HashClass) multihashSetimpl(addr(ctx.mhash), id, impl) proc sslEngineGetHash*(ctx: ptr SslEngineContext; id: cint): ptr HashClass {.inline, - bearSslFunc.} = + bearSslFunc, deprecated.} = return multihashGetimpl(addr(ctx.mhash), id) -proc sslEngineSetPrf10*(cc: ptr SslEngineContext; impl: TlsPrfImpl) {.inline.} = +proc sslEngineSetPrf10*(cc: ptr SslEngineContext; impl: TlsPrfImpl) {.inline, deprecated.} = cc.prf10 = impl -proc sslEngineSetPrfSha256*(cc: ptr SslEngineContext; impl: TlsPrfImpl) {.inline.} = +proc sslEngineSetPrfSha256*(cc: ptr SslEngineContext; impl: TlsPrfImpl) {.inline, deprecated.} = cc.prfSha256 = impl -proc sslEngineSetPrfSha384*(cc: ptr SslEngineContext; impl: TlsPrfImpl) {.inline.} = +proc sslEngineSetPrfSha384*(cc: ptr SslEngineContext; impl: TlsPrfImpl) {.inline, deprecated.} = cc.prfSha384 = impl proc sslEngineSetAesCbc*(cc: ptr SslEngineContext; implEnc: ptr BlockCbcencClass; - implDec: ptr BlockCbcdecClass) {.inline.} = + implDec: ptr BlockCbcdecClass) {.inline, deprecated.} = cc.iaesCbcenc = implEnc cc.iaesCbcdec = implDec -proc sslEngineSetDefaultAesCbc*(cc: ptr SslEngineContext) {.bearSslFunc, +proc sslEngineSetDefaultAesCbc*(cc: ptr SslEngineContext) {.bearSslFunc, deprecated, importc: "br_ssl_engine_set_default_aes_cbc", header: "bearssl_ssl.h".} proc sslEngineSetAesCtr*(cc: ptr SslEngineContext; impl: ptr BlockCtrClass) {.inline, - bearSslFunc.} = + bearSslFunc, deprecated.} = cc.iaesCtr = impl -proc sslEngineSetDefaultAesGcm*(cc: ptr SslEngineContext) {.bearSslFunc, +proc sslEngineSetDefaultAesGcm*(cc: ptr SslEngineContext) {.bearSslFunc, deprecated, importc: "br_ssl_engine_set_default_aes_gcm", header: "bearssl_ssl.h".} proc sslEngineSetDesCbc*(cc: ptr SslEngineContext; implEnc: ptr BlockCbcencClass; - implDec: ptr BlockCbcdecClass) {.inline.} = + implDec: ptr BlockCbcdecClass) {.inline, deprecated.} = cc.idesCbcenc = implEnc cc.idesCbcdec = implDec -proc sslEngineSetDefaultDesCbc*(cc: ptr SslEngineContext) {.bearSslFunc, +proc sslEngineSetDefaultDesCbc*(cc: ptr SslEngineContext) {.bearSslFunc, deprecated, importc: "br_ssl_engine_set_default_des_cbc", header: "bearssl_ssl.h".} -proc sslEngineSetGhash*(cc: ptr SslEngineContext; impl: Ghash) {.inline.} = +proc sslEngineSetGhash*(cc: ptr SslEngineContext; impl: Ghash) {.inline, deprecated.} = cc.ighash = impl proc sslEngineSetChacha20*(cc: ptr SslEngineContext; ichacha: Chacha20Run) {.inline, - bearSslFunc.} = + bearSslFunc, deprecated.} = cc.ichacha = ichacha proc sslEngineSetPoly1305*(cc: ptr SslEngineContext; ipoly: Poly1305Run) {.inline, - bearSslFunc.} = + bearSslFunc, deprecated.} = cc.ipoly = ipoly -proc sslEngineSetDefaultChapol*(cc: ptr SslEngineContext) {.bearSslFunc, +proc sslEngineSetDefaultChapol*(cc: ptr SslEngineContext) {.bearSslFunc, deprecated, importc: "br_ssl_engine_set_default_chapol", header: "bearssl_ssl.h".} proc sslEngineSetCbc*(cc: ptr SslEngineContext; implIn: ptr SslrecInCbcClass; - implOut: ptr SslrecOutCbcClass) {.inline.} = + implOut: ptr SslrecOutCbcClass) {.inline, deprecated.} = cc.icbcIn = implIn cc.icbcOut = implOut proc sslEngineSetGcm*(cc: ptr SslEngineContext; implIn: ptr SslrecInGcmClass; - implOut: ptr SslrecOutGcmClass) {.inline.} = + implOut: ptr SslrecOutGcmClass) {.inline, deprecated.} = cc.igcmIn = implIn cc.igcmOut = implOut proc sslEngineSetChapol*(cc: ptr SslEngineContext; implIn: ptr SslrecInChapolClass; - implOut: ptr SslrecOutChapolClass) {.inline.} = + implOut: ptr SslrecOutChapolClass) {.inline, deprecated.} = cc.ichapolIn = implIn cc.ichapolOut = implOut -proc sslEngineSetEc*(cc: ptr SslEngineContext; iec: ptr EcImpl) {.inline.} = +proc sslEngineSetEc*(cc: ptr SslEngineContext; iec: ptr EcImpl) {.inline, deprecated.} = cc.iec = iec -proc sslEngineSetDefaultEc*(cc: ptr SslEngineContext) {.bearSslFunc, +proc sslEngineSetDefaultEc*(cc: ptr SslEngineContext) {.bearSslFunc, deprecated, importc: "br_ssl_engine_set_default_ec", header: "bearssl_ssl.h".} -proc sslEngineGetEc*(cc: ptr SslEngineContext): ptr EcImpl {.inline.} = +proc sslEngineGetEc*(cc: ptr SslEngineContext): ptr EcImpl {.inline, deprecated.} = return cc.iec proc sslEngineSetRsavrfy*(cc: ptr SslEngineContext; irsavrfy: RsaPkcs1Vrfy) {.inline, - bearSslFunc.} = + bearSslFunc, deprecated.} = cc.irsavrfy = irsavrfy -proc sslEngineSetDefaultRsavrfy*(cc: ptr SslEngineContext) {.bearSslFunc, +proc sslEngineSetDefaultRsavrfy*(cc: ptr SslEngineContext) {.bearSslFunc, deprecated, importc: "br_ssl_engine_set_default_rsavrfy", header: "bearssl_ssl.h".} -proc sslEngineGetRsavrfy*(cc: ptr SslEngineContext): RsaPkcs1Vrfy {.inline.} = +proc sslEngineGetRsavrfy*(cc: ptr SslEngineContext): RsaPkcs1Vrfy {.inline, deprecated.} = return cc.irsavrfy -proc sslEngineSetEcdsa*(cc: ptr SslEngineContext; iecdsa: EcdsaVrfy) {.inline.} = +proc sslEngineSetEcdsa*(cc: ptr SslEngineContext; iecdsa: EcdsaVrfy) {.inline, deprecated.} = cc.iecdsa = iecdsa -proc sslEngineSetDefaultEcdsa*(cc: ptr SslEngineContext) {.bearSslFunc, +proc sslEngineSetDefaultEcdsa*(cc: ptr SslEngineContext) {.bearSslFunc, deprecated, importc: "br_ssl_engine_set_default_ecdsa", header: "bearssl_ssl.h".} -proc sslEngineGetEcdsa*(cc: ptr SslEngineContext): EcdsaVrfy {.inline.} = +proc sslEngineGetEcdsa*(cc: ptr SslEngineContext): EcdsaVrfy {.inline, deprecated.} = return cc.iecdsa proc sslEngineSetBuffer*(cc: ptr SslEngineContext, iobuf: ptr byte, iobufLen: uint, bidi: cint) {. - bearSslFunc, importc: "br_ssl_engine_set_buffer", header: "bearssl_ssl.h".} + bearSslFunc, deprecated, importc: "br_ssl_engine_set_buffer", header: "bearssl_ssl.h".} proc sslEngineSetBuffersBidi*(cc: ptr SslEngineContext, ibuf: ptr byte, ibufLen: uint, obuf: ptr byte, obufLen: uint) {. - bearSslFunc, importc: "br_ssl_engine_set_buffers_bidi", header: "bearssl_ssl.h".} + bearSslFunc, deprecated, importc: "br_ssl_engine_set_buffers_bidi", header: "bearssl_ssl.h".} proc sslEngineInjectEntropy*(cc: ptr SslEngineContext; data: pointer; len: int) {. - bearSslFunc, importc: "br_ssl_engine_inject_entropy", header: "bearssl_ssl.h".} + bearSslFunc, deprecated, importc: "br_ssl_engine_inject_entropy", header: "bearssl_ssl.h".} -proc sslEngineGetServerName*(cc: ptr SslEngineContext): cstring {.inline.} = +proc sslEngineGetServerName*(cc: ptr SslEngineContext): cstring {.inline, deprecated.} = return addr cc.serverName -proc sslEngineGetVersion*(cc: ptr SslEngineContext): cuint {.inline.} = +proc sslEngineGetVersion*(cc: ptr SslEngineContext): cuint {.inline, deprecated.} = return cc.session.version proc sslEngineGetSessionParameters*(cc: ptr SslEngineContext; - pp: ptr SslSessionParameters) {.inline.} = + pp: ptr SslSessionParameters) {.inline, deprecated.} = copyMem(pp, addr(cc.session), sizeof(pp[])) proc sslEngineSetSessionParameters*(cc: ptr SslEngineContext; - pp: ptr SslSessionParameters) {.inline.} = + pp: ptr SslSessionParameters) {.inline, deprecated.} = copyMem(addr(cc.session), pp, sizeof(pp[])) -proc sslEngineGetEcdheCurve*(cc: ptr SslEngineContext): cint {.inline.} = +proc sslEngineGetEcdheCurve*(cc: ptr SslEngineContext): cint {.inline, deprecated.} = return cint cc.ecdheCurve -proc sslEngineCurrentState*(cc: ptr SslEngineContext): cuint {.bearSslFunc, +proc sslEngineCurrentState*(cc: ptr SslEngineContext): cuint {.bearSslFunc, deprecated, importc: "br_ssl_engine_current_state", header: "bearssl_ssl.h".} const @@ -3079,56 +2716,56 @@ const const SSL_RECVAPP* = 0x00000010 -proc sslEngineLastError*(cc: ptr SslEngineContext): cint {.inline.} = +proc sslEngineLastError*(cc: ptr SslEngineContext): cint {.inline, deprecated.} = return cc.err proc sslEngineSendappBuf*(cc: ptr SslEngineContext, length: var uint): ptr byte {. - bearSslFunc, importc: "br_ssl_engine_sendapp_buf", header: "bearssl_ssl.h".} + bearSslFunc, deprecated, importc: "br_ssl_engine_sendapp_buf", header: "bearssl_ssl.h".} proc sslEngineSendappAck*(cc: ptr SslEngineContext, length: uint) {. - bearSslFunc, importc: "br_ssl_engine_sendapp_ack", header: "bearssl_ssl.h".} + bearSslFunc, deprecated, importc: "br_ssl_engine_sendapp_ack", header: "bearssl_ssl.h".} proc sslEngineRecvappBuf*(cc: ptr SslEngineContext, length: var uint): ptr byte {. - bearSslFunc, importc: "br_ssl_engine_recvapp_buf", header: "bearssl_ssl.h".} + bearSslFunc, deprecated, importc: "br_ssl_engine_recvapp_buf", header: "bearssl_ssl.h".} proc sslEngineRecvappAck*(cc: ptr SslEngineContext, length: uint) {. - bearSslFunc, importc: "br_ssl_engine_recvapp_ack", header: "bearssl_ssl.h".} + bearSslFunc, deprecated, importc: "br_ssl_engine_recvapp_ack", header: "bearssl_ssl.h".} proc sslEngineSendrecBuf*(cc: ptr SslEngineContext, length: var uint): ptr byte {. - bearSslFunc, importc: "br_ssl_engine_sendrec_buf", header: "bearssl_ssl.h".} + bearSslFunc, deprecated, importc: "br_ssl_engine_sendrec_buf", header: "bearssl_ssl.h".} proc sslEngineSendrecAck*(cc: ptr SslEngineContext, length: uint) {. - bearSslFunc, importc: "br_ssl_engine_sendrec_ack", header: "bearssl_ssl.h".} + bearSslFunc, deprecated, importc: "br_ssl_engine_sendrec_ack", header: "bearssl_ssl.h".} proc sslEngineRecvrecBuf*(cc: ptr SslEngineContext, length: var uint): ptr byte {. - bearSslFunc, importc: "br_ssl_engine_recvrec_buf", header: "bearssl_ssl.h".} + bearSslFunc, deprecated, importc: "br_ssl_engine_recvrec_buf", header: "bearssl_ssl.h".} proc sslEngineRecvrecAck*(cc: ptr SslEngineContext; length: uint) {. - bearSslFunc, importc: "br_ssl_engine_recvrec_ack", header: "bearssl_ssl.h".} + bearSslFunc, deprecated, importc: "br_ssl_engine_recvrec_ack", header: "bearssl_ssl.h".} proc sslEngineFlush*(cc: ptr SslEngineContext; force: cint) {. - bearSslFunc, importc: "br_ssl_engine_flush", header: "bearssl_ssl.h".} + bearSslFunc, deprecated, importc: "br_ssl_engine_flush", header: "bearssl_ssl.h".} proc sslEngineClose*(cc: ptr SslEngineContext) {. - bearSslFunc, importc: "br_ssl_engine_close", header: "bearssl_ssl.h".} + bearSslFunc, deprecated, importc: "br_ssl_engine_close", header: "bearssl_ssl.h".} proc sslEngineRenegotiate*(cc: ptr SslEngineContext): cint {. - bearSslFunc, importc: "br_ssl_engine_renegotiate", header: "bearssl_ssl.h".} + bearSslFunc, deprecated, importc: "br_ssl_engine_renegotiate", header: "bearssl_ssl.h".} proc sslKeyExport*(cc: ptr SslEngineContext; dst: pointer; len: int; label: cstring; - context: pointer; contextLen: int): cint {.bearSslFunc, + context: pointer; contextLen: int): cint {.bearSslFunc, deprecated, importc: "br_ssl_key_export", header: "bearssl_ssl.h".} type SslClientCertificate* {.importc: "br_ssl_client_certificate", - header: "bearssl_ssl.h", bycopy.} = object + header: "bearssl_ssl.h", bycopy, deprecated.} = object authType* {.importc: "auth_type".}: cint hashId* {.importc: "hash_id".}: cint chain* {.importc: "chain".}: ptr X509Certificate @@ -3164,7 +2801,7 @@ type irsapub* {.importc: "irsapub".}: RsaPublic SslClientCertificateClass* {.importc: "br_ssl_client_certificate_class", - header: "bearssl_ssl.h", bycopy.} = object + header: "bearssl_ssl.h", bycopy, deprecated.} = object contextSize* {.importc: "context_size".}: int startNameList* {.importc: "start_name_list".}: proc ( pctx: ptr ptr SslClientCertificateClass) {.bearSslFunc.} @@ -3187,7 +2824,7 @@ type len: int): int {.bearSslFunc.} SslClientCertificateRsaContext* {.importc: "br_ssl_client_certificate_rsa_context", - header: "bearssl_ssl.h", bycopy.} = object + header: "bearssl_ssl.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr SslClientCertificateClass chain* {.importc: "chain".}: ptr X509Certificate chainLen* {.importc: "chain_len".}: int @@ -3195,7 +2832,7 @@ type irsasign* {.importc: "irsasign".}: RsaPkcs1Sign SslClientCertificateEcContext* {.importc: "br_ssl_client_certificate_ec_context", - header: "bearssl_ssl.h", bycopy.} = object + header: "bearssl_ssl.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr SslClientCertificateClass chain* {.importc: "chain".}: ptr X509Certificate chainLen* {.importc: "chain_len".}: int @@ -3208,17 +2845,17 @@ type -proc sslClientGetServerHashes*(cc: ptr SslClientContext): uint32 {.inline.} = +proc sslClientGetServerHashes*(cc: ptr SslClientContext): uint32 {.inline, deprecated.} = return cc.hashes -proc sslClientGetServerCurve*(cc: ptr SslClientContext): cint {.inline.} = +proc sslClientGetServerCurve*(cc: ptr SslClientContext): cint {.inline, deprecated.} = return cc.serverCurve proc sslClientInitFull*(cc: ptr SslClientContext; xc: ptr X509MinimalContext; trustAnchors: ptr X509TrustAnchor; trustAnchorsNum: int) {. - bearSslFunc, importc: "br_ssl_client_init_full", header: "bearssl_ssl.h".} + bearSslFunc, deprecated, importc: "br_ssl_client_init_full", header: "bearssl_ssl.h".} -proc sslClientZero*(cc: ptr SslClientContext) {.bearSslFunc, importc: "br_ssl_client_zero", +proc sslClientZero*(cc: ptr SslClientContext) {.bearSslFunc, deprecated, importc: "br_ssl_client_zero", header: "bearssl_ssl.h".} proc sslClientSetClientCertificate*(cc: ptr SslClientContext; @@ -3226,32 +2863,32 @@ proc sslClientSetClientCertificate*(cc: ptr SslClientContext; inline.} = cc.clientAuthVtable = pctx -proc sslClientSetRsapub*(cc: ptr SslClientContext; irsapub: RsaPublic) {.inline.} = +proc sslClientSetRsapub*(cc: ptr SslClientContext; irsapub: RsaPublic) {.inline, deprecated.} = cc.irsapub = irsapub -proc sslClientSetDefaultRsapub*(cc: ptr SslClientContext) {.bearSslFunc, +proc sslClientSetDefaultRsapub*(cc: ptr SslClientContext) {.bearSslFunc, deprecated, importc: "br_ssl_client_set_default_rsapub", header: "bearssl_ssl.h".} proc sslClientSetMinClienthelloLen*(cc: ptr SslClientContext; len: uint16) {.inline, - bearSslFunc.} = + bearSslFunc, deprecated.} = cc.minClienthelloLen = len proc sslClientReset*(cc: ptr SslClientContext; serverName: cstring; - resumeSession: cint): cint {.bearSslFunc, + resumeSession: cint): cint {.bearSslFunc, deprecated, importc: "br_ssl_client_reset", header: "bearssl_ssl.h".} -proc sslClientForgetSession*(cc: ptr SslClientContext) {.inline.} = +proc sslClientForgetSession*(cc: ptr SslClientContext) {.inline, deprecated.} = cc.eng.session.sessionIdLen = 0 proc sslClientSetSingleRsa*(cc: ptr SslClientContext; chain: ptr X509Certificate; chainLen: int; sk: ptr RsaPrivateKey; - irsasign: RsaPkcs1Sign) {.bearSslFunc, + irsasign: RsaPkcs1Sign) {.bearSslFunc, deprecated, importc: "br_ssl_client_set_single_rsa", header: "bearssl_ssl.h".} proc sslClientSetSingleEc*(cc: ptr SslClientContext; chain: ptr X509Certificate; chainLen: int; sk: ptr EcPrivateKey; allowedUsages: cuint; certIssuerKeyType: cuint; - iec: ptr EcImpl; iecdsa: EcdsaSign) {.bearSslFunc, + iec: ptr EcImpl; iecdsa: EcdsaSign) {.bearSslFunc, deprecated, importc: "br_ssl_client_set_single_ec", header: "bearssl_ssl.h".} type @@ -3286,7 +2923,7 @@ type chainLen* {.importc: "chain_len".}: int SslServerPolicyClass* {.importc: "br_ssl_server_policy_class", - header: "bearssl_ssl.h", bycopy.} = object + header: "bearssl_ssl.h", bycopy, deprecated.} = object contextSize* {.importc: "context_size".}: int choose* {.importc: "choose".}: proc (pctx: ptr ptr SslServerPolicyClass; cc: ptr SslServerContext; @@ -3299,7 +2936,7 @@ type len: int): int {.bearSslFunc.} SslServerPolicyRsaContext* {.importc: "br_ssl_server_policy_rsa_context", - header: "bearssl_ssl.h", bycopy.} = object + header: "bearssl_ssl.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr SslServerPolicyClass chain* {.importc: "chain".}: ptr X509Certificate chainLen* {.importc: "chain_len".}: int @@ -3309,7 +2946,7 @@ type irsasign* {.importc: "irsasign".}: RsaPkcs1Sign SslServerPolicyEcContext* {.importc: "br_ssl_server_policy_ec_context", - header: "bearssl_ssl.h", bycopy.} = object + header: "bearssl_ssl.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr SslServerPolicyClass chain* {.importc: "chain".}: ptr X509Certificate chainLen* {.importc: "chain_len".}: int @@ -3353,7 +2990,7 @@ type SslSessionCacheClass* {.importc: "br_ssl_session_cache_class", - header: "bearssl_ssl.h", bycopy.} = object + header: "bearssl_ssl.h", bycopy, deprecated.} = object contextSize* {.importc: "context_size".}: int save* {.importc: "save".}: proc (ctx: ptr ptr SslSessionCacheClass; serverCtx: ptr SslServerContext; @@ -3363,7 +3000,7 @@ type params: ptr SslSessionParameters): cint {.bearSslFunc.} SslSessionCacheLru* {.importc: "br_ssl_session_cache_lru", - header: "bearssl_ssl.h", bycopy.} = object + header: "bearssl_ssl.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr SslSessionCacheClass store* {.importc: "store".}: ptr cuchar storeLen* {.importc: "store_len".}: int @@ -3377,48 +3014,48 @@ type proc sslSessionCacheLruInit*(cc: ptr SslSessionCacheLru; store: ptr cuchar; - storeLen: int) {.bearSslFunc, + storeLen: int) {.bearSslFunc, deprecated, importc: "br_ssl_session_cache_lru_init", header: "bearssl_ssl.h".} -proc sslSessionCacheLruForget*(cc: ptr SslSessionCacheLru; id: ptr cuchar) {.bearSslFunc, +proc sslSessionCacheLruForget*(cc: ptr SslSessionCacheLru; id: ptr cuchar) {.bearSslFunc, deprecated, importc: "br_ssl_session_cache_lru_forget", header: "bearssl_ssl.h".} proc sslServerInitFullRsa*(cc: ptr SslServerContext; chain: ptr X509Certificate; - chainLen: int; sk: ptr RsaPrivateKey) {.bearSslFunc, + chainLen: int; sk: ptr RsaPrivateKey) {.bearSslFunc, deprecated, importc: "br_ssl_server_init_full_rsa", header: "bearssl_ssl.h".} proc sslServerInitFullEc*(cc: ptr SslServerContext; chain: ptr X509Certificate; chainLen: int; certIssuerKeyType: cuint; - sk: ptr EcPrivateKey) {.bearSslFunc, + sk: ptr EcPrivateKey) {.bearSslFunc, deprecated, importc: "br_ssl_server_init_full_ec", header: "bearssl_ssl.h".} proc sslServerInitMinr2g*(cc: ptr SslServerContext; chain: ptr X509Certificate; - chainLen: int; sk: ptr RsaPrivateKey) {.bearSslFunc, + chainLen: int; sk: ptr RsaPrivateKey) {.bearSslFunc, deprecated, importc: "br_ssl_server_init_minr2g", header: "bearssl_ssl.h".} proc sslServerInitMine2g*(cc: ptr SslServerContext; chain: ptr X509Certificate; - chainLen: int; sk: ptr RsaPrivateKey) {.bearSslFunc, + chainLen: int; sk: ptr RsaPrivateKey) {.bearSslFunc, deprecated, importc: "br_ssl_server_init_mine2g", header: "bearssl_ssl.h".} proc sslServerInitMinf2g*(cc: ptr SslServerContext; chain: ptr X509Certificate; - chainLen: int; sk: ptr EcPrivateKey) {.bearSslFunc, + chainLen: int; sk: ptr EcPrivateKey) {.bearSslFunc, deprecated, importc: "br_ssl_server_init_minf2g", header: "bearssl_ssl.h".} proc sslServerInitMinu2g*(cc: ptr SslServerContext; chain: ptr X509Certificate; - chainLen: int; sk: ptr EcPrivateKey) {.bearSslFunc, + chainLen: int; sk: ptr EcPrivateKey) {.bearSslFunc, deprecated, importc: "br_ssl_server_init_minu2g", header: "bearssl_ssl.h".} proc sslServerInitMinv2g*(cc: ptr SslServerContext; chain: ptr X509Certificate; - chainLen: int; sk: ptr EcPrivateKey) {.bearSslFunc, + chainLen: int; sk: ptr EcPrivateKey) {.bearSslFunc, deprecated, importc: "br_ssl_server_init_minv2g", header: "bearssl_ssl.h".} proc sslServerInitMine2c*(cc: ptr SslServerContext; chain: ptr X509Certificate; - chainLen: int; sk: ptr RsaPrivateKey) {.bearSslFunc, + chainLen: int; sk: ptr RsaPrivateKey) {.bearSslFunc, deprecated, importc: "br_ssl_server_init_mine2c", header: "bearssl_ssl.h".} proc sslServerInitMinf2c*(cc: ptr SslServerContext; chain: ptr X509Certificate; - chainLen: int; sk: ptr EcPrivateKey) {.bearSslFunc, + chainLen: int; sk: ptr EcPrivateKey) {.bearSslFunc, deprecated, importc: "br_ssl_server_init_minf2c", header: "bearssl_ssl.h".} proc sslServerGetClientSuites*(cc: ptr SslServerContext; num: ptr int): @@ -3427,53 +3064,53 @@ proc sslServerGetClientSuites*(cc: ptr SslServerContext; num: ptr int): num[] = int cc.clientSuitesNum return addr cc.clientSuites -proc sslServerGetClientHashes*(cc: ptr SslServerContext): uint32 {.inline.} = +proc sslServerGetClientHashes*(cc: ptr SslServerContext): uint32 {.inline, deprecated.} = return cc.hashes -proc sslServerGetClientCurves*(cc: ptr SslServerContext): uint32 {.inline.} = +proc sslServerGetClientCurves*(cc: ptr SslServerContext): uint32 {.inline, deprecated.} = return cc.curves -proc sslServerZero*(cc: ptr SslServerContext) {.bearSslFunc, importc: "br_ssl_server_zero", +proc sslServerZero*(cc: ptr SslServerContext) {.bearSslFunc, deprecated, importc: "br_ssl_server_zero", header: "bearssl_ssl.h".} proc sslServerSetPolicy*(cc: ptr SslServerContext; - pctx: ptr ptr SslServerPolicyClass) {.inline.} = + pctx: ptr ptr SslServerPolicyClass) {.inline, deprecated.} = cc.policyVtable = pctx proc sslServerSetSingleRsa*(cc: ptr SslServerContext; chain: ptr X509Certificate; chainLen: int; sk: ptr RsaPrivateKey; allowedUsages: cuint; irsacore: RsaPrivate; - irsasign: RsaPkcs1Sign) {.bearSslFunc, + irsasign: RsaPkcs1Sign) {.bearSslFunc, deprecated, importc: "br_ssl_server_set_single_rsa", header: "bearssl_ssl.h".} proc sslServerSetSingleEc*(cc: ptr SslServerContext; chain: ptr X509Certificate; chainLen: int; sk: ptr EcPrivateKey; allowedUsages: cuint; certIssuerKeyType: cuint; - iec: ptr EcImpl; iecdsa: EcdsaSign) {.bearSslFunc, + iec: ptr EcImpl; iecdsa: EcdsaSign) {.bearSslFunc, deprecated, importc: "br_ssl_server_set_single_ec", header: "bearssl_ssl.h".} proc sslServerSetTrustAnchorNames*(cc: ptr SslServerContext; taNames: ptr X500Name; - num: int) {.inline.} = + num: int) {.inline, deprecated.} = cc.taNames = taNames cc.tas = nil cc.numTas = num proc sslServerSetTrustAnchorNamesAlt*(cc: ptr SslServerContext; tas: ptr X509TrustAnchor; num: int) {.inline, - bearSslFunc.} = + bearSslFunc, deprecated.} = cc.taNames = nil cc.tas = tas cc.numTas = num proc sslServerSetCache*(cc: ptr SslServerContext; - vtable: ptr ptr SslSessionCacheClass) {.inline.} = + vtable: ptr ptr SslSessionCacheClass) {.inline, deprecated.} = cc.cacheVtable = vtable -proc sslServerReset*(cc: ptr SslServerContext): cint {.bearSslFunc, +proc sslServerReset*(cc: ptr SslServerContext): cint {.bearSslFunc, deprecated, importc: "br_ssl_server_reset", header: "bearssl_ssl.h".} type - SslioContext* {.importc: "br_sslio_context", header: "bearssl_ssl.h", bycopy.} = object + SslioContext* {.importc: "br_sslio_context", header: "bearssl_ssl.h", bycopy, deprecated.} = object engine* {.importc: "engine".}: ptr SslEngineContext lowRead* {.importc: "low_read".}: proc (readContext: pointer; data: ptr cuchar; len: int): cint {.bearSslFunc.} @@ -3486,25 +3123,25 @@ type proc sslioInit*(ctx: ptr SslioContext; engine: ptr SslEngineContext; lowRead: proc ( readContext: pointer; data: ptr cuchar; len: int): cint {.bearSslFunc.}; readContext: pointer; lowWrite: proc (writeContext: pointer; - data: ptr cuchar; len: int): cint {.bearSslFunc.}; writeContext: pointer) {.bearSslFunc, + data: ptr cuchar; len: int): cint {.bearSslFunc.}; writeContext: pointer) {.bearSslFunc, deprecated, importc: "br_sslio_init", header: "bearssl_ssl.h".} -proc sslioRead*(cc: ptr SslioContext; dst: pointer; len: int): cint {.bearSslFunc, +proc sslioRead*(cc: ptr SslioContext; dst: pointer; len: int): cint {.bearSslFunc, deprecated, importc: "br_sslio_read", header: "bearssl_ssl.h".} -proc sslioReadAll*(cc: ptr SslioContext; dst: pointer; len: int): cint {.bearSslFunc, +proc sslioReadAll*(cc: ptr SslioContext; dst: pointer; len: int): cint {.bearSslFunc, deprecated, importc: "br_sslio_read_all", header: "bearssl_ssl.h".} -proc sslioWrite*(cc: ptr SslioContext; src: pointer; len: int): cint {.bearSslFunc, +proc sslioWrite*(cc: ptr SslioContext; src: pointer; len: int): cint {.bearSslFunc, deprecated, importc: "br_sslio_write", header: "bearssl_ssl.h".} -proc sslioWriteAll*(cc: ptr SslioContext; src: pointer; len: int): cint {.bearSslFunc, +proc sslioWriteAll*(cc: ptr SslioContext; src: pointer; len: int): cint {.bearSslFunc, deprecated, importc: "br_sslio_write_all", header: "bearssl_ssl.h".} -proc sslioFlush*(cc: ptr SslioContext): cint {.bearSslFunc, importc: "br_sslio_flush", +proc sslioFlush*(cc: ptr SslioContext): cint {.bearSslFunc, deprecated, importc: "br_sslio_flush", header: "bearssl_ssl.h".} -proc sslioClose*(cc: ptr SslioContext): cint {.bearSslFunc, importc: "br_sslio_close", +proc sslioClose*(cc: ptr SslioContext): cint {.bearSslFunc, deprecated, importc: "br_sslio_close", header: "bearssl_ssl.h".} const @@ -3643,7 +3280,7 @@ const ALERT_NO_APPLICATION_PROTOCOL* = 120 type - INNER_C_STRUCT_1475532182* {.importc: "no_name", header: "bearssl_pem.h", bycopy.} = object + INNER_C_STRUCT_1475532182* {.importc: "no_name", header: "bearssl_pem.h", bycopy, deprecated.} = object dp* {.importc: "dp".}: ptr uint32 rp* {.importc: "rp".}: ptr uint32 ip* {.importc: "ip".}: ptr cuchar @@ -3664,18 +3301,18 @@ type `ptr`* {.importc: "ptr".}: int -proc pemDecoderInit*(ctx: ptr PemDecoderContext) {.bearSslFunc, +proc pemDecoderInit*(ctx: ptr PemDecoderContext) {.bearSslFunc, deprecated, importc: "br_pem_decoder_init", header: "bearssl_pem.h".} proc pemDecoderPush*(ctx: ptr PemDecoderContext; data: pointer; len: int): int {. - bearSslFunc, importc: "br_pem_decoder_push", header: "bearssl_pem.h".} + bearSslFunc, deprecated, importc: "br_pem_decoder_push", header: "bearssl_pem.h".} proc pemDecoderSetdest*(ctx: ptr PemDecoderContext; dest: proc (destCtx: pointer; - src: pointer; len: int) {.bearSslFunc.}; destCtx: pointer) {.inline.} = + src: pointer; len: int) {.bearSslFunc.}; destCtx: pointer) {.inline, deprecated.} = ctx.dest = dest ctx.destCtx = destCtx -proc pemDecoderEvent*(ctx: ptr PemDecoderContext): cint {.bearSslFunc, +proc pemDecoderEvent*(ctx: ptr PemDecoderContext): cint {.bearSslFunc, deprecated, importc: "br_pem_decoder_event", header: "bearssl_pem.h".} const @@ -3687,16 +3324,16 @@ const const PEM_ERROR* = 3 -proc pemDecoderName*(ctx: ptr PemDecoderContext): cstring {.inline.} = +proc pemDecoderName*(ctx: ptr PemDecoderContext): cstring {.inline, deprecated.} = return addr ctx.name type - ConfigOption* {.importc: "br_config_option", header: "bearssl.h", bycopy.} = object + ConfigOption* {.importc: "br_config_option", header: "bearssl.h", bycopy, deprecated.} = object name* {.importc: "name".}: cstring value* {.importc: "value".}: clong -proc getConfig*(): ptr ConfigOption {.bearSslFunc, importc: "br_get_config", +proc getConfig*(): ptr ConfigOption {.bearSslFunc, deprecated, importc: "br_get_config", header: "bearssl.h".} const @@ -3709,119 +3346,119 @@ const type X509NoAnchorContext* {.importc: "x509_noanchor_context", - header: "brssl.h", bycopy.} = object + header: "brssl.h", bycopy, deprecated.} = object vtable* {.importc: "vtable".}: ptr X509Class proc initNoAnchor*(xwc: ptr X509NoAnchorContext, inner: ptr ptr X509Class) {. - bearSslFunc, importc: "x509_noanchor_init", header: "brssl.h".} + bearSslFunc, deprecated, importc: "x509_noanchor_init", header: "brssl.h".} # Following declarations are used inside `nim-libp2p`. type - BrHashClass* = HashClass - BrMd5Context* = Md5Context - BrMd5sha1Context* = Md5sha1Context - BrSha512Context* = Sha384Context - BrSha384Context* = Sha384Context - BrSha256Context* = Sha224Context - BrSha224Context* = Sha224Context - BrHashCompatContext* = HashCompatContext - BrPrngClass* = PrngClass - BrHmacDrbgContext* = HmacDrbgContext - BrRsaPublicKey* = RsaPublicKey - BrRsaPrivateKey* = RsaPrivateKey - BrEcPublicKey* = EcPublicKey - BrEcPrivateKey* = EcPrivateKey - BrEcImplementation* = EcImpl - BrPrngSeeder* = PrngSeeder - BrRsaKeygen* = proc (ctx: ptr ptr BrPrngClass, + BrHashClass* {.deprecated.} = HashClass + BrMd5Context* {.deprecated.} = Md5Context + BrMd5sha1Context* {.deprecated.} = Md5sha1Context + BrSha512Context* {.deprecated.} = Sha384Context + BrSha384Context* {.deprecated.} = Sha384Context + BrSha256Context* {.deprecated.} = Sha224Context + BrSha224Context* {.deprecated.} = Sha224Context + BrHashCompatContext* {.deprecated.} = HashCompatContext + BrPrngClass* {.deprecated.} = PrngClass + BrHmacDrbgContext* {.deprecated.} = HmacDrbgContext + BrRsaPublicKey* {.deprecated.} = RsaPublicKey + BrRsaPrivateKey* {.deprecated.} = RsaPrivateKey + BrEcPublicKey* {.deprecated.} = EcPublicKey + BrEcPrivateKey* {.deprecated.} = EcPrivateKey + BrEcImplementation* {.deprecated.} = EcImpl + BrPrngSeeder* {.deprecated.} = PrngSeeder + BrRsaKeygen* {.deprecated.} = proc (ctx: ptr ptr BrPrngClass, sk: ptr BrRsaPrivateKey, bufsec: ptr byte, pk: ptr BrRsaPublicKey, bufpub: ptr byte, size: cuint, pubexp: uint32): uint32 {.bearSslFunc.} - BrRsaComputeModulus* = proc (n: pointer, + BrRsaComputeModulus* {.deprecated.} = proc (n: pointer, sk: ptr BrRsaPrivateKey): int {.bearSslFunc.} - BrRsaComputePubexp* = proc (sk: ptr BrRsaPrivateKey): uint32 {.bearSslFunc.} - BrRsaComputePrivexp* = proc (d: pointer, + BrRsaComputePubexp* {.deprecated.} = proc (sk: ptr BrRsaPrivateKey): uint32 {.bearSslFunc.} + BrRsaComputePrivexp* {.deprecated.} = proc (d: pointer, sk: ptr BrRsaPrivateKey, pubexp: uint32): int {.bearSslFunc.} - BrRsaPkcs1Verify* = proc (x: ptr cuchar, xlen: int, + BrRsaPkcs1Verify* {.deprecated.} = proc (x: ptr cuchar, xlen: int, hash_oid: ptr cuchar, hash_len: int, pk: ptr BrRsaPublicKey, hash_out: ptr cuchar): uint32 {.bearSslFunc.} - BrPemDecoderProc* = proc (destctx: pointer, src: pointer, + BrPemDecoderProc* {.deprecated.} = proc (destctx: pointer, src: pointer, length: int) {.bearSslFunc.} BrRsaPkcs1Sign* = RsaPkcs1Sign -proc brPrngSeederSystem*(name: cstringArray): BrPrngSeeder {.bearSslFunc, +proc brPrngSeederSystem*(name: cstringArray): BrPrngSeeder {.bearSslFunc, deprecated, importc: "br_prng_seeder_system", header: "bearssl_rand.h".} proc brHmacDrbgInit*(ctx: ptr BrHmacDrbgContext, digestClass: ptr BrHashClass, seed: pointer, seedLen: int) {. - bearSslFunc, importc: "br_hmac_drbg_init", header: "bearssl_rand.h".} + bearSslFunc, deprecated, importc: "br_hmac_drbg_init", header: "bearssl_rand.h".} proc brHmacDrbgGenerate*(ctx: ptr BrHmacDrbgContext, outs: pointer, len: csize_t) {. - bearSslFunc, importc: "br_hmac_drbg_generate", header: "bearssl_rand.h".} + bearSslFunc, deprecated, importc: "br_hmac_drbg_generate", header: "bearssl_rand.h".} proc brHmacDrbgGenerate*(ctx: var BrHmacDrbgContext, outp: var openArray[byte]) = brHmacDrbgGenerate(addr ctx, addr outp, csize_t(outp.len)) proc brRsaKeygenGetDefault*(): BrRsaKeygen {. - bearSslFunc, importc: "br_rsa_keygen_get_default", header: "bearssl_rsa.h".} + bearSslFunc, deprecated, importc: "br_rsa_keygen_get_default", header: "bearssl_rsa.h".} proc BrRsaPkcs1SignGetDefault*(): BrRsaPkcs1Sign {. - bearSslFunc, importc: "br_rsa_pkcs1_sign_get_default", header: "bearssl_rsa.h".} + bearSslFunc, deprecated, importc: "br_rsa_pkcs1_sign_get_default", header: "bearssl_rsa.h".} proc BrRsaPkcs1VrfyGetDefault*(): BrRsaPkcs1Verify {. - bearSslFunc, importc: "br_rsa_pkcs1_vrfy_get_default", header: "bearssl_rsa.h".} + bearSslFunc, deprecated, importc: "br_rsa_pkcs1_vrfy_get_default", header: "bearssl_rsa.h".} proc brRsaComputeModulusGetDefault*(): BrRsaComputeModulus {. - bearSslFunc, importc: "br_rsa_compute_modulus_get_default", + bearSslFunc, deprecated, importc: "br_rsa_compute_modulus_get_default", header: "bearssl_rsa.h".} proc brRsaComputePubexpGetDefault*(): BrRsaComputePubexp {. - bearSslFunc, importc: "br_rsa_compute_pubexp_get_default", + bearSslFunc, deprecated, importc: "br_rsa_compute_pubexp_get_default", header: "bearssl_rsa.h".} proc brRsaComputePrivexpGetDefault*(): BrRsaComputePrivexp {. - bearSslFunc, importc: "br_rsa_compute_privexp_get_default", + bearSslFunc, deprecated, importc: "br_rsa_compute_privexp_get_default", header: "bearssl_rsa.h".} proc brEcGetDefault*(): ptr BrEcImplementation {. - bearSslFunc, importc: "br_ec_get_default", header: "bearssl_ec.h".} + bearSslFunc, deprecated, importc: "br_ec_get_default", header: "bearssl_ec.h".} proc brEcKeygen*(ctx: ptr ptr BrPrngClass, impl: ptr BrEcImplementation, sk: ptr BrEcPrivateKey, keybuf: ptr byte, - curve: cint): int {.bearSslFunc, + curve: cint): int {.bearSslFunc, deprecated, importc: "br_ec_keygen", header: "bearssl_ec.h".} proc brEcComputePublicKey*(impl: ptr BrEcImplementation, pk: ptr BrEcPublicKey, kbuf: ptr byte, sk: ptr BrEcPrivateKey): int {. - bearSslFunc, importc: "br_ec_compute_pub", header: "bearssl_ec.h".} + bearSslFunc, deprecated, importc: "br_ec_compute_pub", header: "bearssl_ec.h".} proc brEcdsaSignRaw*(impl: ptr BrEcImplementation, hf: ptr BrHashClass, value: pointer, sk: ptr BrEcPrivateKey, sig: pointer): int {. - bearSslFunc, importc: "br_ecdsa_i31_sign_raw", header: "bearssl_ec.h".} + bearSslFunc, deprecated, importc: "br_ecdsa_i31_sign_raw", header: "bearssl_ec.h".} proc brEcdsaVerifyRaw*(impl: ptr BrEcImplementation, hash: pointer, hashlen: int, pk: ptr BrEcPublicKey, sig: pointer, siglen: int): uint32 {. - bearSslFunc, importc: "br_ecdsa_i31_vrfy_raw", header: "bearssl_ec.h".} + bearSslFunc, deprecated, importc: "br_ecdsa_i31_vrfy_raw", header: "bearssl_ec.h".} proc brEcdsaSignAsn1*(impl: ptr BrEcImplementation, hf: ptr BrHashClass, value: pointer, sk: ptr BrEcPrivateKey, sig: pointer): int {. - bearSslFunc, importc: "br_ecdsa_i31_sign_asn1", header: "bearssl_ec.h".} + bearSslFunc, deprecated, importc: "br_ecdsa_i31_sign_asn1", header: "bearssl_ec.h".} proc brEcdsaVerifyAsn1*(impl: ptr BrEcImplementation, hash: pointer, hashlen: int, pk: ptr BrEcPublicKey, sig: pointer, siglen: int): uint32 {. - bearSslFunc, importc: "br_ecdsa_i31_vrfy_asn1", header: "bearssl_ec.h".} + bearSslFunc, deprecated, importc: "br_ecdsa_i31_vrfy_asn1", header: "bearssl_ec.h".} -template brRsaPrivateKeyBufferSize*(size: int): int = +template brRsaPrivateKeyBufferSize*(size: int): int {.deprecated.} = # BR_RSA_KBUF_PRIV_SIZE(size) (5 * ((size + 15) shr 4)) -template brRsaPublicKeyBufferSize*(size: int): int = +template brRsaPublicKeyBufferSize*(size: int): int {.deprecated.} = # BR_RSA_KBUF_PUB_SIZE(size) (4 + ((size + 7) shr 3)) diff --git a/vendor/nim-bearssl/bearssl/ec.nim b/vendor/nim-bearssl/bearssl/ec.nim new file mode 100644 index 000000000..c315b1bf9 --- /dev/null +++ b/vendor/nim-bearssl/bearssl/ec.nim @@ -0,0 +1,4 @@ +import + ./abi/bearssl_ec + +export bearssl_ec diff --git a/vendor/nim-bearssl/bearssl/hash.nim b/vendor/nim-bearssl/bearssl/hash.nim new file mode 100644 index 000000000..c8a23b506 --- /dev/null +++ b/vendor/nim-bearssl/bearssl/hash.nim @@ -0,0 +1,4 @@ +import + ./abi/bearssl_hash + +export bearssl_hash diff --git a/vendor/nim-bearssl/bearssl/hmac.nim b/vendor/nim-bearssl/bearssl/hmac.nim new file mode 100644 index 000000000..08633f8c7 --- /dev/null +++ b/vendor/nim-bearssl/bearssl/hmac.nim @@ -0,0 +1,4 @@ +import + ./abi/bearssl_hmac + +export bearssl_hmac diff --git a/vendor/nim-bearssl/bearssl/kdf.nim b/vendor/nim-bearssl/bearssl/kdf.nim new file mode 100644 index 000000000..f6f2f94e9 --- /dev/null +++ b/vendor/nim-bearssl/bearssl/kdf.nim @@ -0,0 +1,4 @@ +import + ./abi/bearssl_kdf + +export bearssl_kdf diff --git a/vendor/nim-bearssl/bearssl/pem.nim b/vendor/nim-bearssl/bearssl/pem.nim new file mode 100644 index 000000000..1ddd93799 --- /dev/null +++ b/vendor/nim-bearssl/bearssl/pem.nim @@ -0,0 +1,45 @@ +import + typetraits, + ./abi/bearssl_pem + +export bearssl_pem + +func init*(v: var PemDecoderContext) = + # Careful, PemDecoderContext items are not copyable! + # TODO prevent copying + pemDecoderInit(v) + +func push*(ctx: var PemDecoderContext, data: openArray[byte|char]): int = + if data.len > 0: + let consumed = pemDecoderPush( + ctx, unsafeAddr data[0], uint data.len) + int(consumed) + else: + 0 + +func setdest*( + ctx: var PemDecoderContext; + dest: proc (destCtx: pointer; + src: pointer; len: uint) {.cdecl, gcsafe, noSideEffect, raises: [].}; + destCtx: pointer) = + pemDecoderSetdest(ctx, dest, destCtx) + +func lastEvent*(ctx: var PemDecoderContext): cint = + pemDecoderEvent(ctx) + +func banner*(ctx: PemDecoderContext): string = + ## Return the `name` field as a string + if ctx.name[ctx.name.high] == char(0): + $(unsafeAddr ctx.name) + else: + var res = newString(ctx.name.len) + for i, c in ctx.name: res[i] = ctx.name[i] + res + +func pemEncode*( + data: openArray[byte|char], banner: cstring, flags: cuint = 0): string = + let bytes = pemEncode(nil, nil, uint data.len, banner, flags) + result.setLen(int bytes + 1) + discard pemEncode( + addr result[0], unsafeAddr data[0], uint data.len, banner, flags) + result.setLen(int bytes) diff --git a/vendor/nim-bearssl/bearssl/prf.nim b/vendor/nim-bearssl/bearssl/prf.nim new file mode 100644 index 000000000..41380d294 --- /dev/null +++ b/vendor/nim-bearssl/bearssl/prf.nim @@ -0,0 +1,4 @@ +import + ./abi/bearssl_prf + +export bearssl_prf diff --git a/vendor/nim-bearssl/bearssl/rand.nim b/vendor/nim-bearssl/bearssl/rand.nim new file mode 100644 index 000000000..300363fb3 --- /dev/null +++ b/vendor/nim-bearssl/bearssl/rand.nim @@ -0,0 +1,100 @@ +import + typetraits, + ./abi/[bearssl_hash, bearssl_rand] + +export bearssl_rand + +# About types used in helpers: +# `bool` types are problematic because because they only use one bit of the +# entire byte - a similar problem occurs with `object` types with alignment +# gaps - `supportsCopyMem` is wrong here, we should be using `supportsMemCmp` or +# something similar that takes into account these issues, but alas, there's no +# such trait as of now + +proc init*[S](T: type HmacDrbgContext, seed: openArray[S]): HmacDrbgContext = + ## Create a new randomness context with the given seed - typically, a single + ## instance per thread should be created. + ## + ## The seed can later be topped up with `update`. + static: doAssert supportsCopyMem(S) and sizeof(S) > 0 and S isnot bool + + if seed.len == 0: + hmacDrbgInit(result, addr bearssl_hash.sha256Vtable, nil, 0) + else: + # In theory the multiplication can overflow, but practically we can't + # allocate that much memory, so it won't + hmacDrbgInit( + result, addr sha256Vtable, unsafeAddr seed[0], uint seed.len * sizeof(S)) + +proc new*(T: type HmacDrbgContext): ref HmacDrbgContext = + ## Create a new randomness context intended to be shared between randomness + ## consumers - typically, a single instance per thread should be created. + ## + ## The context is seeded with randomness from the OS / system. + ## Returns `nil` if the OS / system has no randomness API. + let seeder = prngSeederSystem(nil) + if seeder == nil: + return nil + + let rng = (ref HmacDrbgContext)() + hmacDrbgInit(rng[], addr sha256Vtable, nil, 0) + + if seeder(addr rng.vtable) == 0: + return nil + + rng + +func generate*(ctx: var HmacDrbgContext, v: var auto) = + ## Fill `v` with random data - `v` must be a simple type + static: doAssert supportsCopyMem(type v) + + when sizeof(v) > 0: + when v is bool: + # `bool` would result in a heavily biased value because >0 == true + var tmp: byte + hmacDrbgGenerate(ctx, addr tmp, uint sizeof(tmp)) + v = (tmp and 1'u8) == 1 + else: + hmacDrbgGenerate(ctx, addr v, uint sizeof(v)) + +func generate*[V](ctx: var HmacDrbgContext, v: var openArray[V]) = + ## Fill `v` with random data - `T` must be a simple type + static: doAssert supportsCopyMem(V) and sizeof(V) > 0 + + when V is bool: + for b in v.mitems: + ctx.generate(b) + else: + if v.len > 0: + # In theory the multiplication can overflow, but practically we can't + # allocate that much memory, so it won't + hmacDrbgGenerate(ctx, addr v[0], uint v.len * sizeof(V)) + +template generate*[V](ctx: var HmacDrbgContext, v: var seq[V]) = + generate(ctx, v.toOpenArray(0, v.high())) + +func generateBytes*(ctx: var HmacDrbgContext, n: int): seq[byte] = + # https://github.com/nim-lang/Nim/issues/19357 + if n > 0: + result = newSeqUninitialized[byte](n) + ctx.generate(result) + +func generate*(ctx: var HmacDrbgContext, T: type): T {.noinit.} = + ## Create a new instance of `T` filled with random data - `T` must be + ## a simple type + ctx.generate(result) + +func update*[S](ctx: var HmacDrbgContext, seed: openArray[S]) = + ## Update context with additional seed data + static: doAssert supportsCopyMem(S) and sizeof(S) > 0 and S isnot bool + + if seed.len > 0: + # In theory the multiplication can overflow, but practically we can't + # allocate that much memory, so it won't + hmacDrbgUpdate(ctx, unsafeAddr seed[0], uint seed.len * sizeof(S)) + +# Convenience helpers using bearssl naming + +template hmacDrbgGenerate*( + ctx: var HmacDrbgContext, output: var openArray[byte]) = + generate(ctx, output) diff --git a/vendor/nim-bearssl/bearssl/rsa.nim b/vendor/nim-bearssl/bearssl/rsa.nim new file mode 100644 index 000000000..4780b21cf --- /dev/null +++ b/vendor/nim-bearssl/bearssl/rsa.nim @@ -0,0 +1,4 @@ +import + ./abi/bearssl_rsa + +export bearssl_rsa diff --git a/vendor/nim-bearssl/bearssl/ssl.nim b/vendor/nim-bearssl/bearssl/ssl.nim new file mode 100644 index 000000000..bed9715e2 --- /dev/null +++ b/vendor/nim-bearssl/bearssl/ssl.nim @@ -0,0 +1,4 @@ +import + ./abi/bearssl_ssl + +export bearssl_ssl diff --git a/vendor/nim-bearssl/bearssl/x509.nim b/vendor/nim-bearssl/bearssl/x509.nim new file mode 100644 index 000000000..62e245e9e --- /dev/null +++ b/vendor/nim-bearssl/bearssl/x509.nim @@ -0,0 +1,4 @@ +import + ./abi/bearssl_x509 + +export bearssl_x509 diff --git a/vendor/nim-bearssl/config.nims b/vendor/nim-bearssl/config.nims new file mode 100644 index 000000000..7c9db3205 --- /dev/null +++ b/vendor/nim-bearssl/config.nims @@ -0,0 +1,4 @@ +# begin Nimble config (version 1) +when fileExists("nimble.paths"): + include "nimble.paths" +# end Nimble config diff --git a/vendor/nim-bearssl/nim.cfg b/vendor/nim-bearssl/nim.cfg new file mode 100644 index 000000000..371f6d79d --- /dev/null +++ b/vendor/nim-bearssl/nim.cfg @@ -0,0 +1,5 @@ +# Avoid some rare stack corruption while using exceptions with a SEH-enabled +# toolchain: https://github.com/status-im/nimbus-eth2/issues/3121 +@if windows and not vcc: + --define:nimRawSetjmp +@end diff --git a/vendor/nim-bearssl/regenerate.sh b/vendor/nim-bearssl/regenerate.sh new file mode 100644 index 000000000..2a9e66660 --- /dev/null +++ b/vendor/nim-bearssl/regenerate.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +[[ $(c2nim -v) == "0.9.18" ]] || echo "Different c2nim used, check the code" + +mkdir -p gen +cp bearssl/csources/inc/*.h gen +cp bearssl/csources/tools/brssl.h gen + +# c2nim gets confused by #ifdef inside struct's +unifdef -m -UBR_DOXYGEN_IGNORE gen/*.h + +# TODO: several things broken in c2nim 0.9.18 +# https://github.com/nim-lang/c2nim/issues/239 +# https://github.com/nim-lang/c2nim/issues/240 +# https://github.com/nim-lang/c2nim/issues/241 +# https://github.com/nim-lang/c2nim/issues/242 + +c2nim --header --importc --nep1 --prefix:br_ --prefix:BR_ --skipinclude --cdecl --skipcomments gen/*.h + +rm gen/*.h + +# Fix cosmetic and ease-of-use issues +sed -i \ + -e "s/int16T/int16/g" \ + -e "s/int32T/int32/g" \ + -e "s/int64T/int64/g" \ + -e "s/cuchar/byte/g" \ + -e "s/cdecl/importcFunc/g" \ + -e "s/csize_t/uint/g" \ + gen/*.nim + +# The functions taking a "Context" don't allow `nil` being passed to them - use +# `var` instead - ditto for "output" parameters like length +sed -i \ + -e 's/ctx: ptr \(.*\)Context/ctx: var \1Context/g' \ + -e 's/ctx: ptr \(.*\)Keys/ctx: var \1Keys/g' \ + -e 's/hc: ptr \(.*\)Context/hc: var \1Context/g' \ + -e 's/sc: ptr \(.*\)Context/sc: var \1Context/g' \ + -e 's/cc: ptr \(.*\)Context/cc: var \1Context/g' \ + -e 's/kc: ptr \(.*\)Context/kc: var \1Context/g' \ + -e 's/xwc: ptr \(.*\)Context/xwc: var \1Context/g' \ + -e 's/len: ptr uint/len: var uint/g' \ + gen/*.nim diff --git a/vendor/nim-bearssl/tests/nim.cfg b/vendor/nim-bearssl/tests/nim.cfg new file mode 100644 index 000000000..371f6d79d --- /dev/null +++ b/vendor/nim-bearssl/tests/nim.cfg @@ -0,0 +1,5 @@ +# Avoid some rare stack corruption while using exceptions with a SEH-enabled +# toolchain: https://github.com/status-im/nimbus-eth2/issues/3121 +@if windows and not vcc: + --define:nimRawSetjmp +@end diff --git a/vendor/nim-bearssl/tests/hashing.nim b/vendor/nim-bearssl/tests/test_hash.nim similarity index 87% rename from vendor/nim-bearssl/tests/hashing.nim rename to vendor/nim-bearssl/tests/test_hash.nim index d9220b5c7..8ccbee20c 100644 --- a/vendor/nim-bearssl/tests/hashing.nim +++ b/vendor/nim-bearssl/tests/test_hash.nim @@ -1,6 +1,8 @@ import std/[strutils, sequtils], unittest2, - ../bearssl + ../bearssl/hash + +{.used.} suite "Hashing": test "MD5": @@ -25,7 +27,7 @@ suite "Hashing": ctx = Md5Context() res: array[md5SIZE, uint8] - md5Init(addr ctx) - md5Update(addr ctx, input[i].cstring, input[i].len) - md5Out(addr ctx, addr res[0]) + md5Init(ctx) + md5Update(ctx, input[i].cstring, uint input[i].len) + md5Out(ctx, addr res[0]) check res.foldl(a & b.toHex(), "").toLower() == output[i] diff --git a/vendor/nim-bearssl/tests/test_import.nim b/vendor/nim-bearssl/tests/test_import.nim new file mode 100644 index 000000000..38cce0218 --- /dev/null +++ b/vendor/nim-bearssl/tests/test_import.nim @@ -0,0 +1,11 @@ +# Test the full thing, given we do lots of compile and import tricks + +import ../bearssl + +# TODO doesn't work from C++ due to missing `export "C"` +# discard getConfig() + +# TODO doesn't work from C++ due to `const`:ness issues +# discard ecGetDefault() + +discard ghashPwr8Get() diff --git a/vendor/nim-bearssl/tests/test_pem.nim b/vendor/nim-bearssl/tests/test_pem.nim new file mode 100644 index 000000000..c68734fb0 --- /dev/null +++ b/vendor/nim-bearssl/tests/test_pem.nim @@ -0,0 +1,32 @@ +import + unittest2, + ../bearssl/pem + +suite "PEM": + test "roundtrip": + let + data = [byte 0, 1, 2, 3] + pem = pemEncode(data, "") + + var + ctx: PemDecoderContext + called = false + + ctx.init() + + proc test(dctx: pointer, data: pointer, len: uint) {.cdecl.} = + cast[ptr bool](dctx)[] = true + + ctx.setdest(test, addr called) + + var read = 0 + while read < pem.len: + let + consumed = ctx.push(pem.toOpenArray(read, pem.high)) + read += consumed + if read < pem.len: + check: ctx.lastEvent > 0 + + check: + pem.len > data.len + called diff --git a/vendor/nim-bearssl/tests/test_rand.nim b/vendor/nim-bearssl/tests/test_rand.nim new file mode 100644 index 000000000..2ee0afdd3 --- /dev/null +++ b/vendor/nim-bearssl/tests/test_rand.nim @@ -0,0 +1,62 @@ +import + unittest2, + ../bearssl/rand + +{.used.} + +suite "random": + test "simple random ops": + # Some of these tests may end up triggering false fails, but given their + # probability, should be fine + + let rng = HmacDrbgContext.new() + + var v: array[1024, byte] + rng[].generate(v) + + let v2 = rng[].generate(array[1024, byte]) + check: + v != default(array[1024, byte]) # probable + v2 != default(array[1024, byte]) # probable + + for i in 0..<1000: + doAssert cast[int](rng[].generate(bool)) in [0, 1] + + var bools: array[64 * 1024, bool] + rng[].generate(bools) + + check: + true in bools # probable + false in bools # probable + + var + xxx = newSeq[int](1024) + yyy = xxx + rng[].generate(xxx) + check: + xxx != yyy # probable + + test "seed": + for seed in [@[byte 0], @[byte 1], @[byte 1, 1], @[byte 42, 13, 37]]: + var + rng = HmacDrbgContext.init(seed) + rng2 = HmacDrbgContext.init(seed) + + check: + rng.generate(uint64) == rng2.generate(uint64) + + for seed in [@[0], @[1], @[1, 1], @[42, 1337, -5]]: + var + rng = HmacDrbgContext.init(seed) + rng2 = HmacDrbgContext.init(seed) + + check: + rng.generate(uint64) == rng2.generate(uint64) + + test "antiseed": + var + rng = HmacDrbgContext.init([0]) + rng2 = HmacDrbgContext.init([1]) + + check: + rng.generate(array[1024, byte]) != rng2.generate(array[1024, byte]) diff --git a/vendor/nim-chronicles/.github/workflows/ci.yml b/vendor/nim-chronicles/.github/workflows/ci.yml index 3aabc5a66..b20d6d99f 100644 --- a/vendor/nim-chronicles/.github/workflows/ci.yml +++ b/vendor/nim-chronicles/.github/workflows/ci.yml @@ -26,11 +26,11 @@ jobs: include: - target: os: linux - builder: ubuntu-18.04 + builder: ubuntu-20.04 shell: bash - target: os: macos - builder: macos-10.15 + builder: macos-11 shell: bash - target: os: windows diff --git a/vendor/nim-chronicles/chronicles.nimble b/vendor/nim-chronicles/chronicles.nimble index 267a2bd4a..ecfba7afe 100644 --- a/vendor/nim-chronicles/chronicles.nimble +++ b/vendor/nim-chronicles/chronicles.nimble @@ -1,7 +1,7 @@ mode = ScriptMode.Verbose packageName = "chronicles" -version = "0.10.2" +version = "0.10.3" author = "Status Research & Development GmbH" description = "A crafty implementation of structured logging for Nim" license = "Apache License 2.0" diff --git a/vendor/nim-chronicles/config.nims b/vendor/nim-chronicles/config.nims index 7c9db3205..4e03fd061 100644 --- a/vendor/nim-chronicles/config.nims +++ b/vendor/nim-chronicles/config.nims @@ -2,3 +2,8 @@ when fileExists("nimble.paths"): include "nimble.paths" # end Nimble config + +when (NimMajor, NimMinor) < (1, 6): + switch("styleCheck", "hint") +else: + switch("styleCheck", "error") diff --git a/vendor/nim-chronicles/nim.cfg b/vendor/nim-chronicles/nim.cfg index c902ca275..fed8edf2c 100644 --- a/vendor/nim-chronicles/nim.cfg +++ b/vendor/nim-chronicles/nim.cfg @@ -1,3 +1,3 @@ --path: "." --styleCheck:usages ---styleCheck:error +# --styleCheck:error # set up in config.nims diff --git a/vendor/nim-chronicles/nimble.lock b/vendor/nim-chronicles/nimble.lock new file mode 100644 index 000000000..5176cac34 --- /dev/null +++ b/vendor/nim-chronicles/nimble.lock @@ -0,0 +1,118 @@ +{ + "version": 1, + "packages": { + "stew": { + "version": "0.1.0", + "vcsRevision": "6ad35b876fb6ebe0dfee0f697af173acc47906ee", + "url": "https://github.com/status-im/nim-stew.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "46d58c4feb457f3241e3347778334e325dce5268" + } + }, + "unittest2": { + "version": "0.0.4", + "vcsRevision": "f180f596c88dfd266f746ed6f8dbebce39c824db", + "url": "https://github.com/status-im/nim-unittest2.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "fa309c41eaf6ef57895b9e603f2620a2f6e11780" + } + }, + "testutils": { + "version": "0.4.2", + "vcsRevision": "aa6e5216f4b4ab5aa971cdcdd70e1ec1203cedf2", + "url": "https://github.com/status-im/nim-testutils", + "downloadMethod": "git", + "dependencies": [ + "unittest2" + ], + "checksums": { + "sha1": "94427e0cce0e0c5841edcd3a6530b4e6b857a3cb" + } + }, + "bearssl": { + "version": "0.1.5", + "vcsRevision": "0a82a068280e4e9fb7a4936d92f1d0991c3bb363", + "url": "https://github.com/status-im/nim-bearssl.git", + "downloadMethod": "git", + "dependencies": [ + "unittest2" + ], + "checksums": { + "sha1": "9a34d4a65881261099270a22b34d49c9ca6af372" + } + }, + "httputils": { + "version": "0.3.0", + "vcsRevision": "689da19e9e9cfff4ced85e2b25c6b2b5598ed079", + "url": "https://github.com/status-im/nim-http-utils.git", + "downloadMethod": "git", + "dependencies": [ + "stew" + ], + "checksums": { + "sha1": "4ad3ad68d13c50184180ab4b2eacc0bd7ed2ed44" + } + }, + "chronos": { + "version": "3.0.11", + "vcsRevision": "17fed89c99beac5a92d3668d0d3e9b0e4ac13936", + "url": "https://github.com/status-im/nim-chronos.git", + "downloadMethod": "git", + "dependencies": [ + "stew", + "bearssl", + "httputils", + "unittest2" + ], + "checksums": { + "sha1": "f6fffc87571e5f76af2a77c4ebcc0e00909ced4e" + } + }, + "faststreams": { + "version": "0.3.0", + "vcsRevision": "1b561a9e71b6bdad1c1cdff753418906037e9d09", + "url": "https://github.com/status-im/nim-faststreams.git", + "downloadMethod": "git", + "dependencies": [ + "stew", + "testutils", + "chronos", + "unittest2" + ], + "checksums": { + "sha1": "97edf9797924af48566a0af8267203dc21d80c77" + } + }, + "serialization": { + "version": "0.1.0", + "vcsRevision": "fcd0eadadde0ee000a63df8ab21dc4e9f015a790", + "url": "https://github.com/status-im/nim-serialization.git", + "downloadMethod": "git", + "dependencies": [ + "faststreams", + "unittest2", + "stew" + ], + "checksums": { + "sha1": "fef59519892cac70cccd81b612085caaa5e3e6cf" + } + }, + "json_serialization": { + "version": "0.1.0", + "vcsRevision": "c5f0e2465e8375dfc7aa0f56ccef67cb680bc6b0", + "url": "https://github.com/status-im/nim-json-serialization.git", + "downloadMethod": "git", + "dependencies": [ + "serialization", + "stew" + ], + "checksums": { + "sha1": "d89d79d0679a3a41b350e3ad4be56c0308cc5ec6" + } + } + } +} \ No newline at end of file diff --git a/vendor/nim-chronos/chronos.nimble b/vendor/nim-chronos/chronos.nimble index 4a71ae20d..736243805 100644 --- a/vendor/nim-chronos/chronos.nimble +++ b/vendor/nim-chronos/chronos.nimble @@ -11,7 +11,7 @@ requires "nim > 1.2.0", "stew", "bearssl", "httputils", - "https://github.com/status-im/nim-unittest2.git#head" + "unittest2" var commandStart = "nim c -r --hints:off --verbosity:0 --skipParentCfg:on --warning[ObservableStores]:off --styleCheck:usages --styleCheck:error" diff --git a/vendor/nim-chronos/chronos/apps/http/httpclient.nim b/vendor/nim-chronos/chronos/apps/http/httpclient.nim index d75e6f2aa..6e261e897 100644 --- a/vendor/nim-chronos/chronos/apps/http/httpclient.nim +++ b/vendor/nim-chronos/chronos/apps/http/httpclient.nim @@ -157,6 +157,7 @@ type contentEncoding*: set[ContentEncodingFlags] transferEncoding*: set[TransferEncodingFlags] contentLength*: uint64 + contentType*: Opt[ContentTypeData] HttpClientResponseRef* = ref HttpClientResponse @@ -783,13 +784,25 @@ proc prepareResponse(request: HttpClientRequestRef, data: openArray[byte] else: false + let contentType = + block: + let list = headers.getList(ContentTypeHeader) + if len(list) > 0: + let res = getContentType(list) + if res.isErr(): + return err("Invalid headers received, invalid `Content-Type`") + else: + Opt.some(res.get()) + else: + Opt.none(ContentTypeData) + let res = HttpClientResponseRef( state: HttpReqRespState.Open, status: resp.code, address: request.address, requestMethod: request.meth, reason: resp.reason(data), version: resp.version, session: request.session, connection: request.connection, headers: headers, contentEncoding: contentEncoding, transferEncoding: transferEncoding, - contentLength: contentLength, bodyFlag: bodyFlag + contentLength: contentLength, contentType: contentType, bodyFlag: bodyFlag ) res.connection.state = HttpClientConnectionState.ResponseHeadersReceived if nobodyFlag: diff --git a/vendor/nim-chronos/chronos/apps/http/httpcommon.nim b/vendor/nim-chronos/chronos/apps/http/httpcommon.nim index 3f01e674a..0423f2227 100644 --- a/vendor/nim-chronos/chronos/apps/http/httpcommon.nim +++ b/vendor/nim-chronos/chronos/apps/http/httpcommon.nim @@ -32,8 +32,8 @@ const LocationHeader* = "location" AuthorizationHeader* = "authorization" - UrlEncodedContentType* = "application/x-www-form-urlencoded" - MultipartContentType* = "multipart/form-data" + UrlEncodedContentType* = MediaType.init("application/x-www-form-urlencoded") + MultipartContentType* = MediaType.init("multipart/form-data") type HttpResult*[T] = Result[T, string] @@ -193,7 +193,7 @@ func getContentEncoding*(ch: openArray[string]): HttpResult[ return err("Incorrect Content-Encoding value") ok(res) -func getContentType*(ch: openArray[string]): HttpResult[string] {. +func getContentType*(ch: openArray[string]): HttpResult[ContentTypeData] {. raises: [Defect].} = ## Check and prepare value of ``Content-Type`` header. if len(ch) == 0: @@ -201,8 +201,10 @@ func getContentType*(ch: openArray[string]): HttpResult[string] {. elif len(ch) > 1: err("Multiple Content-Type values found") else: - let mparts = ch[0].split(";") - ok(strip(mparts[0]).toLowerAscii()) + let res = getContentType(ch[0]) + if res.isErr(): + return err($res.error()) + ok(res.get()) proc bytesToString*(src: openArray[byte], dst: var openArray[char]) = ## Convert array of bytes to array of characters. diff --git a/vendor/nim-chronos/chronos/apps/http/httpserver.nim b/vendor/nim-chronos/chronos/apps/http/httpserver.nim index e09b532ec..6adfb94e5 100644 --- a/vendor/nim-chronos/chronos/apps/http/httpserver.nim +++ b/vendor/nim-chronos/chronos/apps/http/httpserver.nim @@ -67,7 +67,7 @@ type address*: TransportAddress # semaphore*: AsyncSemaphore maxConnections*: int - backlogSize: int + backlogSize*: int baseUri*: Uri serverIdent*: string flags*: set[HttpServerFlags] @@ -75,12 +75,12 @@ type connections*: Table[string, Future[void]] acceptLoop*: Future[void] lifetime*: Future[void] - headersTimeout: Duration - bufferSize: int - maxHeadersSize: int - maxRequestBodySize: int - processCallback: HttpProcessCallback - createConnCallback: HttpConnectionCallback + headersTimeout*: Duration + bufferSize*: int + maxHeadersSize*: int + maxRequestBodySize*: int + processCallback*: HttpProcessCallback + createConnCallback*: HttpConnectionCallback HttpServerRef* = ref HttpServer @@ -98,6 +98,7 @@ type transferEncoding*: set[TransferEncodingFlags] requestFlags*: set[HttpRequestFlags] contentLength: int + contentTypeData*: Option[ContentTypeData] connection*: HttpConnectionRef response*: Option[HttpResponseRef] @@ -135,46 +136,6 @@ proc init(htype: typedesc[HttpProcessError], error: HttpServerError, code: HttpCode): HttpProcessError {.raises: [Defect].} = HttpProcessError(error: error, exc: exc, remote: remote, code: code) -proc init*(value: var HttpServer, - address: TransportAddress, - server: StreamServer, - processCallback: HttpProcessCallback, - createConnCallback: HttpConnectionCallback, - serverUri: Uri, - serverFlags: set[HttpServerFlags] = {}, - socketFlags: set[ServerFlags] = {ReuseAddr}, - serverIdent = "", - maxConnections: int = -1, - bufferSize: int = 4096, - backlogSize: int = 100, - httpHeadersTimeout = 10.seconds, - maxHeadersSize: int = 8192, - maxRequestBodySize: int = 1_048_576) = - - value = HttpServer( - address: address, - instance: server, - processCallback: processCallback, - createConnCallback: createConnCallback, - baseUri: serverUri, - serverIdent: serverIdent, - flags: serverFlags, - socketFlags: socketFlags, - maxConnections: maxConnections, - bufferSize: bufferSize, - backlogSize: backlogSize, - headersTimeout: httpHeadersTimeout, - maxHeadersSize: maxHeadersSize, - maxRequestBodySize: maxRequestBodySize, - # semaphore: - # if maxConnections > 0: - # newAsyncSemaphore(maxConnections) - # else: - # nil - lifetime: newFuture[void]("http.server.lifetime"), - connections: initTable[string, Future[void]]() - ) - proc createConnection(server: HttpServerRef, transp: StreamTransport): Future[HttpConnectionRef] {. gcsafe.} @@ -191,7 +152,8 @@ proc new*(htype: typedesc[HttpServerRef], backlogSize: int = 100, httpHeadersTimeout = 10.seconds, maxHeadersSize: int = 8192, - maxRequestBodySize: int = 1_048_576): HttpResult[HttpServerRef] = + maxRequestBodySize: int = 1_048_576): HttpResult[HttpServerRef] {. + raises: [Defect].} = let serverUri = if len(serverUri.hostname) > 0: @@ -211,11 +173,29 @@ proc new*(htype: typedesc[HttpServerRef], except CatchableError as exc: return err(exc.msg) - var res = HttpServerRef() - res[].init(address, serverInstance, processCallback, createConnection, - serverUri, serverFlags, socketFlags, serverIdent, maxConnections, - bufferSize, backlogSize, httpHeadersTimeout, maxHeadersSize, - maxRequestBodySize) + var res = HttpServerRef( + address: address, + instance: serverInstance, + processCallback: processCallback, + createConnCallback: createConnection, + baseUri: serverUri, + serverIdent: serverIdent, + flags: serverFlags, + socketFlags: socketFlags, + maxConnections: maxConnections, + bufferSize: bufferSize, + backlogSize: backlogSize, + headersTimeout: httpHeadersTimeout, + maxHeadersSize: maxHeadersSize, + maxRequestBodySize: maxRequestBodySize, + # semaphore: + # if maxConnections > 0: + # newAsyncSemaphore(maxConnections) + # else: + # nil + lifetime: newFuture[void]("http.server.lifetime"), + connections: initTable[string, Future[void]]() + ) ok(res) proc getResponse*(req: HttpRequestRef): HttpResponseRef {.raises: [Defect].} = @@ -345,9 +325,10 @@ proc prepareRequest(conn: HttpConnectionRef, # steps to reveal information about body. if ContentLengthHeader in request.headers: let length = request.headers.getInt(ContentLengthHeader) - if length > 0: + if length >= 0: if request.meth == MethodTrace: return err(Http400) + # Because of coversion to `int` we should avoid unexpected OverflowError. if length > uint64(high(int)): return err(Http413) if length > uint64(conn.server.maxRequestBodySize): @@ -363,12 +344,14 @@ proc prepareRequest(conn: HttpConnectionRef, if request.hasBody(): # If request has body, we going to understand how its encoded. if ContentTypeHeader in request.headers: - let contentType = request.headers.getString(ContentTypeHeader) - let tmp = strip(contentType).toLowerAscii() - if tmp.startsWith(UrlEncodedContentType): + let contentType = + getContentType(request.headers.getList(ContentTypeHeader)).valueOr: + return err(Http415) + if contentType == UrlEncodedContentType: request.requestFlags.incl(HttpRequestFlags.UrlencodedForm) - elif tmp.startsWith(MultipartContentType): + elif contentType == MultipartContentType: request.requestFlags.incl(HttpRequestFlags.MultipartForm) + request.contentTypeData = some(contentType) if ExpectHeader in request.headers: let expectHeader = request.headers.getString(ExpectHeader) @@ -488,9 +471,10 @@ proc preferredContentMediaType*(acceptHeader: string): MediaType = MediaType.init("*", "*") proc preferredContentType*(acceptHeader: string, - types: varargs[MediaType]): Result[MediaType, cstring] = - ## Match or obtain preferred content-type using ``Accept`` header specified by - ## string ``acceptHeader``. + types: varargs[MediaType] + ): Result[MediaType, cstring] = + ## Match or obtain preferred content type using ``Accept`` header specified by + ## string ``acceptHeader`` and server preferred content types ``types``. ## ## If ``Accept`` header is missing in client's request - ``types[0]`` or ## ``*/*`` value will be returned as result. @@ -498,10 +482,14 @@ proc preferredContentType*(acceptHeader: string, ## If ``Accept`` header has incorrect format in client's request - ## ``types[0]`` or ``*/*`` value will be returned as result. ## - ## If ``Accept`` header is present and has one or more content types supported - ## by client, the best value will be selected from ``types`` using - ## quality value (weight) reported in ``Accept`` header. If client do not - ## support any methods in ``types`` error will be returned. + ## If ``Accept`` header is present in request to server and it has one or more + ## content types supported by client, the best value will be selected from + ## ``types`` using position and quality value (weight) reported in ``Accept`` + ## header. If client do not support any methods in ``types`` error + ## will be returned. + ## + ## Note: Quality value (weight) for content type has priority over server's + ## preferred content-type. if len(types) == 0: if len(acceptHeader) == 0: # If `Accept` header is missing, return `*/*`. @@ -513,10 +501,19 @@ proc preferredContentType*(acceptHeader: string, ok(wildCardMediaType) else: let mediaTypes = res.get().data - if len(mediaTypes) > 0: - ok(mediaTypes[0].mediaType) - else: + var + currentType = MediaType() + currentWeight = 0.0 + # `Accept` header values array is not sorted, so we need to find value + # with the biggest ``q-value``. + for item in mediaTypes: + if currentWeight < item.qvalue: + currentType = item.mediaType + currentWeight = item.qvalue + if len(currentType.media) == 0 and len(currentType.subtype) == 0: ok(wildCardMediaType) + else: + ok(currentType) else: if len(acceptHeader) == 0: # If `Accept` header is missing, client accepts any type of content. @@ -527,7 +524,32 @@ proc preferredContentType*(acceptHeader: string, # If `Accept` header is incorrect, client accepts any type of content. ok(types[0]) else: - selectContentType(ares.get().data, types) + # ``maxWeight`` represents maximum possible weight value which can be + # obtained. + let maxWeight = (1.0, 0) + var + currentType = MediaType() + currentIndex = -1 + currentWeight = (-1.0, 0) + + for itemType in ares.get().data: + let preferredIndex = types.find(itemType.mediaType) + if preferredIndex != -1: + let weight = (itemType.qvalue, -preferredIndex) + if currentWeight < weight: + currentType = types[preferredIndex] + currentWeight = weight + currentIndex = preferredIndex + + if currentWeight == maxWeight: + # There is no reason to continue search, because maximum possible + # weight is already achieved, so this is the best match. + break + + if currentIndex == -1: + err("Preferred content type not found") + else: + ok(currentType) proc preferredContentMediaType*(request: HttpRequestRef): MediaType = ## Returns preferred content-type using ``Accept`` header specified by @@ -535,7 +557,8 @@ proc preferredContentMediaType*(request: HttpRequestRef): MediaType = preferredContentMediaType(request.headers.getString(AcceptHeaderName)) proc preferredContentType*(request: HttpRequestRef, - types: varargs[MediaType]): Result[MediaType, cstring] = + types: varargs[MediaType] + ): Result[MediaType, cstring] = ## Match or obtain preferred content-type using ``Accept`` header specified by ## client in request ``request``. preferredContentType(request.headers.getString(AcceptHeaderName), types) @@ -920,19 +943,17 @@ proc join*(server: HttpServerRef): Future[void] = retFuture -proc getMultipartReader*(req: HttpRequestRef): HttpResult[MultiPartReaderRef] = +proc getMultipartReader*(req: HttpRequestRef): HttpResult[MultiPartReaderRef] {. + raises: [Defect].} = ## Create new MultiPartReader interface for specific request. if req.meth in PostMethods: if MultipartForm in req.requestFlags: - let ctype = ? getContentType(req.headers.getList(ContentTypeHeader)) - if ctype != MultipartContentType: - err("Content type is not supported") - else: - let boundary = ? getMultipartBoundary( - req.headers.getList(ContentTypeHeader) - ) + if req.contentTypeData.isSome(): + let boundary = ? getMultipartBoundary(req.contentTypeData.get()) var stream = ? req.getBodyReader() ok(MultiPartReaderRef.new(stream, boundary)) + else: + err("Content type is missing or invalid") else: err("Request's data is not multipart encoded") else: @@ -1322,17 +1343,35 @@ proc respond*(req: HttpRequestRef, code: HttpCode): Future[HttpResponseRef] = ## Responds to the request with specified ``HttpCode`` only. respond(req, code, "", HttpTable.init()) +proc redirect*(req: HttpRequestRef, code: HttpCode, + location: string, headers: HttpTable): Future[HttpResponseRef] = + ## Responds to the request with redirection to location ``location`` and + ## additional headers ``headers``. + ## + ## Note, ``location`` argument's value has priority over "Location" header's + ## value in ``headers`` argument. + var mheaders = headers + mheaders.set("location", location) + respond(req, code, "", mheaders) + +proc redirect*(req: HttpRequestRef, code: HttpCode, + location: Uri, headers: HttpTable): Future[HttpResponseRef] = + ## Responds to the request with redirection to location ``location`` and + ## additional headers ``headers``. + ## + ## Note, ``location`` argument's value has priority over "Location" header's + ## value in ``headers`` argument. + redirect(req, code, $location, headers) + proc redirect*(req: HttpRequestRef, code: HttpCode, location: Uri): Future[HttpResponseRef] = ## Responds to the request with redirection to location ``location``. - let headers = HttpTable.init([("location", $location)]) - respond(req, code, "", headers) + redirect(req, code, location, HttpTable.init()) proc redirect*(req: HttpRequestRef, code: HttpCode, location: string): Future[HttpResponseRef] = ## Responds to the request with redirection to location ``location``. - let headers = HttpTable.init([("location", location)]) - respond(req, code, "", headers) + redirect(req, code, location, HttpTable.init()) proc responded*(req: HttpRequestRef): bool = ## Returns ``true`` if request ``req`` has been responded or responding. diff --git a/vendor/nim-chronos/chronos/apps/http/httptable.nim b/vendor/nim-chronos/chronos/apps/http/httptable.nim index 5449dd5d9..1cbf62469 100644 --- a/vendor/nim-chronos/chronos/apps/http/httptable.nim +++ b/vendor/nim-chronos/chronos/apps/http/httptable.nim @@ -10,7 +10,10 @@ import std/[tables, strutils] import stew/base10 -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} type HttpTable* = object diff --git a/vendor/nim-chronos/chronos/apps/http/multipart.nim b/vendor/nim-chronos/chronos/apps/http/multipart.nim index 5c45a6b72..971c00098 100644 --- a/vendor/nim-chronos/chronos/apps/http/multipart.nim +++ b/vendor/nim-chronos/chronos/apps/http/multipart.nim @@ -8,11 +8,11 @@ # Apache License, version 2.0, (LICENSE-APACHEv2) # MIT license (LICENSE-MIT) import std/[monotimes, strutils] -import stew/results +import stew/results, httputils import ../../asyncloop import ../../streams/[asyncstream, boundstream, chunkstream] import httptable, httpcommon, httpbodyrw -export asyncloop, httptable, httpcommon, httpbodyrw, asyncstream +export asyncloop, httptable, httpcommon, httpbodyrw, asyncstream, httputils const UnableToReadMultipartBody = "Unable to read multipart message body" @@ -439,55 +439,25 @@ func validateBoundary[B: BChar](boundary: openArray[B]): HttpResult[void] = return err("Content-Type boundary alphabet incorrect") ok() -func getMultipartBoundary*(ch: openArray[string]): HttpResult[string] {. +func getMultipartBoundary*(contentData: ContentTypeData): HttpResult[string] {. raises: [Defect].} = ## Returns ``multipart/form-data`` boundary value from ``Content-Type`` ## header. ## ## The procedure carries out all the necessary checks: - ## 1) There should be single `Content-Type` header value in headers. - ## 2) `Content-Type` must be ``multipart/form-data``. - ## 3) `boundary` value must be present - ## 4) `boundary` value must be less then 70 characters length and + ## 1) `boundary` value must be present. + ## 2) `boundary` value must be less then 70 characters length and ## all characters should be part of specific alphabet. - if len(ch) > 1: - err("Multiple Content-Type headers found") - else: - if len(ch) == 0: - err("Content-Type header is missing") - else: - if len(ch[0]) == 0: - return err("Content-Type header has empty value") - let mparts = ch[0].split(";") - if strip(mparts[0]).toLowerAscii() != "multipart/form-data": - return err("Content-Type is not multipart") - if len(mparts) < 2: - return err("Content-Type missing boundary value") - - let index = - block: - var idx = 0 - for i in 1 ..< len(mparts): - let stripped = strip(mparts[i]) - if stripped.toLowerAscii().startsWith("boundary="): - idx = i - break - idx - - if index == 0: - err("Missing Content-Type boundary key") - else: - let stripped = strip(mparts[index]) - let bparts = stripped.split("=", 1) - if len(bparts) < 2: - err("Missing Content-Type boundary") - else: - let candidate = strip(bparts[1]) - let res = validateBoundary(candidate) - if res.isErr(): - err($res.error()) - else: - ok(candidate) + let candidate = + block: + var res: string + for item in contentData.params: + if cmpIgnoreCase(item.name, "boundary") == 0: + res = item.value + break + res + ? validateBoundary(candidate) + ok(candidate) proc quoteCheck(name: string): HttpResult[string] = if len(name) > 0: diff --git a/vendor/nim-chronos/chronos/apps/http/shttpserver.nim b/vendor/nim-chronos/chronos/apps/http/shttpserver.nim index 17dc8cc08..37cf8ca57 100644 --- a/vendor/nim-chronos/chronos/apps/http/shttpserver.nim +++ b/vendor/nim-chronos/chronos/apps/http/shttpserver.nim @@ -70,7 +70,7 @@ proc new*(htype: typedesc[SecureHttpServerRef], httpHeadersTimeout = 10.seconds, maxHeadersSize: int = 8192, maxRequestBodySize: int = 1_048_576 - ): HttpResult[SecureHttpServerRef] = + ): HttpResult[SecureHttpServerRef] {.raises: [Defect].} = doAssert(not(isNil(tlsPrivateKey)), "TLS private key must not be nil!") doAssert(not(isNil(tlsCertificate)), "TLS certificate must not be nil!") @@ -93,13 +93,30 @@ proc new*(htype: typedesc[SecureHttpServerRef], except CatchableError as exc: return err(exc.msg) - var res = SecureHttpServerRef() - HttpServer(res[]).init(address, serverInstance, processCallback, - createSecConnection, serverUri, serverFlags, - socketFlags, serverIdent, maxConnections, - bufferSize, backlogSize, httpHeadersTimeout, - maxHeadersSize, maxRequestBodySize) - res.tlsCertificate = tlsCertificate - res.tlsPrivateKey = tlsPrivateKey - res.secureFlags = secureFlags + let res = SecureHttpServerRef( + address: address, + instance: serverInstance, + processCallback: processCallback, + createConnCallback: createSecConnection, + baseUri: serverUri, + serverIdent: serverIdent, + flags: serverFlags, + socketFlags: socketFlags, + maxConnections: maxConnections, + bufferSize: bufferSize, + backlogSize: backlogSize, + headersTimeout: httpHeadersTimeout, + maxHeadersSize: maxHeadersSize, + maxRequestBodySize: maxRequestBodySize, + # semaphore: + # if maxConnections > 0: + # newAsyncSemaphore(maxConnections) + # else: + # nil + lifetime: newFuture[void]("http.server.lifetime"), + connections: initTable[string, Future[void]](), + tlsCertificate: tlsCertificate, + tlsPrivateKey: tlsPrivateKey, + secureFlags: secureFlags + ) ok(res) diff --git a/vendor/nim-chronos/chronos/asyncloop.nim b/vendor/nim-chronos/chronos/asyncloop.nim index 43b2c437e..8ef3753ce 100644 --- a/vendor/nim-chronos/chronos/asyncloop.nim +++ b/vendor/nim-chronos/chronos/asyncloop.nim @@ -8,7 +8,10 @@ # Apache License, version 2.0, (LICENSE-APACHEv2) # MIT license (LICENSE-MIT) -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/[os, tables, strutils, heapqueue, lists, options, nativesockets, net, deques] @@ -174,7 +177,13 @@ when defined(windows): elif unixPlatform: import ./selectors2 from posix import EINTR, EAGAIN, EINPROGRESS, EWOULDBLOCK, MSG_PEEK, - MSG_NOSIGNAL, SIGPIPE + MSG_NOSIGNAL + from posix import SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, + SIGBUS, SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, + SIGPIPE, SIGALRM, SIGTERM, SIGPIPE + export SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, + SIGBUS, SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, + SIGPIPE, SIGALRM, SIGTERM, SIGPIPE type CallbackFunc* = proc (arg: pointer) {.gcsafe, raises: [Defect].} @@ -851,6 +860,50 @@ proc callIdle*(cbproc: CallbackFunc) {.gcsafe, raises: [Defect].} = include asyncfutures2 +when not(defined(windows)): + when ioselSupportedPlatform: + proc waitSignal*(signal: int): Future[void] {. + raises: [Defect].} = + var retFuture = newFuture[void]("chronos.waitSignal()") + var sigfd: int = -1 + + template getSignalException(e: untyped): untyped = + newException(AsyncError, "Could not manipulate signal handler, " & + "reason [" & $e.name & "]: " & $e.msg) + + proc continuation(udata: pointer) {.gcsafe.} = + if not(retFuture.finished()): + if sigfd != -1: + try: + removeSignal(sigfd) + retFuture.complete() + except IOSelectorsException as exc: + retFuture.fail(getSignalException(exc)) + + proc cancellation(udata: pointer) {.gcsafe.} = + if not(retFuture.finished()): + if sigfd != -1: + try: + removeSignal(sigfd) + except IOSelectorsException as exc: + retFuture.fail(getSignalException(exc)) + + sigfd = + try: + addSignal(signal, continuation) + except IOSelectorsException as exc: + retFuture.fail(getSignalException(exc)) + return retFuture + except ValueError as exc: + retFuture.fail(getSignalException(exc)) + return retFuture + except OSError as exc: + retFuture.fail(getSignalException(exc)) + return retFuture + + retFuture.cancelCallback = cancellation + retFuture + proc sleepAsync*(duration: Duration): Future[void] = ## Suspends the execution of the current async procedure for the next ## ``duration`` time. diff --git a/vendor/nim-chronos/chronos/asyncsync.nim b/vendor/nim-chronos/chronos/asyncsync.nim index 824c0df3f..12feffdc3 100644 --- a/vendor/nim-chronos/chronos/asyncsync.nim +++ b/vendor/nim-chronos/chronos/asyncsync.nim @@ -10,9 +10,12 @@ ## This module implements some core synchronization primitives. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} -import std/[sequtils, deques, tables, typetraits] +import std/[sequtils, math, deques, tables, typetraits] import ./asyncloop export asyncloop @@ -55,11 +58,11 @@ type queue: Deque[T] maxsize: int - AsyncQueueEmptyError* = object of CatchableError + AsyncQueueEmptyError* = object of AsyncError ## ``AsyncQueue`` is empty. - AsyncQueueFullError* = object of CatchableError + AsyncQueueFullError* = object of AsyncError ## ``AsyncQueue`` is full. - AsyncLockError* = object of CatchableError + AsyncLockError* = object of AsyncError ## ``AsyncLock`` is either locked or unlocked. EventBusSubscription*[T] = proc(bus: AsyncEventBus, @@ -106,6 +109,23 @@ type eventName: string payload: EventPayloadBase + AsyncEventQueueFullError* = object of AsyncError + + EventQueueKey* = distinct uint64 + + EventQueueReader* = object + key: EventQueueKey + offset: int + waiter: Future[void] + overflow: bool + + AsyncEventQueue*[T] = ref object of RootObj + readers: seq[EventQueueReader] + queue: Deque[T] + counter: uint64 + limit: int + offset: int + proc newAsyncLock*(): AsyncLock = ## Creates new asynchronous lock ``AsyncLock``. ## @@ -448,7 +468,9 @@ proc `$`*[T](aq: AsyncQueue[T]): string = template generateKey(typeName, eventName: string): string = "type[" & typeName & "]-key[" & eventName & "]" -proc newAsyncEventBus*(): AsyncEventBus = +proc newAsyncEventBus*(): AsyncEventBus {. + deprecated: "Implementation has unfixable flaws, please use" & + "AsyncEventQueue[T] instead".} = ## Creates new ``AsyncEventBus``. AsyncEventBus(counter: 0'u64, events: initTable[string, EventItem]()) @@ -460,7 +482,9 @@ template location*(payload: EventPayloadBase): SrcLoc = ## Returns source location address of event emitter. payload.loc[] -proc get*(event: AwaitableEvent, T: typedesc): T = +proc get*(event: AwaitableEvent, T: typedesc): T {. + deprecated: "Implementation has unfixable flaws, please use " & + "AsyncEventQueue[T] instead".} = ## Returns event's payload of type ``T`` from event ``event``. cast[EventPayload[T]](event.payload).value @@ -472,7 +496,9 @@ template location*(event: AwaitableEvent): SrcLoc = ## Returns source location address of event emitter. event.payload.loc[] -proc waitEvent*(bus: AsyncEventBus, T: typedesc, event: string): Future[T] = +proc waitEvent*(bus: AsyncEventBus, T: typedesc, event: string): Future[T] {. + deprecated: "Implementation has unfixable flaws, please use " & + "AsyncEventQueue[T] instead".} = ## Wait for the event from AsyncEventBus ``bus`` with name ``event``. ## ## Returned ``Future[T]`` will hold event's payload of type ``T``. @@ -488,7 +514,9 @@ proc waitEvent*(bus: AsyncEventBus, T: typedesc, event: string): Future[T] = bus.events.mgetOrPut(eventKey, default).waiters.add(baseFuture) retFuture -proc waitAllEvents*(bus: AsyncEventBus): Future[AwaitableEvent] = +proc waitAllEvents*(bus: AsyncEventBus): Future[AwaitableEvent] {. + deprecated: "Implementation has unfixable flaws, please use " & + "AsyncEventQueue[T] instead".} = ## Wait for any event from AsyncEventBus ``bus``. ## ## Returns ``Future`` which holds helper object. Using this object you can @@ -502,7 +530,9 @@ proc waitAllEvents*(bus: AsyncEventBus): Future[AwaitableEvent] = retFuture proc subscribe*[T](bus: AsyncEventBus, event: string, - callback: EventBusSubscription[T]): EventBusKey = + callback: EventBusSubscription[T]): EventBusKey {. + deprecated: "Implementation has unfixable flaws, please use " & + "AsyncEventQueue[T] instead".} = ## Subscribe to the event ``event`` passed through eventbus ``bus`` with ## callback ``callback``. ## @@ -524,7 +554,9 @@ proc subscribe*[T](bus: AsyncEventBus, event: string, subkey proc subscribeAll*(bus: AsyncEventBus, - callback: EventBusAllSubscription): EventBusKey = + callback: EventBusAllSubscription): EventBusKey {. + deprecated: "Implementation has unfixable flaws, please use " & + "AsyncEventQueue instead".} = ## Subscribe to all events passed through eventbus ``bus`` with callback ## ``callback``. ## @@ -542,7 +574,9 @@ proc subscribeAll*(bus: AsyncEventBus, bus.subscribers.add(subkey) subkey -proc unsubscribe*(bus: AsyncEventBus, key: EventBusKey) = +proc unsubscribe*(bus: AsyncEventBus, key: EventBusKey) {. + deprecated: "Implementation has unfixable flaws, please use " & + "AsyncEventQueue instead".} = ## Cancel subscription of subscriber with key ``key`` from eventbus ``bus``. let eventKey = generateKey(key.typeName, key.eventName) @@ -590,7 +624,9 @@ proc emit[T](bus: AsyncEventBus, event: string, data: T, loc: ptr SrcLoc) = for subscriber in bus.subscribers: triggerSubscriberCallback(subscriber) -template emit*[T](bus: AsyncEventBus, event: string, data: T) = +template emit*[T](bus: AsyncEventBus, event: string, data: T) {. + deprecated: "Implementation has unfixable flaws, please use " & + "AsyncEventQueue instead".} = ## Emit new event ``event`` to the eventbus ``bus`` with payload ``data``. emit(bus, event, data, getSrcLocation()) @@ -605,8 +641,205 @@ proc emitWait[T](bus: AsyncEventBus, event: string, data: T, return retFuture template emitWait*[T](bus: AsyncEventBus, event: string, - data: T): Future[void] = + data: T): Future[void] {. + deprecated: "Implementation has unfixable flaws, please use " & + "AsyncEventQueue instead".} = ## Emit new event ``event`` to the eventbus ``bus`` with payload ``data`` and ## wait until all the subscribers/waiters will receive notification about ## event. emitWait(bus, event, data, getSrcLocation()) + +proc `==`(a, b: EventQueueKey): bool {.borrow.} + +proc compact(ab: AsyncEventQueue) {.raises: [Defect].} = + if len(ab.readers) > 0: + let minOffset = + block: + var res = -1 + for reader in ab.readers.items(): + if not(reader.overflow): + res = reader.offset + break + res + + if minOffset == -1: + ab.offset += len(ab.queue) + ab.queue.clear() + else: + doAssert(minOffset >= ab.offset) + if minOffset > ab.offset: + let delta = minOffset - ab.offset + ab.queue.shrink(fromFirst = delta) + ab.offset += delta + else: + ab.queue.clear() + +proc getReaderIndex(ab: AsyncEventQueue, key: EventQueueKey): int {. + raises: [Defect].} = + for index, value in ab.readers.pairs(): + if value.key == key: + return index + -1 + +proc newAsyncEventQueue*[T](limitSize = 0): AsyncEventQueue[T] {. + raises: [Defect].} = + ## Creates new ``AsyncEventBus`` maximum size of ``limitSize`` (default is + ## ``0`` which means that there no limits). + ## + ## When number of events emitted exceeds ``limitSize`` - emit() procedure + ## will discard new events, consumers which has number of pending events + ## more than ``limitSize`` will get ``AsyncEventQueueFullError`` + ## error. + doAssert(limitSize >= 0, "Limit size should be non-negative integer") + let queue = + if limitSize == 0: + initDeque[T]() + elif isPowerOfTwo(limitSize + 1): + initDeque[T](limitSize + 1) + else: + initDeque[T](nextPowerOfTwo(limitSize + 1)) + AsyncEventQueue[T](counter: 0'u64, queue: queue, limit: limitSize) + +proc len*(ab: AsyncEventQueue): int {.raises: [Defect].} = + len(ab.queue) + +proc register*(ab: AsyncEventQueue): EventQueueKey {.raises: [Defect].} = + inc(ab.counter) + let reader = EventQueueReader(key: EventQueueKey(ab.counter), + offset: ab.offset + len(ab.queue), + overflow: false) + ab.readers.add(reader) + EventQueueKey(ab.counter) + +proc unregister*(ab: AsyncEventQueue, key: EventQueueKey) {. + raises: [Defect] .} = + let index = ab.getReaderIndex(key) + if index >= 0: + let reader = ab.readers[index] + # Completing pending Future to avoid deadlock. + if not(isNil(reader.waiter)) and not(reader.waiter.finished()): + reader.waiter.complete() + ab.readers.delete(index) + ab.compact() + +proc close*(ab: AsyncEventQueue) {.raises: [Defect].} = + for reader in ab.readers.items(): + if not(isNil(reader.waiter)) and not(reader.waiter.finished()): + reader.waiter.complete() + ab.readers.reset() + ab.queue.clear() + +proc closeWait*(ab: AsyncEventQueue): Future[void] {.raises: [Defect].} = + var retFuture = newFuture[void]("AsyncEventQueue.closeWait()") + proc continuation(udata: pointer) {.gcsafe.} = + if not(retFuture.finished()): + retFuture.complete() + ab.close() + # Schedule `continuation` to be called only after all the `reader` + # notifications will be scheduled and processed. + callSoon(continuation) + retFuture + +template readerOverflow*(ab: AsyncEventQueue, + reader: EventQueueReader): bool = + ab.limit + (reader.offset - ab.offset) <= len(ab.queue) + +proc emit*[T](ab: AsyncEventQueue[T], data: T) {.raises: [Defect].} = + if len(ab.readers) > 0: + # We enqueue `data` only if there active reader present. + var changesPresent = false + let couldEmit = + if ab.limit == 0: + true + else: + # Because ab.readers is sequence sorted by `offset`, we will apply our + # limit to the most recent consumer. + if ab.readerOverflow(ab.readers[^1]): + false + else: + true + + if couldEmit: + if ab.limit != 0: + for reader in ab.readers.mitems(): + if not(reader.overflow): + if ab.readerOverflow(reader): + reader.overflow = true + changesPresent = true + ab.queue.addLast(data) + for reader in ab.readers.mitems(): + if not(isNil(reader.waiter)) and not(reader.waiter.finished()): + reader.waiter.complete() + else: + for reader in ab.readers.mitems(): + if not(reader.overflow): + reader.overflow = true + changesPresent = true + + if changesPresent: + ab.compact() + +proc waitEvents*[T](ab: AsyncEventQueue[T], + key: EventQueueKey, + eventsCount = -1): Future[seq[T]] {.async.} = + ## Wait for events + var + events: seq[T] + resetFuture = false + + while true: + # We need to obtain reader index at every iteration, because `ab.readers` + # sequence could be changed after `await waitFuture` call. + let index = ab.getReaderIndex(key) + if index < 0: + # We going to return everything we have in `events`. + break + + if resetFuture: + resetFuture = false + ab.readers[index].waiter = nil + + let reader = ab.readers[index] + doAssert(isNil(reader.waiter), + "Concurrent waits on same key are not allowed!") + + if reader.overflow: + raise newException(AsyncEventQueueFullError, + "AsyncEventQueue size exceeds limits") + + let length = len(ab.queue) + ab.offset + doAssert(length >= ab.readers[index].offset) + if length == ab.readers[index].offset: + # We are at the end of queue, it means that we should wait for new events. + let waitFuture = newFuture[void]("AsyncEventQueue.waitEvents") + ab.readers[index].waiter = waitFuture + resetFuture = true + await waitFuture + else: + let + itemsInQueue = length - ab.readers[index].offset + itemsOffset = ab.readers[index].offset - ab.offset + itemsCount = + if eventsCount <= 0: + itemsInQueue + else: + min(itemsInQueue, eventsCount - len(events)) + + for i in 0 ..< itemsCount: + events.add(ab.queue[itemsOffset + i]) + ab.readers[index].offset += itemsCount + + # Keep readers sequence sorted by `offset` field. + var slider = index + while (slider + 1 < len(ab.readers)) and + (ab.readers[slider].offset > ab.readers[slider + 1].offset): + swap(ab.readers[slider], ab.readers[slider + 1]) + inc(slider) + + # Shrink data queue. + ab.compact() + + if (eventsCount <= 0) or (len(events) == eventsCount): + break + + return events diff --git a/vendor/nim-chronos/chronos/debugutils.nim b/vendor/nim-chronos/chronos/debugutils.nim index c893f66f8..0f42afa88 100644 --- a/vendor/nim-chronos/chronos/debugutils.nim +++ b/vendor/nim-chronos/chronos/debugutils.nim @@ -7,7 +7,10 @@ # Apache License, version 2.0, (LICENSE-APACHEv2) # MIT license (LICENSE-MIT) -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import ./asyncloop export asyncloop diff --git a/vendor/nim-chronos/chronos/handles.nim b/vendor/nim-chronos/chronos/handles.nim index df583581b..690ad9247 100644 --- a/vendor/nim-chronos/chronos/handles.nim +++ b/vendor/nim-chronos/chronos/handles.nim @@ -7,7 +7,10 @@ # Apache License, version 2.0, (LICENSE-APACHEv2) # MIT license (LICENSE-MIT) -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/[net, nativesockets] import stew/base10 diff --git a/vendor/nim-chronos/chronos/ioselects/ioselectors_epoll.nim b/vendor/nim-chronos/chronos/ioselects/ioselectors_epoll.nim index 5a3044461..d1e138ad9 100644 --- a/vendor/nim-chronos/chronos/ioselects/ioselectors_epoll.nim +++ b/vendor/nim-chronos/chronos/ioselects/ioselectors_epoll.nim @@ -9,7 +9,10 @@ # This module implements Linux epoll(). -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import posix, times, epoll diff --git a/vendor/nim-chronos/chronos/sendfile.nim b/vendor/nim-chronos/chronos/sendfile.nim index c8f70778b..6993cb7ab 100644 --- a/vendor/nim-chronos/chronos/sendfile.nim +++ b/vendor/nim-chronos/chronos/sendfile.nim @@ -9,7 +9,10 @@ ## This module provides cross-platform wrapper for ``sendfile()`` syscall. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} when defined(nimdoc): proc sendfile*(outfd, infd: int, offset: int, count: var int): int = diff --git a/vendor/nim-chronos/chronos/srcloc.nim b/vendor/nim-chronos/chronos/srcloc.nim index 8652e9dd0..6edaefb5e 100644 --- a/vendor/nim-chronos/chronos/srcloc.nim +++ b/vendor/nim-chronos/chronos/srcloc.nim @@ -6,7 +6,10 @@ # Licensed under either of # Apache License, version 2.0, (LICENSE-APACHEv2) # MIT license (LICENSE-MIT) -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import stew/base10 type diff --git a/vendor/nim-chronos/chronos/streams/asyncstream.nim b/vendor/nim-chronos/chronos/streams/asyncstream.nim index 4022dc4ac..9cfa9637d 100644 --- a/vendor/nim-chronos/chronos/streams/asyncstream.nim +++ b/vendor/nim-chronos/chronos/streams/asyncstream.nim @@ -7,7 +7,10 @@ # Apache License, version 2.0, (LICENSE-APACHEv2) # MIT license (LICENSE-MIT) -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import ../asyncloop, ../asyncsync import ../transports/common, ../transports/stream @@ -820,7 +823,7 @@ proc write*(wstream: AsyncStreamWriter, pbytes: pointer, except CatchableError as exc: raise newAsyncStreamWriteError(exc) -proc write*(wstream: AsyncStreamWriter, sbytes: seq[byte], +proc write*(wstream: AsyncStreamWriter, sbytes: sink seq[byte], msglen = -1) {.async.} = ## Write sequence of bytes ``sbytes`` of length ``msglen`` to writer ## stream ``wstream``. @@ -852,8 +855,11 @@ proc write*(wstream: AsyncStreamWriter, sbytes: seq[byte], wstream.bytesCount = wstream.bytesCount + uint64(length) else: var item = WriteItem(kind: Sequence) - if not isLiteral(sbytes): - shallowCopy(item.dataSeq, sbytes) + when declared(shallowCopy): + if not(isLiteral(sbytes)): + shallowCopy(item.dataSeq, sbytes) + else: + item.dataSeq = sbytes else: item.dataSeq = sbytes item.size = length @@ -869,7 +875,7 @@ proc write*(wstream: AsyncStreamWriter, sbytes: seq[byte], except CatchableError as exc: raise newAsyncStreamWriteError(exc) -proc write*(wstream: AsyncStreamWriter, sbytes: string, +proc write*(wstream: AsyncStreamWriter, sbytes: sink string, msglen = -1) {.async.} = ## Write string ``sbytes`` of length ``msglen`` to writer stream ``wstream``. ## @@ -900,8 +906,11 @@ proc write*(wstream: AsyncStreamWriter, sbytes: string, wstream.bytesCount = wstream.bytesCount + uint64(length) else: var item = WriteItem(kind: String) - if not isLiteral(sbytes): - shallowCopy(item.dataStr, sbytes) + when declared(shallowCopy): + if not(isLiteral(sbytes)): + shallowCopy(item.dataStr, sbytes) + else: + item.dataStr = sbytes else: item.dataStr = sbytes item.size = length diff --git a/vendor/nim-chronos/chronos/streams/tlsstream.nim b/vendor/nim-chronos/chronos/streams/tlsstream.nim index 54a652de1..00052af3b 100644 --- a/vendor/nim-chronos/chronos/streams/tlsstream.nim +++ b/vendor/nim-chronos/chronos/streams/tlsstream.nim @@ -9,10 +9,12 @@ ## This module implements Transport Layer Security (TLS) stream. This module ## uses sources of BearSSL by Thomas Pornin. -import bearssl, bearssl/cacert +import + bearssl/[brssl, ec, errors, pem, rsa, ssl, x509], + bearssl/abi/cacert import ../asyncloop, ../timer, ../asyncsync import asyncstream, ../transports/stream, ../transports/common -export asyncloop, asyncsync, timer, asyncstream, bearssl +export asyncloop, asyncsync, timer, asyncstream type TLSStreamKind {.pure.} = enum @@ -79,7 +81,7 @@ type handshakeFut*: Future[void] TLSAsyncStream* = ref object of RootRef - xwc*: X509NoAnchorContext + xwc*: X509NoanchorContext ccontext*: SslClientContext scontext*: SslServerContext sbuffer*: seq[byte] @@ -141,10 +143,10 @@ proc tlsWriteRec(engine: ptr SslEngineContext, writer: TLSStreamWriter): Future[TLSResult] {.async.} = try: var length = 0'u - var buf = sslEngineSendrecBuf(engine, length) + var buf = sslEngineSendrecBuf(engine[], length) doAssert(length != 0 and not isNil(buf)) await writer.wsource.write(buf, int(length)) - sslEngineSendrecAck(engine, length) + sslEngineSendrecAck(engine[], length) return TLSResult.Success except AsyncStreamError as exc: if writer.state == AsyncStreamState.Running: @@ -161,13 +163,13 @@ proc tlsWriteApp(engine: ptr SslEngineContext, var item = await writer.queue.get() if item.size > 0: var length = 0'u - var buf = sslEngineSendappBuf(engine, length) + var buf = sslEngineSendappBuf(engine[], length) let toWrite = min(int(length), item.size) copyOut(buf, item, toWrite) if int(length) >= item.size: # BearSSL is ready to accept whole item size. - sslEngineSendappAck(engine, uint(item.size)) - sslEngineFlush(engine, 0) + sslEngineSendappAck(engine[], uint(item.size)) + sslEngineFlush(engine[], 0) item.future.complete() return TLSResult.Success else: @@ -176,10 +178,10 @@ proc tlsWriteApp(engine: ptr SslEngineContext, item.offset = item.offset + int(length) item.size = item.size - int(length) writer.queue.addFirstNoWait(item) - sslEngineSendappAck(engine, length) + sslEngineSendappAck(engine[], length) return TLSResult.Success else: - sslEngineClose(engine) + sslEngineClose(engine[]) item.future.complete() return TLSResult.Success except CancelledError: @@ -191,11 +193,11 @@ proc tlsReadRec(engine: ptr SslEngineContext, reader: TLSStreamReader): Future[TLSResult] {.async.} = try: var length = 0'u - var buf = sslEngineRecvrecBuf(engine, length) + var buf = sslEngineRecvrecBuf(engine[], length) let res = await reader.rsource.readOnce(buf, int(length)) - sslEngineRecvrecAck(engine, uint(res)) + sslEngineRecvrecAck(engine[], uint(res)) if res == 0: - sslEngineClose(engine) + sslEngineClose(engine[]) return TLSResult.EOF else: @@ -213,9 +215,9 @@ proc tlsReadApp(engine: ptr SslEngineContext, reader: TLSStreamReader): Future[TLSResult] {.async.} = try: var length = 0'u - var buf = sslEngineRecvappBuf(engine, length) + var buf = sslEngineRecvappBuf(engine[], length) await upload(addr reader.buffer, buf, int(length)) - sslEngineRecvappAck(engine, length) + sslEngineRecvappAck(engine[], length) return TLSResult.Success except CancelledError: if reader.state == AsyncStreamState.Running: @@ -291,7 +293,7 @@ proc tlsLoop*(stream: TLSAsyncStream) {.async.} = while true: var waiting: seq[Future[TLSResult]] - var state = sslEngineCurrentState(engine) + var state = sslEngineCurrentState(engine[]) if (state and SSL_CLOSED) == SSL_CLOSED: if loopState == AsyncStreamState.Running: @@ -361,7 +363,7 @@ proc tlsLoop*(stream: TLSAsyncStream) {.async.} = else: newTLSStreamWriteError(stream.reader.error) of AsyncStreamState.Finished: - let err = engine.sslEngineLastError() + let err = engine[].sslEngineLastError() if err != 0: newTLSStreamProtocolError(err) else: @@ -419,13 +421,13 @@ proc tlsReadLoop(stream: AsyncStreamReader) {.async.} = proc getSignerAlgo(xc: X509Certificate): int = ## Get certificate's signing algorithm. var dc: X509DecoderContext - x509DecoderInit(addr dc, nil, nil) - x509DecoderPush(addr dc, xc.data, xc.dataLen) - let err = x509DecoderLastError(addr dc) + x509DecoderInit(dc, nil, nil) + x509DecoderPush(dc, xc.data, xc.dataLen) + let err = x509DecoderLastError(dc) if err != 0: -1 else: - int(x509DecoderGetSignerKeyType(addr dc)) + int(x509DecoderGetSignerKeyType(dc)) proc newTLSClientAsyncStream*(rsource: AsyncStreamReader, wsource: AsyncStreamWriter, @@ -465,23 +467,23 @@ proc newTLSClientAsyncStream*(rsource: AsyncStreamReader, res.writer = writer if TLSFlags.NoVerifyHost in flags: - sslClientInitFull(addr res.ccontext, addr res.x509, nil, 0) - initNoAnchor(addr res.xwc, addr res.x509.vtable) - sslEngineSetX509(addr res.ccontext.eng, addr res.xwc.vtable) + sslClientInitFull(res.ccontext, addr res.x509, nil, 0) + initNoAnchor(res.xwc, addr res.x509.vtable) + sslEngineSetX509(res.ccontext.eng, addr res.xwc.vtable) else: - sslClientInitFull(addr res.ccontext, addr res.x509, + sslClientInitFull(res.ccontext, addr res.x509, unsafeAddr MozillaTrustAnchors[0], - len(MozillaTrustAnchors)) + uint(len(MozillaTrustAnchors))) let size = max(SSL_BUFSIZE_BIDI, bufferSize) res.sbuffer = newSeq[byte](size) - sslEngineSetBuffer(addr res.ccontext.eng, addr res.sbuffer[0], + sslEngineSetBuffer(res.ccontext.eng, addr res.sbuffer[0], uint(len(res.sbuffer)), 1) - sslEngineSetVersions(addr res.ccontext.eng, uint16(minVersion), + sslEngineSetVersions(res.ccontext.eng, uint16(minVersion), uint16(maxVersion)) if TLSFlags.NoVerifyServerName in flags: - let err = sslClientReset(addr res.ccontext, "", 0) + let err = sslClientReset(res.ccontext, "", 0) if err == 0: raise newException(TLSStreamInitError, "Could not initialize TLS layer") else: @@ -489,7 +491,7 @@ proc newTLSClientAsyncStream*(rsource: AsyncStreamReader, raise newException(TLSStreamInitError, "serverName must not be empty string") - let err = sslClientReset(addr res.ccontext, serverName, 0) + let err = sslClientReset(res.ccontext, serverName, 0) if err == 0: raise newException(TLSStreamInitError, "Could not initialize TLS layer") @@ -545,33 +547,33 @@ proc newTLSServerAsyncStream*(rsource: AsyncStreamReader, let algo = getSignerAlgo(certificate.certs[0]) if algo == -1: raiseTLSStreamProtocolError("Could not decode certificate") - sslServerInitFullEc(addr res.scontext, addr certificate.certs[0], - len(certificate.certs), cuint(algo), + sslServerInitFullEc(res.scontext, addr certificate.certs[0], + uint(len(certificate.certs)), cuint(algo), addr privateKey.eckey) elif privateKey.kind == TLSKeyType.RSA: - sslServerInitFullRsa(addr res.scontext, addr certificate.certs[0], - len(certificate.certs), addr privateKey.rsakey) + sslServerInitFullRsa(res.scontext, addr certificate.certs[0], + uint(len(certificate.certs)), addr privateKey.rsakey) let size = max(SSL_BUFSIZE_BIDI, bufferSize) res.sbuffer = newSeq[byte](size) - sslEngineSetBuffer(addr res.scontext.eng, addr res.sbuffer[0], + sslEngineSetBuffer(res.scontext.eng, addr res.sbuffer[0], uint(len(res.sbuffer)), 1) - sslEngineSetVersions(addr res.scontext.eng, uint16(minVersion), + sslEngineSetVersions(res.scontext.eng, uint16(minVersion), uint16(maxVersion)) if not isNil(cache): - sslServerSetCache(addr res.scontext, addr cache.context.vtable) + sslServerSetCache(res.scontext, addr cache.context.vtable) if TLSFlags.EnforceServerPref in flags: - sslEngineAddFlags(addr res.scontext.eng, OPT_ENFORCE_SERVER_PREFERENCES) + sslEngineAddFlags(res.scontext.eng, OPT_ENFORCE_SERVER_PREFERENCES) if TLSFlags.NoRenegotiation in flags: - sslEngineAddFlags(addr res.scontext.eng, OPT_NO_RENEGOTIATION) + sslEngineAddFlags(res.scontext.eng, OPT_NO_RENEGOTIATION) if TLSFlags.TolerateNoClientAuth in flags: - sslEngineAddFlags(addr res.scontext.eng, OPT_TOLERATE_NO_CLIENT_AUTH) + sslEngineAddFlags(res.scontext.eng, OPT_TOLERATE_NO_CLIENT_AUTH) if TLSFlags.FailOnAlpnMismatch in flags: - sslEngineAddFlags(addr res.scontext.eng, OPT_FAIL_ON_ALPN_MISMATCH) + sslEngineAddFlags(res.scontext.eng, OPT_FAIL_ON_ALPN_MISMATCH) - let err = sslServerReset(addr res.scontext) + let err = sslServerReset(res.scontext) if err == 0: raise newException(TLSStreamInitError, "Could not initialize TLS layer") @@ -583,27 +585,27 @@ proc newTLSServerAsyncStream*(rsource: AsyncStreamReader, proc copyKey(src: RsaPrivateKey): TLSPrivateKey = ## Creates copy of RsaPrivateKey ``src``. - var offset = 0 + var offset = 0'u let keySize = src.plen + src.qlen + src.dplen + src.dqlen + src.iqlen var res = TLSPrivateKey(kind: TLSKeyType.RSA, storage: newSeq[byte](keySize)) copyMem(addr res.storage[offset], src.p, src.plen) - res.rsakey.p = cast[ptr cuchar](addr res.storage[offset]) + res.rsakey.p = addr res.storage[offset] res.rsakey.plen = src.plen offset = offset + src.plen copyMem(addr res.storage[offset], src.q, src.qlen) - res.rsakey.q = cast[ptr cuchar](addr res.storage[offset]) + res.rsakey.q = addr res.storage[offset] res.rsakey.qlen = src.qlen offset = offset + src.qlen copyMem(addr res.storage[offset], src.dp, src.dplen) - res.rsakey.dp = cast[ptr cuchar](addr res.storage[offset]) + res.rsakey.dp = addr res.storage[offset] res.rsakey.dplen = src.dplen offset = offset + src.dplen copyMem(addr res.storage[offset], src.dq, src.dqlen) - res.rsakey.dq = cast[ptr cuchar](addr res.storage[offset]) + res.rsakey.dq = addr res.storage[offset] res.rsakey.dqlen = src.dqlen offset = offset + src.dqlen copyMem(addr res.storage[offset], src.iq, src.iqlen) - res.rsakey.iq = cast[ptr cuchar](addr res.storage[offset]) + res.rsakey.iq = addr res.storage[offset] res.rsakey.iqlen = src.iqlen res.rsakey.nBitlen = src.nBitlen res @@ -614,7 +616,7 @@ proc copyKey(src: EcPrivateKey): TLSPrivateKey = let keySize = src.xlen var res = TLSPrivateKey(kind: TLSKeyType.EC, storage: newSeq[byte](keySize)) copyMem(addr res.storage[offset], src.x, src.xlen) - res.eckey.x = cast[ptr cuchar](addr res.storage[offset]) + res.eckey.x = addr res.storage[offset] res.eckey.xlen = src.xlen res.eckey.curve = src.curve res @@ -627,12 +629,12 @@ proc init*(tt: typedesc[TLSPrivateKey], data: openArray[byte]): TLSPrivateKey = var ctx: SkeyDecoderContext if len(data) == 0: raiseTLSStreamProtocolError("Incorrect private key") - skeyDecoderInit(addr ctx) - skeyDecoderPush(addr ctx, cast[pointer](unsafeAddr data[0]), len(data)) - let err = skeyDecoderLastError(addr ctx) + skeyDecoderInit(ctx) + skeyDecoderPush(ctx, cast[pointer](unsafeAddr data[0]), uint(len(data))) + let err = skeyDecoderLastError(ctx) if err != 0: raiseTLSStreamProtocolError(err) - let keyType = skeyDecoderKeyType(addr ctx) + let keyType = skeyDecoderKeyType(ctx) let res = if keyType == KEYTYPE_RSA: copyKey(ctx.key.rsa) @@ -646,34 +648,32 @@ proc pemDecode*(data: openArray[char]): seq[PEMElement] = ## Decode PEM encoded string and get array of binary blobs. if len(data) == 0: raiseTLSStreamProtocolError("Empty PEM message") - var ctx: PemDecoderContext var pctx = new PEMContext var res = newSeq[PEMElement]() - pemDecoderInit(addr ctx) - proc itemAppend(ctx: pointer, pbytes: pointer, nbytes: int) {.cdecl.} = + proc itemAppend(ctx: pointer, pbytes: pointer, nbytes: uint) {.cdecl.} = var p = cast[PEMContext](ctx) - var o = len(p.data) + var o = uint(len(p.data)) p.data.setLen(o + nbytes) copyMem(addr p.data[o], pbytes, nbytes) - var length = len(data) var offset = 0 var inobj = false var elem: PEMElement - while length > 0: - var tlen = pemDecoderPush(addr ctx, - cast[pointer](unsafeAddr data[offset]), length) - offset = offset + tlen - length = length - tlen + var ctx: PemDecoderContext + ctx.init() + ctx.setdest(itemAppend, cast[pointer](pctx)) - let event = pemDecoderEvent(addr ctx) + while offset < data.len: + let tlen = ctx.push(data.toOpenArray(offset, data.high)) + offset = offset + tlen + + let event = ctx.lastEvent() if event == PEM_BEGIN_OBJ: inobj = true - elem.name = $pemDecoderName(addr ctx) - pctx.data = newSeq[byte]() - pemDecoderSetdest(addr ctx, itemAppend, cast[pointer](pctx)) + elem.name = ctx.banner() + pctx.data.setLen(0) elif event == PEM_END_OBJ: if inobj: elem.data = pctx.data @@ -715,8 +715,8 @@ proc init*(tt: typedesc[TLSCertificate], let offset = len(res.storage) res.storage.add(item.data) let cert = X509Certificate( - data: cast[ptr cuchar](addr res.storage[offset]), - dataLen: len(item.data) + data: addr res.storage[offset], + dataLen: uint(len(item.data)) ) let ares = getSignerAlgo(cert) if ares == -1: diff --git a/vendor/nim-chronos/chronos/timer.nim b/vendor/nim-chronos/chronos/timer.nim index c4584233d..1a44189f7 100644 --- a/vendor/nim-chronos/chronos/timer.nim +++ b/vendor/nim-chronos/chronos/timer.nim @@ -24,7 +24,10 @@ ## You can specify which timer you want to use ``-d:asyncTimer=``. const asyncTimer* {.strdefine.} = "mono" -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} when defined(windows): when asyncTimer == "system": @@ -302,6 +305,18 @@ const ZeroDuration* = Duration(value: 0'i64) InfiniteDuration* = Duration(value: high(int64)) +template high*(T: typedesc[Moment]): Moment = + Moment(value: high(int64)) + +template low*(T: typedesc[Moment]): Moment = + Moment(value: 0) + +template high*(T: typedesc[Duration]): Duration = + Duration(value: high(int64)) + +template low*(T: typedesc[Duration]): Duration = + Duration(value: 0) + func nanoseconds*(v: SomeIntegerI64): Duration {.inline.} = ## Initialize Duration with nanoseconds value ``v``. result.value = int64(v) @@ -438,6 +453,12 @@ func init*(t: typedesc[Moment], value: int64, precision: Duration): Moment = ## ``precision``. result.value = value * precision.value +func epochSeconds*(moment: Moment): int64 = + moment.value div Second.value + +func epochNanoSeconds*(moment: Moment): int64 = + moment.value + proc fromNow*(t: typedesc[Moment], a: Duration): Moment {.inline.} = ## Returns moment in time which is equal to current moment + Duration. result = Moment.now() + a diff --git a/vendor/nim-chronos/chronos/transports/common.nim b/vendor/nim-chronos/chronos/transports/common.nim index 7f1ec9dfd..bc9cc1c07 100644 --- a/vendor/nim-chronos/chronos/transports/common.nim +++ b/vendor/nim-chronos/chronos/transports/common.nim @@ -7,7 +7,10 @@ # Apache License, version 2.0, (LICENSE-APACHEv2) # MIT license (LICENSE-MIT) -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/[os, strutils, nativesockets, net] import stew/base10 diff --git a/vendor/nim-chronos/chronos/transports/datagram.nim b/vendor/nim-chronos/chronos/transports/datagram.nim index f863e6692..2f195a6bf 100644 --- a/vendor/nim-chronos/chronos/transports/datagram.nim +++ b/vendor/nim-chronos/chronos/transports/datagram.nim @@ -7,7 +7,10 @@ # Apache License, version 2.0, (LICENSE-APACHEv2) # MIT license (LICENSE-MIT) -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/[net, nativesockets, os, deques] import ".."/[selectors2, asyncloop, handles] @@ -768,13 +771,17 @@ proc send*(transp: DatagramTransport, pbytes: pointer, transp.resumeWrite() return retFuture -proc send*(transp: DatagramTransport, msg: string, msglen = -1): Future[void] = +proc send*(transp: DatagramTransport, msg: sink string, + msglen = -1): Future[void] = ## Send string ``msg`` using transport ``transp`` to remote destination ## address which was bounded on transport. var retFuture = newFutureStr[void]("datagram.transport.send(string)") transp.checkClosed(retFuture) - if not isLiteral(msg): - shallowCopy(retFuture.gcholder, msg) + when declared(shallowCopy): + if not(isLiteral(msg)): + shallowCopy(retFuture.gcholder, msg) + else: + retFuture.gcholder = msg else: retFuture.gcholder = msg let length = if msglen <= 0: len(msg) else: msglen @@ -786,14 +793,17 @@ proc send*(transp: DatagramTransport, msg: string, msglen = -1): Future[void] = transp.resumeWrite() return retFuture -proc send*[T](transp: DatagramTransport, msg: seq[T], +proc send*[T](transp: DatagramTransport, msg: sink seq[T], msglen = -1): Future[void] = ## Send string ``msg`` using transport ``transp`` to remote destination ## address which was bounded on transport. var retFuture = newFutureSeq[void, T]("datagram.transport.send(seq)") transp.checkClosed(retFuture) - if not isLiteral(msg): - shallowCopy(retFuture.gcholder, msg) + when declared(shallowCopy): + if not(isLiteral(msg)): + shallowCopy(retFuture.gcholder, msg) + else: + retFuture.gcholder = msg else: retFuture.gcholder = msg let length = if msglen <= 0: (len(msg) * sizeof(T)) else: (msglen * sizeof(T)) @@ -819,13 +829,16 @@ proc sendTo*(transp: DatagramTransport, remote: TransportAddress, return retFuture proc sendTo*(transp: DatagramTransport, remote: TransportAddress, - msg: string, msglen = -1): Future[void] = + msg: sink string, msglen = -1): Future[void] = ## Send string ``msg`` using transport ``transp`` to remote destination ## address ``remote``. var retFuture = newFutureStr[void]("datagram.transport.sendTo(string)") transp.checkClosed(retFuture) - if not isLiteral(msg): - shallowCopy(retFuture.gcholder, msg) + when declared(shallowCopy): + if not(isLiteral(msg)): + shallowCopy(retFuture.gcholder, msg) + else: + retFuture.gcholder = msg else: retFuture.gcholder = msg let length = if msglen <= 0: len(msg) else: msglen @@ -839,13 +852,16 @@ proc sendTo*(transp: DatagramTransport, remote: TransportAddress, return retFuture proc sendTo*[T](transp: DatagramTransport, remote: TransportAddress, - msg: seq[T], msglen = -1): Future[void] = + msg: sink seq[T], msglen = -1): Future[void] = ## Send sequence ``msg`` using transport ``transp`` to remote destination ## address ``remote``. var retFuture = newFutureSeq[void, T]("datagram.transport.sendTo(seq)") transp.checkClosed(retFuture) - if not isLiteral(msg): - shallowCopy(retFuture.gcholder, msg) + when declared(shallowCopy): + if not(isLiteral(msg)): + shallowCopy(retFuture.gcholder, msg) + else: + retFuture.gcholder = msg else: retFuture.gcholder = msg let length = if msglen <= 0: (len(msg) * sizeof(T)) else: (msglen * sizeof(T)) @@ -864,7 +880,10 @@ proc peekMessage*(transp: DatagramTransport, msg: var seq[byte], if ReadError in transp.state: transp.state.excl(ReadError) raise transp.getError() - shallowCopy(msg, transp.buffer) + when declared(shallowCopy): + shallowCopy(msg, transp.buffer) + else: + msg = transp.buffer msglen = transp.buflen proc getMessage*(transp: DatagramTransport): seq[byte] {. diff --git a/vendor/nim-chronos/chronos/transports/ipnet.nim b/vendor/nim-chronos/chronos/transports/ipnet.nim index 270ccdee0..ec7c690fb 100644 --- a/vendor/nim-chronos/chronos/transports/ipnet.nim +++ b/vendor/nim-chronos/chronos/transports/ipnet.nim @@ -9,7 +9,10 @@ ## This module implements various IP network utility procedures. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/strutils import stew/endians2 diff --git a/vendor/nim-chronos/chronos/transports/osnet.nim b/vendor/nim-chronos/chronos/transports/osnet.nim index 592992ecd..62569ac41 100644 --- a/vendor/nim-chronos/chronos/transports/osnet.nim +++ b/vendor/nim-chronos/chronos/transports/osnet.nim @@ -10,7 +10,10 @@ ## This module implements cross-platform network interfaces list. ## Currently supported OSes are Windows, Linux, MacOS, BSD(not tested). -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/algorithm from std/strutils import toHex diff --git a/vendor/nim-chronos/chronos/transports/stream.nim b/vendor/nim-chronos/chronos/transports/stream.nim index 90512c82b..3ec133139 100644 --- a/vendor/nim-chronos/chronos/transports/stream.nim +++ b/vendor/nim-chronos/chronos/transports/stream.nim @@ -7,7 +7,10 @@ # Apache License, version 2.0, (LICENSE-APACHEv2) # MIT license (LICENSE-MIT) -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/[net, nativesockets, os, deques] import ".."/[asyncloop, handles, selectors2] @@ -2116,7 +2119,8 @@ proc write*(transp: StreamTransport, pbytes: pointer, transp.resumeWrite() return retFuture -proc write*(transp: StreamTransport, msg: string, msglen = -1): Future[int] = +proc write*(transp: StreamTransport, msg: sink string, + msglen = -1): Future[int] = ## Write data from string ``msg`` using transport ``transp``. var retFuture = newFutureStr[int]("stream.transport.write(string)") transp.checkClosed(retFuture) @@ -2134,12 +2138,17 @@ proc write*(transp: StreamTransport, msg: string, msglen = -1): Future[int] = let written = nbytes - rbytes # In case fastWrite wrote some - pbytes = if not(isLiteral(msg)): - shallowCopy(retFuture.gcholder, msg) - cast[ptr byte](addr retFuture.gcholder[written]) - else: - retFuture.gcholder = msg[written..> $GITHUB_PATH + - name: 'Install dependencies (macOS)' + if: runner.os == 'macOS' && matrix.branch == 'devel' + run: | + brew install openssl@1.1 + ln -s $(brew --prefix)/opt/openssl/lib/libcrypto.1.1.dylib /usr/local/lib/ + ln -s $(brew --prefix)/opt/openssl/lib/libssl.1.1.dylib /usr/local/lib/ + - name: Restore rocksdb from cache (Macos) if: runner.os != 'Windows' id: rocksdb-cache @@ -230,10 +237,6 @@ jobs: run: | export PLATFORM="${{ matrix.target.os }}-${{ matrix.target.cpu }}" export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib" - if [[ "${{ matrix.target.os }}" == "windows" ]]; then - # https://github.com/status-im/nimbus-eth2/issues/3121 - export NIMFLAGS="-d:nimRawSetjmp" - fi nim --version nimble --version nimble install -y --depsOnly diff --git a/vendor/nim-eth/README.md b/vendor/nim-eth/README.md index f5b66a480..b4ea1c367 100644 --- a/vendor/nim-eth/README.md +++ b/vendor/nim-eth/README.md @@ -22,12 +22,6 @@ Ethereum-related utilities written in Nim. Includes things like Bloom filters, p ## Prerequisites - Nim & Nimble -- RocksDB, SQLite, LMDB (required for the trie backend tests) - -E.g. on Ubuntu one can run: -``` -apt install -y librocksdb-dev liblmdb-dev sqlite3 -``` ## Building & Testing ``` diff --git a/vendor/nim-eth/doc/p2p.md b/vendor/nim-eth/doc/p2p.md index d2534b296..f52b4740c 100644 --- a/vendor/nim-eth/doc/p2p.md +++ b/vendor/nim-eth/doc/p2p.md @@ -56,7 +56,6 @@ proc newEthereumNode*(keys: KeyPair, ```nim node.addCapability(eth) - node.addCapability(shh) ``` Each supplied protocol identifier is a name of a protocol introduced diff --git a/vendor/nim-eth/eth.nimble b/vendor/nim-eth/eth.nimble index cdfe5cdba..a9f8d18a0 100644 --- a/vendor/nim-eth/eth.nimble +++ b/vendor/nim-eth/eth.nimble @@ -8,7 +8,6 @@ requires "nim >= 1.2.0", "nimcrypto", "stint", "secp256k1", - "rocksdb", "chronos", "chronicles", "stew", @@ -19,9 +18,15 @@ requires "nim >= 1.2.0", "testutils", "unittest2" +let styleCheckStyle = + if (NimMajor, NimMinor) < (1, 6): + "hint" + else: + "error" + let commonParams = " --verbosity:0 --hints:off --skipUserCfg:on " & - "--warning[ObservableStores]:off --styleCheck:usages --styleCheck:hint " & - getEnv("NIMFLAGS") & " " + "--warning[ObservableStores]:off --styleCheck:usages --styleCheck:" & + styleCheckStyle & " " & getEnv("NIMFLAGS") & " " proc runTest(path: string, release: bool = true, chronosStrict = true) = echo "\nBuilding and running: ", path diff --git a/vendor/nim-eth/eth/bloom.nim b/vendor/nim-eth/eth/bloom.nim index a8735a68e..0976debe1 100644 --- a/vendor/nim-eth/eth/bloom.nim +++ b/vendor/nim-eth/eth/bloom.nim @@ -1,4 +1,4 @@ -import stint, nimcrypto/[keccak, hash] +import stint, ./common/eth_hash type UInt2048 = StUint[2048] @@ -27,8 +27,8 @@ proc init*(_: type BloomFilter, h: MDigest[256]): BloomFilter = result.incl(h) # TODO: The following 2 procs should be one genric, but it doesn't compile. Nim bug? -proc incl*(f: var BloomFilter, v: string) = f.incl(keccak256.digest(v)) -proc incl*(f: var BloomFilter, v: openArray[byte]) = f.incl(keccak256.digest(v)) +proc incl*(f: var BloomFilter, v: string) = f.incl(keccakHash(v)) +proc incl*(f: var BloomFilter, v: openArray[byte]) = f.incl(keccakHash(v)) proc contains*(f: BloomFilter, h: MDigest[256]): bool = for bits in bloomBits(h): @@ -36,4 +36,4 @@ proc contains*(f: BloomFilter, h: MDigest[256]): bool = return true template contains*[T](f: BloomFilter, v: openArray[T]): bool = - f.contains(keccak256.digest(v)) + f.contains(keccakHash(v)) diff --git a/vendor/nim-eth/eth/common.nim b/vendor/nim-eth/eth/common.nim index abe3686c4..3cba37dc9 100644 --- a/vendor/nim-eth/eth/common.nim +++ b/vendor/nim-eth/eth/common.nim @@ -1,2 +1,2 @@ -import ./common/[eth_types, utils] -export eth_types, utils +import ./common/[eth_types_rlp, utils] +export eth_types_rlp, utils diff --git a/vendor/nim-eth/eth/common/chaindb.nim b/vendor/nim-eth/eth/common/chaindb.nim new file mode 100644 index 000000000..94750777b --- /dev/null +++ b/vendor/nim-eth/eth/common/chaindb.nim @@ -0,0 +1,100 @@ +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +import + chronicles, + ./eth_types_rlp, + ../rlp, + ../trie/db + +export eth_types_rlp, rlp, db + +type + AbstractChainDB* = ref object of RootRef + +proc notImplemented(name: string) = + debug "Method not implemented", meth = name + +method genesisHash*(db: AbstractChainDB): KeccakHash + {.base, gcsafe, raises: [Defect].} = + notImplemented("genesisHash") + +method getBlockHeader*(db: AbstractChainDB, b: HashOrNum, + output: var BlockHeader): bool {.base, gcsafe, raises: [RlpError, Defect].} = + notImplemented("getBlockHeader") + +proc getBlockHeader*(db: AbstractChainDB, hash: KeccakHash): BlockHeaderRef {.gcsafe.} = + new result + if not db.getBlockHeader(HashOrNum(isHash: true, hash: hash), result[]): + return nil + +proc getBlockHeader*(db: AbstractChainDB, b: BlockNumber): BlockHeaderRef {.gcsafe.} = + new result + if not db.getBlockHeader(HashOrNum(isHash: false, number: b), result[]): + return nil + +# Need to add `RlpError` and sometimes `CatchableError` as the implementations +# of these methods in nimbus-eth1 will raise these. Using `CatchableError` +# because some can raise for errors not know to this repository such as +# `CanonicalHeadNotFound`. It would probably be better to use Result. +method getBestBlockHeader*(self: AbstractChainDB): BlockHeader + {.base, gcsafe, raises: [RlpError, CatchableError, Defect].} = + notImplemented("getBestBlockHeader") + +method getSuccessorHeader*(db: AbstractChainDB, h: BlockHeader, + output: var BlockHeader, skip = 0'u): bool + {.base, gcsafe, raises: [RlpError, Defect].} = + notImplemented("getSuccessorHeader") + +method getAncestorHeader*(db: AbstractChainDB, h: BlockHeader, + output: var BlockHeader, skip = 0'u): bool + {.base, gcsafe, raises: [RlpError, Defect].} = + notImplemented("getAncestorHeader") + +method getBlockBody*(db: AbstractChainDB, blockHash: KeccakHash): BlockBodyRef + {.base, gcsafe, raises: [RlpError, Defect].} = + notImplemented("getBlockBody") + +method getReceipt*(db: AbstractChainDB, hash: KeccakHash): ReceiptRef {.base, gcsafe.} = + notImplemented("getReceipt") + +method getTrieDB*(db: AbstractChainDB): TrieDatabaseRef + {.base, gcsafe, raises: [Defect].} = + notImplemented("getTrieDB") + +method getCodeByHash*(db: AbstractChainDB, hash: KeccakHash): Blob {.base, gcsafe.} = + notImplemented("getCodeByHash") + +method getSetting*(db: AbstractChainDB, key: string): seq[byte] {.base, gcsafe.} = + notImplemented("getSetting") + +method setSetting*(db: AbstractChainDB, key: string, val: openArray[byte]) {.base, gcsafe.} = + notImplemented("setSetting") + +method getHeaderProof*(db: AbstractChainDB, req: ProofRequest): Blob {.base, gcsafe.} = + notImplemented("getHeaderProof") + +method getProof*(db: AbstractChainDB, req: ProofRequest): Blob {.base, gcsafe.} = + notImplemented("getProof") + +method getHelperTrieProof*(db: AbstractChainDB, req: HelperTrieProofRequest): Blob {.base, gcsafe.} = + notImplemented("getHelperTrieProof") + +method getTransactionStatus*(db: AbstractChainDB, txHash: KeccakHash): TransactionStatusMsg {.base, gcsafe.} = + notImplemented("getTransactionStatus") + +method addTransactions*(db: AbstractChainDB, transactions: openArray[Transaction]) {.base, gcsafe.} = + notImplemented("addTransactions") + +method persistBlocks*(db: AbstractChainDB, headers: openArray[BlockHeader], bodies: openArray[BlockBody]): ValidationResult {.base, gcsafe.} = + notImplemented("persistBlocks") + +method getForkId*(db: AbstractChainDB, n: BlockNumber): ForkID {.base, gcsafe.} = + # EIP 2364/2124 + notImplemented("getForkId") + +method getTotalDifficulty*(db: AbstractChainDB): DifficultyInt {.base, gcsafe, raises: [RlpError, Defect].} = + notImplemented("getTotalDifficulty") diff --git a/vendor/nim-eth/eth/common/eth_hash.nim b/vendor/nim-eth/eth/common/eth_hash.nim new file mode 100644 index 000000000..f4fbb3f49 --- /dev/null +++ b/vendor/nim-eth/eth/common/eth_hash.nim @@ -0,0 +1,44 @@ +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} + +## keccak256 is used across ethereum as the "default" hash function and this +## module provides a type and some helpers to produce such hashes + +import + nimcrypto/[keccak, hash] + +export + keccak.update, keccak.finish, hash + +type + KeccakHash* = MDigest[256] + ## A hash value computed using keccak256 + ## note: this aliases Eth2Digest too, which uses a different hash! + +template withKeccakHash*(body: untyped): KeccakHash = + ## This little helper will init the hash function and return the sliced + ## hash: + ## let hashOfData = withHash: h.update(data) + block: + var h {.inject.}: keccak256 + # init(h) # not needed for new instance + body + finish(h) + +func keccakHash*(input: openArray[byte]): KeccakHash = + keccak256.digest(input) +func keccakHash*(input: openArray[char]): KeccakHash = + keccak256.digest(input) + +func keccakHash*(a, b: openArray[byte]): KeccakHash = + withKeccakHash: + h.update a + h.update b diff --git a/vendor/nim-eth/eth/common/eth_hash_rlp.nim b/vendor/nim-eth/eth/common/eth_hash_rlp.nim new file mode 100644 index 000000000..4fcfc0463 --- /dev/null +++ b/vendor/nim-eth/eth/common/eth_hash_rlp.nim @@ -0,0 +1,17 @@ +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +import + ./eth_hash, + ../rlp + +export eth_hash, rlp + +proc read*(rlp: var Rlp, T: typedesc[MDigest]): T = + result.data = rlp.read(type(result.data)) + +proc append*(rlpWriter: var RlpWriter, a: MDigest) = + rlpWriter.append(a.data) diff --git a/vendor/nim-eth/eth/common/eth_types.nim b/vendor/nim-eth/eth/common/eth_types.nim index 7e771a427..f85854eb2 100644 --- a/vendor/nim-eth/eth/common/eth_types.nim +++ b/vendor/nim-eth/eth/common/eth_types.nim @@ -1,10 +1,25 @@ +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} + +## Core ethereum types and smalll helpers - keep focused as it gets imported +## from many places + import - std/[strutils, options, times], - stew/[endians2, byteutils], chronicles, stint, nimcrypto/[keccak, hash], - ../rlp, ../trie/[trie_defs, db] + std/[options, strutils, times], + stew/[byteutils, endians2], stint, + ./eth_hash export - stint, read, append, KeccakHash, rlp, options + options, stint, eth_hash, + times.Time, times.fromUnix, times.toUnix type Hash256* = MDigest[256] @@ -17,8 +32,6 @@ type BloomFilter* = array[256, byte] EthAddress* = array[20, byte] - WhisperIdentity* = array[60, byte] - DifficultyInt* = UInt256 GasInt* = int64 ## Type alias used for gas computation @@ -183,8 +196,6 @@ type fromLevel*: uint auxReq*: uint - AbstractChainDB* = ref object of RootRef - BlockHeaderRef* = ref BlockHeader BlockBodyRef* = ref BlockBody ReceiptRef* = ref Receipt @@ -200,6 +211,11 @@ const Eip2930Receipt* = TxEip2930 Eip1559Receipt* = TxEip1559 + # TODO clean these up + EMPTY_ROOT_HASH* = "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".toDigest + EMPTY_UNCLE_HASH* = "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347".toDigest + EMPTY_CODE_HASH* = "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470".toDigest + when BlockNumber is int64: ## The goal of these templates is to make it easier to switch ## the block number type to a different representation @@ -260,8 +276,8 @@ func toUint*(n: BlockNonce): uint64 = proc newAccount*(nonce: AccountNonce = 0, balance: UInt256 = 0.u256): Account = result.nonce = nonce result.balance = balance - result.storageRoot = emptyRlpHash - result.codeHash = blankStringHash + result.storageRoot = EMPTY_ROOT_HASH + result.codeHash = EMPTY_CODE_HASH proc hasStatus*(rec: Receipt): bool {.inline.} = rec.isHash == false @@ -282,233 +298,6 @@ func destination*(tx: Transaction): EthAddress = if tx.to.isSome: return tx.to.get -# -# Rlp serialization: -# - -proc read*(rlp: var Rlp, T: type StUint): T {.inline.} = - if rlp.isBlob: - let bytes = rlp.toBytes - if bytes.len > 0: - # be sure the amount of bytes matches the size of the stint - if bytes.len <= sizeof(result): - result.initFromBytesBE(bytes) - else: - raise newException(RlpTypeMismatch, "Unsigned integer expected, but the source RLP has the wrong length") - else: - result = 0.to(T) - else: - raise newException(RlpTypeMismatch, "Unsigned integer expected, but the source RLP is a list") - - rlp.skipElem - -proc append*(rlpWriter: var RlpWriter, value: StUint) = - if value > 128: - let bytes = value.toByteArrayBE - let nonZeroBytes = significantBytesBE(bytes) - rlpWriter.append bytes.toOpenArray(bytes.len - nonZeroBytes, - bytes.len - 1) - else: - rlpWriter.append(value.truncate(int)) - -proc read*(rlp: var Rlp, T: type StInt): T {.inline.} = - # The Ethereum Yellow Paper defines the RLP serialization only - # for unsigned integers: - {.fatal: "RLP serialization of signed integers is not allowed".} - discard - -proc append*(rlpWriter: var RlpWriter, value: StInt) = - # The Ethereum Yellow Paper defines the RLP serialization only - # for unsigned integers: - {.fatal: "RLP serialization of signed integers is not allowed".} - discard - -proc append*[T](w: var RlpWriter, val: Option[T]) = - if val.isSome: - w.append(val.get()) - else: - w.append("") - -proc appendTxLegacy(w: var RlpWriter, tx: Transaction) = - w.startList(9) - w.append(tx.nonce) - w.append(tx.gasPrice) - w.append(tx.gasLimit) - w.append(tx.to) - w.append(tx.value) - w.append(tx.payload) - w.append(tx.V) - w.append(tx.R) - w.append(tx.S) - -proc appendTxEip2930(w: var RlpWriter, tx: Transaction) = - w.append(1) - w.startList(11) - w.append(tx.chainId.uint64) - w.append(tx.nonce) - w.append(tx.gasPrice) - w.append(tx.gasLimit) - w.append(tx.to) - w.append(tx.value) - w.append(tx.payload) - w.append(tx.accessList) - w.append(tx.V) - w.append(tx.R) - w.append(tx.S) - -proc appendTxEip1559(w: var RlpWriter, tx: Transaction) = - w.append(2) - w.startList(12) - w.append(tx.chainId.uint64) - w.append(tx.nonce) - w.append(tx.maxPriorityFee) - w.append(tx.maxFee) - w.append(tx.gasLimit) - w.append(tx.to) - w.append(tx.value) - w.append(tx.payload) - w.append(tx.accessList) - w.append(tx.V) - w.append(tx.R) - w.append(tx.S) - -proc append*(w: var RlpWriter, tx: Transaction) = - case tx.txType - of TxLegacy: - w.appendTxLegacy(tx) - of TxEip2930: - w.appendTxEip2930(tx) - of TxEip1559: - w.appendTxEip1559(tx) - -template read[T](rlp: var Rlp, val: var T)= - val = rlp.read(type val) - -proc read[T](rlp: var Rlp, val: var Option[T])= - if rlp.blobLen != 0: - val = some(rlp.read(T)) - else: - rlp.skipElem - -proc readTxLegacy(rlp: var Rlp, tx: var Transaction)= - tx.txType = TxLegacy - rlp.tryEnterList() - rlp.read(tx.nonce) - rlp.read(tx.gasPrice) - rlp.read(tx.gasLimit) - rlp.read(tx.to) - rlp.read(tx.value) - rlp.read(tx.payload) - rlp.read(tx.V) - rlp.read(tx.R) - rlp.read(tx.S) - -proc readTxEip2930(rlp: var Rlp, tx: var Transaction)= - tx.txType = TxEip2930 - rlp.tryEnterList() - tx.chainId = rlp.read(uint64).ChainId - rlp.read(tx.nonce) - rlp.read(tx.gasPrice) - rlp.read(tx.gasLimit) - rlp.read(tx.to) - rlp.read(tx.value) - rlp.read(tx.payload) - rlp.read(tx.accessList) - rlp.read(tx.V) - rlp.read(tx.R) - rlp.read(tx.S) - -proc readTxEip1559(rlp: var Rlp, tx: var Transaction)= - tx.txType = TxEip1559 - rlp.tryEnterList() - tx.chainId = rlp.read(uint64).ChainId - rlp.read(tx.nonce) - rlp.read(tx.maxPriorityFee) - rlp.read(tx.maxFee) - rlp.read(tx.gasLimit) - rlp.read(tx.to) - rlp.read(tx.value) - rlp.read(tx.payload) - rlp.read(tx.accessList) - rlp.read(tx.V) - rlp.read(tx.R) - rlp.read(tx.S) - -proc readTxTyped(rlp: var Rlp, tx: var Transaction) {.inline.} = - # EIP-2718: We MUST decode the first byte as a byte, not `rlp.read(int)`. - # If decoded with `rlp.read(int)`, bad transaction data (from the network) - # or even just incorrectly framed data for other reasons fails with - # any of these misleading error messages: - # - "Message too large to fit in memory" - # - "Number encoded with a leading zero" - # - "Read past the end of the RLP stream" - # - "Small number encoded in a non-canonical way" - # - "Attempt to read an Int value past the RLP end" - # - "The RLP contains a larger than expected Int value" - if not rlp.isSingleByte: - if not rlp.hasData: - raise newException(MalformedRlpError, - "Transaction expected but source RLP is empty") - raise newException(MalformedRlpError, - "TypedTransaction type byte is out of range, must be 0x00 to 0x7f") - let txType = rlp.getByteValue - rlp.position += 1 - - case TxType(txType): - of TxEip2930: - rlp.readTxEip2930(tx) - of TxEip1559: - rlp.readTxEip1559(tx) - else: - raise newException(UnsupportedRlpError, - "TypedTransaction type must be 1 or 2 in this version, got " & $txType) - -proc read*(rlp: var Rlp, T: type Transaction): T = - # Individual transactions are encoded and stored as either `RLP([fields..])` - # for legacy transactions, or `Type || RLP([fields..])`. Both of these - # encodings are byte sequences. The part after `Type` doesn't have to be - # RLP in theory, but all types so far use RLP. EIP-2718 covers this. - if rlp.isList: - rlp.readTxLegacy(result) - else: - rlp.readTxTyped(result) - -proc read*(rlp: var Rlp, - T: (type seq[Transaction]) | (type openArray[Transaction])): seq[Transaction] = - # In arrays (sequences), transactions are encoded as either `RLP([fields..])` - # for legacy transactions, or `RLP(Type || RLP([fields..]))` for all typed - # transactions to date. Spot the extra `RLP(..)` blob encoding, to make it - # valid RLP inside a larger RLP. EIP-2976 covers this, "Typed Transactions - # over Gossip", although it's not very clear about the blob encoding. - # - # In practice the extra `RLP(..)` applies to all arrays/sequences of - # transactions. In principle, all aggregates (objects etc.), but - # arrays/sequences are enough. In `eth/65` protocol this is essential for - # the correct encoding/decoding of `Transactions`, `NewBlock`, and - # `PooledTransactions` network calls. We need a type match on both - # `openArray[Transaction]` and `seq[Transaction]` to catch all cases. - if not rlp.isList: - raise newException(RlpTypeMismatch, - "Transaction list expected, but source RLP is not a list") - for item in rlp: - var tx: Transaction - if item.isList: - item.readTxLegacy(tx) - else: - var rr = rlpFromBytes(rlp.read(Blob)) - rr.readTxTyped(tx) - result.add tx - -proc append*(rlpWriter: var RlpWriter, - txs: seq[Transaction] | openArray[Transaction]) {.inline.} = - # See above about encoding arrays/sequences of transactions. - rlpWriter.startList(txs.len) - for tx in txs: - if tx.txType == TxLegacy: - rlpWriter.append(tx) - else: - rlpWriter.append(rlp.encode(tx)) - func init*(T: type BlockHashOrNumber, str: string): T {.raises: [ValueError, Defect].} = if str.startsWith "0x": @@ -527,178 +316,9 @@ func `$`*(x: BlockHashOrNumber): string = else: $x.number -proc append*(w: var RlpWriter, rec: Receipt) = - if rec.receiptType in {Eip2930Receipt, Eip1559Receipt}: - w.append(rec.receiptType.int) - - w.startList(4) - if rec.isHash: - w.append(rec.hash) - else: - w.append(rec.status.uint8) - - w.append(rec.cumulativeGasUsed) - w.append(rec.bloom) - w.append(rec.logs) - -proc read*(rlp: var Rlp, T: type Receipt): T = - if rlp.isList: - result.receiptType = LegacyReceipt - else: - # EIP 2718 - let recType = rlp.read(int) - if recType notin {1, 2}: - raise newException(UnsupportedRlpError, - "TxType expect 1 or 2 got " & $recType) - result.receiptType = ReceiptType(recType) - - rlp.tryEnterList() - if rlp.isBlob and rlp.blobLen in {0, 1}: - result.isHash = false - result.status = rlp.read(uint8) == 1 - elif rlp.isBlob and rlp.blobLen == 32: - result.isHash = true - result.hash = rlp.read(Hash256) - else: - raise newException(RlpTypeMismatch, - "HashOrStatus expected, but the source RLP is not a blob of right size.") - - rlp.read(result.cumulativeGasUsed) - rlp.read(result.bloom) - rlp.read(result.logs) - -proc read*(rlp: var Rlp, T: type Time): T {.inline.} = - result = fromUnix(rlp.read(int64)) - -proc append*(rlpWriter: var RlpWriter, value: HashOrNum) = - case value.isHash - of true: - rlpWriter.append(value.hash) - else: - rlpWriter.append(value.number) - -proc read*(rlp: var Rlp, T: type HashOrNum): T = - if rlp.blobLen == 32: - result = HashOrNum(isHash: true, hash: rlp.read(Hash256)) - else: - result = HashOrNum(isHash: false, number: rlp.read(BlockNumber)) - -proc append*(rlpWriter: var RlpWriter, t: Time) {.inline.} = - rlpWriter.append(t.toUnix()) - -proc append*(w: var RlpWriter, h: BlockHeader) = - w.startList(if h.fee.isSome: 16 else: 15) - for k, v in fieldPairs(h): - when k != "fee": - w.append(v) - if h.fee.isSome: - w.append(h.fee.get()) - -proc read*(rlp: var Rlp, T: type BlockHeader): T = - let len = rlp.listLen - - if len notin {15, 16}: - raise newException(UnsupportedRlpError, - "BlockHeader elems should be 15 or 16 got " & $len) - - rlp.tryEnterList() - for k, v in fieldPairs(result): - when k != "fee": - v = rlp.read(type v) - - if len == 16: - # EIP-1559 - result.baseFee = rlp.read(UInt256) - -proc rlpHash*[T](v: T): Hash256 = - keccak256.digest(rlp.encode(v)) - -func blockHash*(h: BlockHeader): KeccakHash {.inline.} = rlpHash(h) - -proc notImplemented = - debug "Method not implemented" - template hasData*(b: Blob): bool = b.len > 0 template hasData*(r: EthResourceRefs): bool = r != nil template deref*(b: Blob): auto = b template deref*(o: Option): auto = o.get template deref*(r: EthResourceRefs): auto = r[] - -method genesisHash*(db: AbstractChainDB): KeccakHash - {.base, gcsafe, raises: [Defect].} = - notImplemented() - -method getBlockHeader*(db: AbstractChainDB, b: HashOrNum, - output: var BlockHeader): bool {.base, gcsafe, raises: [RlpError, Defect].} = - notImplemented() - -proc getBlockHeader*(db: AbstractChainDB, hash: KeccakHash): BlockHeaderRef {.gcsafe.} = - new result - if not db.getBlockHeader(HashOrNum(isHash: true, hash: hash), result[]): - return nil - -proc getBlockHeader*(db: AbstractChainDB, b: BlockNumber): BlockHeaderRef {.gcsafe.} = - new result - if not db.getBlockHeader(HashOrNum(isHash: false, number: b), result[]): - return nil - -# Need to add `RlpError` and sometimes `CatchableError` as the implementations -# of these methods in nimbus-eth1 will raise these. Using `CatchableError` -# because some can raise for errors not know to this repository such as -# `CanonicalHeadNotFound`. It would probably be better to use Result. -method getBestBlockHeader*(self: AbstractChainDB): BlockHeader - {.base, gcsafe, raises: [RlpError, CatchableError, Defect].} = - notImplemented() - -method getSuccessorHeader*(db: AbstractChainDB, h: BlockHeader, - output: var BlockHeader, skip = 0'u): bool - {.base, gcsafe, raises: [RlpError, Defect].} = - notImplemented() - -method getAncestorHeader*(db: AbstractChainDB, h: BlockHeader, - output: var BlockHeader, skip = 0'u): bool - {.base, gcsafe, raises: [RlpError, Defect].} = - notImplemented() - -method getBlockBody*(db: AbstractChainDB, blockHash: KeccakHash): BlockBodyRef - {.base, gcsafe, raises: [Defect].} = - notImplemented() - -method getReceipt*(db: AbstractChainDB, hash: KeccakHash): ReceiptRef {.base, gcsafe.} = - notImplemented() - -method getTrieDB*(db: AbstractChainDB): TrieDatabaseRef - {.base, gcsafe, raises: [Defect].} = - notImplemented() - -method getCodeByHash*(db: AbstractChainDB, hash: KeccakHash): Blob {.base, gcsafe.} = - notImplemented() - -method getSetting*(db: AbstractChainDB, key: string): seq[byte] {.base, gcsafe.} = - notImplemented() - -method setSetting*(db: AbstractChainDB, key: string, val: openArray[byte]) {.base, gcsafe.} = - notImplemented() - -method getHeaderProof*(db: AbstractChainDB, req: ProofRequest): Blob {.base, gcsafe.} = - notImplemented() - -method getProof*(db: AbstractChainDB, req: ProofRequest): Blob {.base, gcsafe.} = - notImplemented() - -method getHelperTrieProof*(db: AbstractChainDB, req: HelperTrieProofRequest): Blob {.base, gcsafe.} = - notImplemented() - -method getTransactionStatus*(db: AbstractChainDB, txHash: KeccakHash): TransactionStatusMsg {.base, gcsafe.} = - notImplemented() - -method addTransactions*(db: AbstractChainDB, transactions: openArray[Transaction]) {.base, gcsafe.} = - notImplemented() - -method persistBlocks*(db: AbstractChainDB, headers: openArray[BlockHeader], bodies: openArray[BlockBody]): ValidationResult {.base, gcsafe.} = - notImplemented() - -method getForkId*(db: AbstractChainDB, n: BlockNumber): ForkID {.base, gcsafe.} = - # EIP 2364/2124 - notImplemented() diff --git a/vendor/nim-eth/eth/common/eth_types_rlp.nim b/vendor/nim-eth/eth/common/eth_types_rlp.nim new file mode 100644 index 000000000..cf0b119af --- /dev/null +++ b/vendor/nim-eth/eth/common/eth_types_rlp.nim @@ -0,0 +1,338 @@ +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +import + "."/[eth_types, eth_hash_rlp], + ../rlp + +from stew/objects + import checkedEnumAssign + +export + eth_types, eth_hash_rlp, rlp + +# +# Rlp serialization: +# + +proc read*(rlp: var Rlp, T: type StUint): T {.inline.} = + if rlp.isBlob: + let bytes = rlp.toBytes + if bytes.len > 0: + # be sure the amount of bytes matches the size of the stint + if bytes.len <= sizeof(result): + result.initFromBytesBE(bytes) + else: + raise newException(RlpTypeMismatch, "Unsigned integer expected, but the source RLP has the wrong length") + else: + result = 0.to(T) + else: + raise newException(RlpTypeMismatch, "Unsigned integer expected, but the source RLP is a list") + + rlp.skipElem + +proc append*(rlpWriter: var RlpWriter, value: StUint) = + if value > 128: + let bytes = value.toByteArrayBE + let nonZeroBytes = significantBytesBE(bytes) + rlpWriter.append bytes.toOpenArray(bytes.len - nonZeroBytes, + bytes.len - 1) + else: + rlpWriter.append(value.truncate(int)) + +proc read*(rlp: var Rlp, T: type StInt): T {.inline.} = + # The Ethereum Yellow Paper defines the RLP serialization only + # for unsigned integers: + {.fatal: "RLP serialization of signed integers is not allowed".} + discard + +proc append*(rlpWriter: var RlpWriter, value: StInt) = + # The Ethereum Yellow Paper defines the RLP serialization only + # for unsigned integers: + {.fatal: "RLP serialization of signed integers is not allowed".} + discard + +proc append*[T](w: var RlpWriter, val: Option[T]) = + if val.isSome: + w.append(val.get()) + else: + w.append("") + +proc appendTxLegacy(w: var RlpWriter, tx: Transaction) = + w.startList(9) + w.append(tx.nonce) + w.append(tx.gasPrice) + w.append(tx.gasLimit) + w.append(tx.to) + w.append(tx.value) + w.append(tx.payload) + w.append(tx.V) + w.append(tx.R) + w.append(tx.S) + +proc appendTxEip2930(w: var RlpWriter, tx: Transaction) = + w.append(1) + w.startList(11) + w.append(tx.chainId.uint64) + w.append(tx.nonce) + w.append(tx.gasPrice) + w.append(tx.gasLimit) + w.append(tx.to) + w.append(tx.value) + w.append(tx.payload) + w.append(tx.accessList) + w.append(tx.V) + w.append(tx.R) + w.append(tx.S) + +proc appendTxEip1559(w: var RlpWriter, tx: Transaction) = + w.append(2) + w.startList(12) + w.append(tx.chainId.uint64) + w.append(tx.nonce) + w.append(tx.maxPriorityFee) + w.append(tx.maxFee) + w.append(tx.gasLimit) + w.append(tx.to) + w.append(tx.value) + w.append(tx.payload) + w.append(tx.accessList) + w.append(tx.V) + w.append(tx.R) + w.append(tx.S) + +proc append*(w: var RlpWriter, tx: Transaction) = + case tx.txType + of TxLegacy: + w.appendTxLegacy(tx) + of TxEip2930: + w.appendTxEip2930(tx) + of TxEip1559: + w.appendTxEip1559(tx) + +template read[T](rlp: var Rlp, val: var T)= + val = rlp.read(type val) + +proc read[T](rlp: var Rlp, val: var Option[T])= + if rlp.blobLen != 0: + val = some(rlp.read(T)) + else: + rlp.skipElem + +proc readTxLegacy(rlp: var Rlp, tx: var Transaction)= + tx.txType = TxLegacy + rlp.tryEnterList() + rlp.read(tx.nonce) + rlp.read(tx.gasPrice) + rlp.read(tx.gasLimit) + rlp.read(tx.to) + rlp.read(tx.value) + rlp.read(tx.payload) + rlp.read(tx.V) + rlp.read(tx.R) + rlp.read(tx.S) + +proc readTxEip2930(rlp: var Rlp, tx: var Transaction)= + tx.txType = TxEip2930 + rlp.tryEnterList() + tx.chainId = rlp.read(uint64).ChainId + rlp.read(tx.nonce) + rlp.read(tx.gasPrice) + rlp.read(tx.gasLimit) + rlp.read(tx.to) + rlp.read(tx.value) + rlp.read(tx.payload) + rlp.read(tx.accessList) + rlp.read(tx.V) + rlp.read(tx.R) + rlp.read(tx.S) + +proc readTxEip1559(rlp: var Rlp, tx: var Transaction)= + tx.txType = TxEip1559 + rlp.tryEnterList() + tx.chainId = rlp.read(uint64).ChainId + rlp.read(tx.nonce) + rlp.read(tx.maxPriorityFee) + rlp.read(tx.maxFee) + rlp.read(tx.gasLimit) + rlp.read(tx.to) + rlp.read(tx.value) + rlp.read(tx.payload) + rlp.read(tx.accessList) + rlp.read(tx.V) + rlp.read(tx.R) + rlp.read(tx.S) + +proc readTxTyped(rlp: var Rlp, tx: var Transaction) {.inline.} = + # EIP-2718: We MUST decode the first byte as a byte, not `rlp.read(int)`. + # If decoded with `rlp.read(int)`, bad transaction data (from the network) + # or even just incorrectly framed data for other reasons fails with + # any of these misleading error messages: + # - "Message too large to fit in memory" + # - "Number encoded with a leading zero" + # - "Read past the end of the RLP stream" + # - "Small number encoded in a non-canonical way" + # - "Attempt to read an Int value past the RLP end" + # - "The RLP contains a larger than expected Int value" + if not rlp.isSingleByte: + if not rlp.hasData: + raise newException(MalformedRlpError, + "Transaction expected but source RLP is empty") + raise newException(MalformedRlpError, + "TypedTransaction type byte is out of range, must be 0x00 to 0x7f") + let txType = rlp.getByteValue + rlp.position += 1 + + var txVal: TxType + if checkedEnumAssign(txVal, txType): + case txVal: + of TxEip2930: + rlp.readTxEip2930(tx) + return + of TxEip1559: + rlp.readTxEip1559(tx) + return + else: + discard + + raise newException(UnsupportedRlpError, + "TypedTransaction type must be 1 or 2 in this version, got " & $txType) + + +proc read*(rlp: var Rlp, T: type Transaction): T = + # Individual transactions are encoded and stored as either `RLP([fields..])` + # for legacy transactions, or `Type || RLP([fields..])`. Both of these + # encodings are byte sequences. The part after `Type` doesn't have to be + # RLP in theory, but all types so far use RLP. EIP-2718 covers this. + if rlp.isList: + rlp.readTxLegacy(result) + else: + rlp.readTxTyped(result) + +proc read*(rlp: var Rlp, + T: (type seq[Transaction]) | (type openArray[Transaction])): seq[Transaction] = + # In arrays (sequences), transactions are encoded as either `RLP([fields..])` + # for legacy transactions, or `RLP(Type || RLP([fields..]))` for all typed + # transactions to date. Spot the extra `RLP(..)` blob encoding, to make it + # valid RLP inside a larger RLP. EIP-2976 covers this, "Typed Transactions + # over Gossip", although it's not very clear about the blob encoding. + # + # In practice the extra `RLP(..)` applies to all arrays/sequences of + # transactions. In principle, all aggregates (objects etc.), but + # arrays/sequences are enough. In `eth/65` protocol this is essential for + # the correct encoding/decoding of `Transactions`, `NewBlock`, and + # `PooledTransactions` network calls. We need a type match on both + # `openArray[Transaction]` and `seq[Transaction]` to catch all cases. + if not rlp.isList: + raise newException(RlpTypeMismatch, + "Transaction list expected, but source RLP is not a list") + for item in rlp: + var tx: Transaction + if item.isList: + item.readTxLegacy(tx) + else: + var rr = rlpFromBytes(rlp.read(Blob)) + rr.readTxTyped(tx) + result.add tx + +proc append*(rlpWriter: var RlpWriter, + txs: seq[Transaction] | openArray[Transaction]) {.inline.} = + # See above about encoding arrays/sequences of transactions. + rlpWriter.startList(txs.len) + for tx in txs: + if tx.txType == TxLegacy: + rlpWriter.append(tx) + else: + rlpWriter.append(rlp.encode(tx)) + +proc append*(w: var RlpWriter, rec: Receipt) = + if rec.receiptType in {Eip2930Receipt, Eip1559Receipt}: + w.append(rec.receiptType.int) + + w.startList(4) + if rec.isHash: + w.append(rec.hash) + else: + w.append(rec.status.uint8) + + w.append(rec.cumulativeGasUsed) + w.append(rec.bloom) + w.append(rec.logs) + +proc read*(rlp: var Rlp, T: type Receipt): T = + if rlp.isList: + result.receiptType = LegacyReceipt + else: + # EIP 2718 + let recType = rlp.read(int) + if recType notin {1, 2}: + raise newException(UnsupportedRlpError, + "TxType expect 1 or 2 got " & $recType) + result.receiptType = ReceiptType(recType) + + rlp.tryEnterList() + if rlp.isBlob and rlp.blobLen in {0, 1}: + result.isHash = false + result.status = rlp.read(uint8) == 1 + elif rlp.isBlob and rlp.blobLen == 32: + result.isHash = true + result.hash = rlp.read(Hash256) + else: + raise newException(RlpTypeMismatch, + "HashOrStatus expected, but the source RLP is not a blob of right size.") + + rlp.read(result.cumulativeGasUsed) + rlp.read(result.bloom) + rlp.read(result.logs) + +proc read*(rlp: var Rlp, T: type Time): T {.inline.} = + result = fromUnix(rlp.read(int64)) + +proc append*(rlpWriter: var RlpWriter, value: HashOrNum) = + case value.isHash + of true: + rlpWriter.append(value.hash) + else: + rlpWriter.append(value.number) + +proc read*(rlp: var Rlp, T: type HashOrNum): T = + if rlp.blobLen == 32: + result = HashOrNum(isHash: true, hash: rlp.read(Hash256)) + else: + result = HashOrNum(isHash: false, number: rlp.read(BlockNumber)) + +proc append*(rlpWriter: var RlpWriter, t: Time) {.inline.} = + rlpWriter.append(t.toUnix()) + +proc append*(w: var RlpWriter, h: BlockHeader) = + w.startList(if h.fee.isSome: 16 else: 15) + for k, v in fieldPairs(h): + when k != "fee": + w.append(v) + if h.fee.isSome: + w.append(h.fee.get()) + +proc read*(rlp: var Rlp, T: type BlockHeader): T = + let len = rlp.listLen + + if len notin {15, 16}: + raise newException(UnsupportedRlpError, + "BlockHeader elems should be 15 or 16 got " & $len) + + rlp.tryEnterList() + for k, v in fieldPairs(result): + when k != "fee": + v = rlp.read(type v) + + if len == 16: + # EIP-1559 + result.baseFee = rlp.read(UInt256) + +proc rlpHash*[T](v: T): Hash256 = + keccakHash(rlp.encode(v)) + +func blockHash*(h: BlockHeader): KeccakHash {.inline.} = rlpHash(h) + diff --git a/vendor/nim-eth/eth/common/state_accessors.nim b/vendor/nim-eth/eth/common/state_accessors.nim index d4d637070..f3f8ad0b6 100644 --- a/vendor/nim-eth/eth/common/state_accessors.nim +++ b/vendor/nim-eth/eth/common/state_accessors.nim @@ -1,6 +1,9 @@ import - ../trie/[trie_defs, db, hexary], ../rlp, - ./eth_types + ../trie/[trie_defs, db, hexary], + ../rlp, + ./chaindb + +export chaindb proc getAccount*(db: TrieDatabaseRef, rootHash: KeccakHash, diff --git a/vendor/nim-eth/eth/common/transaction.nim b/vendor/nim-eth/eth/common/transaction.nim index 2527cf278..e9c939a3a 100644 --- a/vendor/nim-eth/eth/common/transaction.nim +++ b/vendor/nim-eth/eth/common/transaction.nim @@ -1,6 +1,7 @@ import - nimcrypto/keccak, - ".."/[common, rlp, keys] + ../common/eth_types_rlp + +export eth_types_rlp const EIP155_CHAIN_ID_OFFSET* = 35'i64 @@ -64,7 +65,7 @@ func rlpEncode*(tx: Transaction): auto = case tx.txType of TxLegacy: if tx.V >= EIP155_CHAIN_ID_OFFSET: - tx.rlpEncodeEIP155 + tx.rlpEncodeEip155 else: tx.rlpEncodeLegacy of TxEip2930: @@ -74,4 +75,4 @@ func rlpEncode*(tx: Transaction): auto = func txHashNoSignature*(tx: Transaction): Hash256 = # Hash transaction without signature - keccak256.digest(rlpEncode(tx)) + keccakHash(rlpEncode(tx)) diff --git a/vendor/nim-eth/eth/db/kvstore_rocksdb.nim b/vendor/nim-eth/eth/db/kvstore_rocksdb.nim deleted file mode 100644 index fd02640b8..000000000 --- a/vendor/nim-eth/eth/db/kvstore_rocksdb.nim +++ /dev/null @@ -1,52 +0,0 @@ -{.push raises: [Defect].} - -import - std/os, - rocksdb, stew/results, - ./kvstore - -export results - -const maxOpenFiles = 512 - -type - RocksStoreRef* = ref object of RootObj - store: RocksDBInstance - -proc get*(db: RocksStoreRef, key: openArray[byte], onData: kvstore.DataProc): KvResult[bool] = - db.store.get(key, onData) - -proc find*(db: RocksStoreRef, prefix: openArray[byte], onFind: kvstore.KeyValueProc): KvResult[int] = - raiseAssert "Unimplemented" - -proc put*(db: RocksStoreRef, key, value: openArray[byte]): KvResult[void] = - db.store.put(key, value) - -proc contains*(db: RocksStoreRef, key: openArray[byte]): KvResult[bool] = - db.store.contains(key) - -proc del*(db: RocksStoreRef, key: openArray[byte]): KvResult[void] = - db.store.del(key) - -proc close*(db: RocksStoreRef) = - db.store.close - -proc init*( - T: type RocksStoreRef, basePath: string, name: string, - readOnly = false): KvResult[T] = - let - dataDir = basePath / name / "data" - backupsDir = basePath / name / "backups" - - try: - createDir(dataDir) - createDir(backupsDir) - except OSError, IOError: - return err("rocksdb: cannot create database directory") - - var store: RocksDBInstance - if (let v = store.init( - dataDir, backupsDir, readOnly, maxOpenFiles = maxOpenFiles); v.isErr): - return err(v.error) - - ok(T(store: store)) diff --git a/vendor/nim-eth/eth/db/kvstore_sqlite3.nim b/vendor/nim-eth/eth/db/kvstore_sqlite3.nim index 2c3d60954..d1d1d8881 100644 --- a/vendor/nim-eth/eth/db/kvstore_sqlite3.nim +++ b/vendor/nim-eth/eth/db/kvstore_sqlite3.nim @@ -42,6 +42,12 @@ type SqKeyspaceRef* = ref SqKeyspace + CustomFunction* = + proc ( + a: openArray[byte], + b: openArray[byte] + ): Result[seq[byte], cstring] {.noSideEffect, gcsafe, cdecl, raises: [Defect].} + template dispose(db: Sqlite) = discard sqlite3_close(db) @@ -51,6 +57,9 @@ template dispose(db: RawStmtPtr) = template dispose*(db: SqliteStmt) = discard sqlite3_finalize(RawStmtPtr db) +func isInsideTransaction*(db: SqStoreRef): bool = + sqlite3_get_autocommit(db.env) == 0 + proc release[T](x: var AutoDisposed[T]): T = result = x.val x.val = nil @@ -516,7 +525,7 @@ proc init*( except OSError, IOError: return err("sqlite: cannot create database directory") - checkErr sqlite3_open_v2(name, addr env.val, flags.cint, nil) + checkErr sqlite3_open_v2(cstring name, addr env.val, flags.cint, nil) template checkWalPragmaResult(journalModePragma: ptr sqlite3_stmt) = if (let x = sqlite3_step(journalModePragma); x != SQLITE_ROW): @@ -527,7 +536,7 @@ proc init*( discard sqlite3_finalize(journalModePragma) return err($sqlite3_errstr(x)) - if (let x = sqlite3_column_text(journalModePragma, 0); + if (let x = cstring sqlite3_column_text(journalModePragma, 0); x != "memory" and x != "wal"): discard sqlite3_finalize(journalModePragma) return err("Invalid pragma result: " & $x) @@ -593,6 +602,64 @@ proc openKvStore*(db: SqStoreRef, name = "kvstore", withoutRowid = false): KvRes tmp = SqKeyspace() # make close harmless ok res +proc customScalarBlobFunction(ctx: ptr sqlite3_context, n: cint, v: ptr ptr sqlite3_value) {.cdecl.} = + let ptrs = cast[ptr UncheckedArray[ptr sqlite3_value]](v) + let blob1 = cast[ptr UncheckedArray[byte]](sqlite3_value_blob(ptrs[][0])) + let blob2 = cast[ptr UncheckedArray[byte]](sqlite3_value_blob(ptrs[][1])) + let blob1Len = sqlite3_value_bytes(ptrs[][0]) + let blob2Len = sqlite3_value_bytes(ptrs[][1]) + # sqlite3_user_data retrieves data which was pointed by 5th param to + # sqlite3_create_function functions, which in our case is custom function + # provided by user + let usrFun = cast[CustomFunction](sqlite3_user_data(ctx)) + let s = usrFun( + toOpenArray(blob1, 0, blob1Len - 1), + toOpenArray(blob2, 0, blob2Len - 1) + ) + + try: + if s.isOk(): + let bytes = s.unsafeGet() + # try is necessessary as otherwise nim marks SQLITE_TRANSIENT as throwning + # unlisted exception. + # Using SQLITE_TRANSIENT destructor type, as it inform sqlite that data + # under provided pointer may be deleted at any moment, which is the case + # for seq[byte] as it is managed by nim gc. With this flag sqlite copy bytes + # under pointer and then realeases them itself. + sqlite3_result_blob(ctx, unsafeAddr bytes[0], bytes.len.cint, SQLITE_TRANSIENT) + else: + let errMsg = s.error + sqlite3_result_error(ctx, errMsg, -1) + + except Exception as e: + raiseAssert(e.msg) + +proc registerCustomScalarFunction*(db: SqStoreRef, name: string, fun: CustomFunction): KvResult[void] = + ## Register custom function inside sqlite engine. Registered function can + ## be used in further queries by its name. Function should be side-effect + ## free and depends only on provided arguments. + ## Name of the function should be valid utf8 string. + + # Using SQLITE_DETERMINISTIC flag to inform sqlite that provided function + # won't have any side effect this may enable additional optimisations. + let deterministicUtf8Func = cint(SQLITE_UTF8 or SQLITE_DETERMINISTIC) + + let res = sqlite3_create_function( + db.env, + name, + cint(2), + deterministicUtf8Func, + cast[pointer](fun), + customScalarBlobFunction, + nil, + nil + ) + + if res != SQLITE_OK: + return err($sqlite3_errstr(res)) + else: + return ok() + when defined(metrics): import locks, tables, times, chronicles, metrics diff --git a/vendor/nim-eth/eth/eip1559.nim b/vendor/nim-eth/eth/eip1559.nim new file mode 100644 index 000000000..45b112d7d --- /dev/null +++ b/vendor/nim-eth/eth/eip1559.nim @@ -0,0 +1,47 @@ +import + common/eth_types + +const + EIP1559_BASE_FEE_CHANGE_DENOMINATOR* = ##\ + ## Bounds the amount the base fee can change between blocks. + 8 + + EIP1559_ELASTICITY_MULTIPLIER* = ##\ + ## Bounds the maximum gas limit an EIP-1559 block may have. + 2 + + EIP1559_INITIAL_BASE_FEE* = ##\ + ## Initial base fee for Eip1559 blocks. + 1000000000.u256 + +proc calcEip1599BaseFee*(parentGasLimit, parentGasUsed: GasInt; + parentBaseFee: UInt256): UInt256 = + ## calculates the basefee of the header. + + let parentGasTarget = parentGasLimit div EIP1559_ELASTICITY_MULTIPLIER + + # If the parent gasUsed is the same as the target, the baseFee remains + # unchanged. + if parentGasUsed == parentGasTarget: + return parentBaseFee + + let parentGasDenom = parentGasTarget.u256 * + EIP1559_BASE_FEE_CHANGE_DENOMINATOR.u256 + + if parentGasTarget < parentGasUsed: + # If the parent block used more gas than its target, the baseFee should + # increase. + let + gasUsedDelta = (parentGasUsed - parentGasTarget).u256 + baseFeeDelta = (parentBaseFee * gasUsedDelta) div parentGasDenom + + return parentBaseFee + max(baseFeeDelta, 1.u256) + + else: + # Otherwise if the parent block used less gas than its target, the + # baseFee should decrease. + let + gasUsedDelta = (parentGasTarget - parentGasUsed).u256 + baseFeeDelta = (parentBaseFee * gasUsedDelta) div parentGasDenom + + return max(parentBaseFee - baseFeeDelta, 0.u256) diff --git a/vendor/nim-eth/eth/keys.nim b/vendor/nim-eth/eth/keys.nim index 0c89b4b81..7699466bd 100644 --- a/vendor/nim-eth/eth/keys.nim +++ b/vendor/nim-eth/eth/keys.nim @@ -16,12 +16,13 @@ import std/strformat, - secp256k1, bearssl, stew/[byteutils, objects, results], - nimcrypto/[hash, keccak] + secp256k1, bearssl/hash as bhash, bearssl/rand, + stew/[byteutils, objects, results], + ./common/eth_hash from nimcrypto/utils import burnMem -export secp256k1, results, bearssl +export secp256k1, results, rand const KeyLength* = SkEcdhRawSecretSize - 1 @@ -51,24 +52,15 @@ type template pubkey*(v: KeyPair): PublicKey = PublicKey(SkKeyPair(v).pubkey) template seckey*(v: KeyPair): PrivateKey = PrivateKey(SkKeyPair(v).seckey) -proc newRng*(): ref BrHmacDrbgContext = +proc newRng*(): ref HmacDrbgContext = # You should only create one instance of the RNG per application / library # Ref is used so that it can be shared between components - # TODO consider moving to bearssl - var seeder = brPrngSeederSystem(nil) - if seeder == nil: - return nil + HmacDrbgContext.new() - var rng = (ref BrHmacDrbgContext)() - brHmacDrbgInit(addr rng[], addr sha256Vtable, nil, 0) - if seeder(addr rng.vtable) == 0: - return nil - rng - -proc random*(T: type PrivateKey, rng: var BrHmacDrbgContext): T = +proc random*(T: type PrivateKey, rng: var HmacDrbgContext): T = let rngPtr = unsafeAddr rng # doesn't escape proc callRng(data: var openArray[byte]) = - brHmacDrbgGenerate(rngPtr[], data) + generate(rngPtr[], data) T(SkSecretKey.random(callRng)) @@ -106,7 +98,7 @@ func toRaw*(pubkey: PublicKey): array[RawPublicKeySize, byte] = func toRawCompressed*(pubkey: PublicKey): array[33, byte] {.borrow.} -proc random*(T: type KeyPair, rng: var BrHmacDrbgContext): T = +proc random*(T: type KeyPair, rng: var HmacDrbgContext): T = let seckey = SkSecretKey(PrivateKey.random(rng)) KeyPair(SkKeyPair( seckey: seckey, @@ -132,16 +124,16 @@ func toRaw*(sig: SignatureNR): array[RawSignatureNRSize, byte] {.borrow.} func toAddress*(pubkey: PublicKey, with0x = true): string = ## Convert public key to hexadecimal string address. - var hash = keccak256.digest(pubkey.toRaw()) + var hash = keccakHash(pubkey.toRaw()) result = if with0x: "0x" else: "" result.add(toHex(toOpenArray(hash.data, 12, len(hash.data) - 1))) func toChecksumAddress*(pubkey: PublicKey, with0x = true): string = ## Convert public key to checksumable mixed-case address (EIP-55). result = if with0x: "0x" else: "" - var hash1 = keccak256.digest(pubkey.toRaw()) + var hash1 = keccakHash(pubkey.toRaw()) var hhash1 = toHex(toOpenArray(hash1.data, 12, len(hash1.data) - 1)) - var hash2 = keccak256.digest(hhash1) + var hash2 = keccakHash(hhash1) var hhash2 = toHex(hash2.data) for i in 0..= '0' and hhash2[i] <= '7': @@ -169,7 +161,7 @@ func validateChecksumAddress*(a: string): bool = address &= chr(ord(ch) - ord('A') + ord('a')) else: return false - var hash = keccak256.digest(address) + var hash = keccakHash(address) var hexhash = toHex(hash.data) for i in 0..= '0' and hexhash[i] <= '7': @@ -184,7 +176,7 @@ func validateChecksumAddress*(a: string): bool = func toCanonicalAddress*(pubkey: PublicKey): array[20, byte] = ## Convert public key to canonical address. - var hash = keccak256.digest(pubkey.toRaw()) + var hash = keccakHash(pubkey.toRaw()) copyMem(addr result[0], addr hash.data[12], 20) func `$`*(pubkey: PublicKey): string = @@ -214,28 +206,28 @@ func sign*(seckey: PrivateKey, msg: SkMessage): Signature = Signature(signRecoverable(SkSecretKey(seckey), msg)) func sign*(seckey: PrivateKey, msg: openArray[byte]): Signature = - let hash = keccak256.digest(msg) + let hash = keccakHash(msg) sign(seckey, SkMessage(hash.data)) func signNR*(seckey: PrivateKey, msg: SkMessage): SignatureNR = SignatureNR(sign(SkSecretKey(seckey), msg)) func signNR*(seckey: PrivateKey, msg: openArray[byte]): SignatureNR = - let hash = keccak256.digest(msg) + let hash = keccakHash(msg) signNR(seckey, SkMessage(hash.data)) func recover*(sig: Signature, msg: SkMessage): SkResult[PublicKey] = recover(SkRecoverableSignature(sig), msg).mapConvert(PublicKey) func recover*(sig: Signature, msg: openArray[byte]): SkResult[PublicKey] = - let hash = keccak256.digest(msg) + let hash = keccakHash(msg) recover(sig, SkMessage(hash.data)) func verify*(sig: SignatureNR, msg: SkMessage, key: PublicKey): bool = verify(SkSignature(sig), msg, SkPublicKey(key)) func verify*(sig: SignatureNR, msg: openArray[byte], key: PublicKey): bool = - let hash = keccak256.digest(msg) + let hash = keccakHash(msg) verify(sig, SkMessage(hash.data), key) func ecdhRaw*(seckey: PrivateKey, pubkey: PublicKey): SharedSecret = diff --git a/vendor/nim-eth/eth/net/nat.nim b/vendor/nim-eth/eth/net/nat.nim index 462b4ef05..8901af819 100644 --- a/vendor/nim-eth/eth/net/nat.nim +++ b/vendor/nim-eth/eth/net/nat.nim @@ -6,12 +6,16 @@ # This file may not be copied, modified, or distributed except according to # those terms. +{.push raises: [Defect].} + import std/[options, os, strutils, times], stew/results, nat_traversal/[miniupnpc, natpmp], - chronicles, json_serialization/std/net, chronos, + chronicles, json_serialization/std/net, chronos, confutils, ../common/utils, ./utils as netutils +export ConfigurationError + type NatStrategy* = enum NatAny @@ -19,6 +23,13 @@ type NatPmp NatNone + PrefSrcStatus = enum + NoRoutingInfo + PrefSrcIsPublic + PrefSrcIsPrivate + BindAddressIsPublic + BindAddressIsPrivate + const UPNP_TIMEOUT = 200 # ms PORT_MAPPING_INTERVAL = 20 * 60 # seconds @@ -98,6 +109,42 @@ proc getExternalIP*(natStrategy: NatStrategy, quiet = false): Option[IpAddress] error "parseIpAddress() exception", err = e.msg return +# This queries the routing table to get the "preferred source" attribute and +# checks if it's a public IP. If so, then it's our public IP. +# +# Further more, we check if the bind address (user provided, or a "0.0.0.0" +# default) is a public IP. That's a long shot, because code paths involving a +# user-provided bind address are not supposed to get here. +proc getRoutePrefSrc(bindIp: ValidIpAddress): (Option[ValidIpAddress], PrefSrcStatus) = + let bindAddress = initTAddress(bindIp, Port(0)) + + if bindAddress.isAnyLocal(): + let ip = getRouteIpv4() + if ip.isErr(): + # No route was found, log error and continue without IP. + error "No routable IP address found, check your network connection", error = ip.error + return (none(ValidIpAddress), NoRoutingInfo) + elif ip.get().isPublic(): + return (some(ip.get()), PrefSrcIsPublic) + else: + return (none(ValidIpAddress), PrefSrcIsPrivate) + elif bindAddress.isPublic(): + return (some(ValidIpAddress.init(bindIp)), BindAddressIsPublic) + else: + return (none(ValidIpAddress), BindAddressIsPrivate) + +# Try to detect a public IP assigned to this host, before trying NAT traversal. +proc getPublicRoutePrefSrcOrExternalIP*(natStrategy: NatStrategy, bindIp: ValidIpAddress, quiet = true): Option[ValidIpAddress] = + let (prefSrcIp, prefSrcStatus) = getRoutePrefSrc(bindIp) + + case prefSrcStatus: + of NoRoutingInfo, PrefSrcIsPublic, BindAddressIsPublic: + return prefSrcIp + of PrefSrcIsPrivate, BindAddressIsPrivate: + let extIp = getExternalIP(natStrategy, quiet) + if extIp.isSome: + return some(ValidIpAddress.init(extIp.get)) + proc doPortMapping(tcpPort, udpPort: Port, description: string): Option[(Port, Port)] {.gcsafe.} = var extTcpPort: Port @@ -155,7 +202,7 @@ var natThread: Thread[PortMappingArgs] natCloseChan: Channel[bool] -proc repeatPortMapping(args: PortMappingArgs) {.thread.} = +proc repeatPortMapping(args: PortMappingArgs) {.thread, raises: [Defect, ValueError].} = ignoreSignalsInThread() let (tcpPort, udpPort, description) = args @@ -173,7 +220,8 @@ proc repeatPortMapping(args: PortMappingArgs) {.thread.} = while true: # we're being silly here with this channel polling because we can't # select on Nim channels like on Go ones - let (dataAvailable, _) = natCloseChan.tryRecv() + let (dataAvailable, _) = try: natCloseChan.tryRecv() + except Exception: (false, false) if dataAvailable: return else: @@ -186,9 +234,12 @@ proc repeatPortMapping(args: PortMappingArgs) {.thread.} = proc stopNatThread() {.noconv.} = # stop the thread - natCloseChan.send(true) - natThread.joinThread() - natCloseChan.close() + try: + natCloseChan.send(true) + natThread.joinThread() + natCloseChan.close() + except Exception as exc: + warn "Failed to stop NAT port mapping renewal thread", exc = exc.msg # delete our port mappings @@ -233,9 +284,12 @@ proc redirectPorts*(tcpPort, udpPort: Port, description: string): Option[(Port, # NAT-PMP lease expires or the router is rebooted and forgets all about # these mappings. natCloseChan.open() - natThread.createThread(repeatPortMapping, (externalTcpPort, externalUdpPort, description)) - # atexit() in disguise - addQuitProc(stopNatThread) + try: + natThread.createThread(repeatPortMapping, (externalTcpPort, externalUdpPort, description)) + # atexit() in disguise + addQuitProc(stopNatThread) + except Exception as exc: + warn "Failed to create NAT port mapping renewal thread", exc = exc.msg proc setupNat*(natStrategy: NatStrategy, tcpPort, udpPort: Port, clientId: string): @@ -267,7 +321,7 @@ type of true: extIp*: ValidIpAddress of false: nat*: NatStrategy -func parseCmdArg*(T: type NatConfig, p: TaintedString): T = +func parseCmdArg*(T: type NatConfig, p: TaintedString): T {.raises: [Defect, ConfigurationError].} = case p.toLowerAscii: of "any": NatConfig(hasExtIp: false, nat: NatAny) @@ -308,46 +362,24 @@ proc setupAddress*(natConfig: NatConfig, bindIp: ValidIpAddress, case natConfig.nat: of NatAny: - let bindAddress = initTAddress(bindIp, Port(0)) - if bindAddress.isAnyLocal(): - let ip = getRouteIpv4() - if ip.isErr(): - # No route was found, log error and continue without IP. - error "No routable IP address found, check your network connection", - error = ip.error - return (none(ValidIpAddress), some(tcpPort), some(udpPort)) - elif ip.get().isPublic(): - return (some(ip.get()), some(tcpPort), some(udpPort)) - else: - # Best route IP is not public, might be an internal network and the - # node is either behind a gateway with NAT or for example a container - # or VM bridge (or both). Lets try UPnP and NAT-PMP for the case where - # the node is behind a gateway with UPnP or NAT-PMP support. + let (prefSrcIp, prefSrcStatus) = getRoutePrefSrc(bindIp) + + case prefSrcStatus: + of NoRoutingInfo, PrefSrcIsPublic, BindAddressIsPublic: + return (prefSrcIp, some(tcpPort), some(udpPort)) + of PrefSrcIsPrivate, BindAddressIsPrivate: return setupNat(natConfig.nat, tcpPort, udpPort, clientId) - elif bindAddress.isPublic(): - # When a specific public interface is provided, use that one. - return (some(ValidIpAddress.init(bindIp)), some(tcpPort), some(udpPort)) - else: - return setupNat(natConfig.nat, tcpPort, udpPort, clientId) of NatNone: - let bindAddress = initTAddress(bindIp, Port(0)) - if bindAddress.isAnyLocal(): - let ip = getRouteIpv4() - if ip.isErr(): - # No route was found, log error and continue without IP. - error "No routable IP address found, check your network connection", - error = ip.error - return (none(ValidIpAddress), some(tcpPort), some(udpPort)) - elif ip.get().isPublic(): - return (some(ip.get()), some(tcpPort), some(udpPort)) - else: + let (prefSrcIp, prefSrcStatus) = getRoutePrefSrc(bindIp) + + case prefSrcStatus: + of NoRoutingInfo, PrefSrcIsPublic, BindAddressIsPublic: + return (prefSrcIp, some(tcpPort), some(udpPort)) + of PrefSrcIsPrivate: error "No public IP address found. Should not use --nat:none option" return (none(ValidIpAddress), some(tcpPort), some(udpPort)) - elif bindAddress.isPublic(): - # When a specific public interface is provided, use that one. - return (some(ValidIpAddress.init(bindIp)), some(tcpPort), some(udpPort)) - else: - error "Bind IP is not a public IP address. Should not use --nat:none option" - return (none(ValidIpAddress), some(tcpPort), some(udpPort)) + of BindAddressIsPrivate: + error "Bind IP is not a public IP address. Should not use --nat:none option" + return (none(ValidIpAddress), some(tcpPort), some(udpPort)) of NatUpnp, NatPmp: return setupNat(natConfig.nat, tcpPort, udpPort, clientId) diff --git a/vendor/nim-eth/eth/p2p.nim b/vendor/nim-eth/eth/p2p.nim index a945451b6..f5982e7ab 100644 --- a/vendor/nim-eth/eth/p2p.nim +++ b/vendor/nim-eth/eth/p2p.nim @@ -9,8 +9,8 @@ import std/[tables, algorithm, random], - bearssl, chronos, chronos/timer, chronicles, - ./keys, ./common/eth_types, ./p2p/private/p2p_types, + chronos, chronos/timer, chronicles, + ./keys, ./common/chaindb, ./p2p/private/p2p_types, ./p2p/[kademlia, discovery, enode, peer_pool, rlpx] export @@ -29,15 +29,20 @@ proc addCapability*(node: var EthereumNode, p: ProtocolInfo) = template addCapability*(node: var EthereumNode, Protocol: type) = addCapability(node, Protocol.protocolInfo) -proc newEthereumNode*(keys: KeyPair, - address: Address, - networkId: NetworkId, - chain: AbstractChainDB, - clientId = "nim-eth-p2p/0.2.0", # TODO: read this value from nimble somehow - addAllCapabilities = true, - useCompression: bool = false, - minPeers = 10, - rng = newRng()): EthereumNode = +proc newEthereumNode*( + keys: KeyPair, + address: Address, + networkId: NetworkId, + chain: AbstractChainDB, + clientId = "nim-eth-p2p/0.2.0", # TODO: read this value from nimble somehow + addAllCapabilities = true, + useCompression: bool = false, + minPeers = 10, + bootstrapNodes: seq[ENode] = @[], + bindUdpPort: Port, + bindTcpPort: Port, + bindIp = IPv4_any(), + rng = newRng()): EthereumNode = if rng == nil: # newRng could fail raise (ref Defect)(msg: "Cannot initialize RNG") @@ -50,6 +55,12 @@ proc newEthereumNode*(keys: KeyPair, result.capabilities.newSeq 0 result.address = address result.connectionState = ConnectionState.None + result.bindIp = bindIp + result.bindPort = bindTcpPort + + result.discovery = newDiscoveryProtocol( + keys.seckey, address, bootstrapNodes, bindUdpPort, bindIp, rng) + result.rng = rng when useSnappy: @@ -58,10 +69,10 @@ proc newEthereumNode*(keys: KeyPair, result.protocolStates.newSeq allProtocols.len - result.peerPool = newPeerPool(result, networkId, - keys, nil, - clientId, address.tcpPort, - minPeers = minPeers) + result.peerPool = newPeerPool( + result, networkId, keys, nil, clientId, minPeers = minPeers) + + result.peerPool.discovery = result.discovery if addAllCapabilities: for p in allProtocols: @@ -81,8 +92,8 @@ proc listeningAddress*(node: EthereumNode): ENode = node.toENode() proc startListening*(node: EthereumNode) {.raises: [CatchableError, Defect].} = - # TODO allow binding to specific IP / IPv6 / etc - let ta = initTAddress(IPv4_any(), node.address.tcpPort) + # TODO: allow binding to both IPv4 & IPv6 + let ta = initTAddress(node.bindIp, node.bindPort) if node.listeningServer == nil: node.listeningServer = createStreamServer(ta, processIncoming, {ReuseAddr}, @@ -90,18 +101,12 @@ proc startListening*(node: EthereumNode) {.raises: [CatchableError, Defect].} = node.listeningServer.start() info "RLPx listener up", self = node.listeningAddress -proc connectToNetwork*(node: EthereumNode, - bootstrapNodes: seq[ENode], - startListening = true, - enableDiscovery = true, - waitForPeers = true) {.async.} = +proc connectToNetwork*( + node: EthereumNode, startListening = true, + enableDiscovery = true, waitForPeers = true) {.async.} = doAssert node.connectionState == ConnectionState.None node.connectionState = Connecting - node.discovery = newDiscoveryProtocol(node.keys.seckey, - node.address, - bootstrapNodes) - node.peerPool.discovery = node.discovery if startListening: p2p.startListening(node) @@ -171,3 +176,21 @@ proc getPeer*(node: EthereumNode, peerId: NodeId, Protocol: type): Option[Peer] for peer in node.peers(Protocol): if peer.remote.id == peerId: return some(peer) + +proc connectToNode*(node: EthereumNode, n: Node) {.async.} = + await node.peerPool.connectToNode(n) + +proc connectToNode*(node: EthereumNode, n: ENode) {.async.} = + await node.peerPool.connectToNode(n) + +func numPeers*(node: EthereumNode): int = + node.peerPool.numPeers + +func hasPeer*(node: EthereumNode, n: ENode): bool = + n in node.peerPool + +func hasPeer*(node: EthereumNode, n: Node): bool = + n in node.peerPool + +func hasPeer*(node: EthereumNode, n: Peer): bool = + n in node.peerPool diff --git a/vendor/nim-eth/eth/p2p/auth.nim b/vendor/nim-eth/eth/p2p/auth.nim index a76b3b14e..89a9fd14a 100644 --- a/vendor/nim-eth/eth/p2p/auth.nim +++ b/vendor/nim-eth/eth/p2p/auth.nim @@ -13,8 +13,8 @@ {.push raises: [Defect].} import - nimcrypto/[rijndael, keccak, utils], bearssl, - stew/[byteutils, endians2, objects, results], + nimcrypto/[rijndael, keccak, utils], + stew/[arrayops, byteutils, endians2, objects, results], ".."/[keys, rlp], ./ecies @@ -88,19 +88,14 @@ type template toa(a, b, c: untyped): untyped = toOpenArray((a), (b), (b) + (c) - 1) -proc `xor`[N: static int](a, b: array[N, byte]): array[N, byte] = - for i in 0 ..< len(a): - result[i] = a[i] xor b[i] - proc mapErrTo[T, E](r: Result[T, E], v: static AuthError): AuthResult[T] = r.mapErr(proc (e: E): AuthError = v) -proc tryInit*( - T: type Handshake, rng: var BrHmacDrbgContext, host: KeyPair, +proc init*( + T: type Handshake, rng: var HmacDrbgContext, host: KeyPair, flags: set[HandshakeFlag] = {Initiator}, - version: uint8 = SupportedRlpxVersion): AuthResult[T] = + version: uint8 = SupportedRlpxVersion): T = ## Create new `Handshake` object. - var initiatorNonce: Nonce responderNonce: Nonce @@ -109,12 +104,12 @@ proc tryInit*( if Initiator in flags: expectedLength = AckMessageV4Length - brHmacDrbgGenerate(rng, initiatorNonce) + rng.generate(initiatorNonce) else: expectedLength = AuthMessageV4Length - brHmacDrbgGenerate(rng, responderNonce) + rng.generate(responderNonce) - return ok(T( + return T( version: version, flags: flags, host: host, @@ -122,10 +117,10 @@ proc tryInit*( initiatorNonce: initiatorNonce, responderNonce: responderNonce, expectedLength: expectedLength - )) + ) proc authMessagePreEIP8(h: var Handshake, - rng: var BrHmacDrbgContext, + rng: var HmacDrbgContext, pubkey: PublicKey, output: var openArray[byte], outlen: var int, @@ -164,7 +159,7 @@ proc authMessagePreEIP8(h: var Handshake, ok() proc authMessageEIP8(h: var Handshake, - rng: var BrHmacDrbgContext, + rng: var HmacDrbgContext, pubkey: PublicKey, output: var openArray[byte], outlen: var int, @@ -173,7 +168,6 @@ proc authMessageEIP8(h: var Handshake, ## Create EIP8 authentication message. var buffer: array[PlainAuthMessageMaxEIP8, byte] - padsize: array[1, byte] doAssert(EIP8 in h.flags) outlen = 0 @@ -193,29 +187,33 @@ proc authMessageEIP8(h: var Handshake, let pencsize = eciesEncryptedLength(len(payload)) - while true: - brHmacDrbgGenerate(rng, padsize) - if int(padsize[0]) > (AuthMessageV4Length - (pencsize + 2)): - break + var padsize = int(rng.generate(byte)) # aka rand(max) + while padsize <= (AuthMessageV4Length - (pencsize + 2)): + padsize = int(rng.generate(byte)) + # It is possible to make packet size constant by uncommenting this line # padsize = 24 - let wosize = pencsize + int(padsize[0]) - let fullsize = wosize + 2 - brHmacDrbgGenerate( - rng, toa(buffer, PlainAuthMessageEIP8Length, int(padsize[0]))) + let + wosize = pencsize + padsize + fullsize = wosize + 2 + + rng.generate(toa(buffer, PlainAuthMessageEIP8Length, padsize)) + if encrypt: - copyMem(addr buffer[0], addr payload[0], len(payload)) if len(output) < fullsize: return err(BufferOverrun) + + copyMem(addr buffer[0], addr payload[0], len(payload)) + let wosizeBE = uint16(wosize).toBytesBE() output[0..<2] = wosizeBE - if eciesEncrypt(rng, toa(buffer, 0, len(payload) + int(padsize[0])), + if eciesEncrypt(rng, toa(buffer, 0, len(payload) + padsize), toa(output, 2, wosize), pubkey, toa(output, 0, 2)).isErr: return err(EciesError) outlen = fullsize else: - let plainsize = len(payload) + int(padsize[0]) + let plainsize = len(payload) + padsize if len(output) < plainsize: return err(BufferOverrun) copyMem(addr output[0], addr buffer[0], plainsize) @@ -224,7 +222,7 @@ proc authMessageEIP8(h: var Handshake, ok() proc ackMessagePreEIP8(h: var Handshake, - rng: var BrHmacDrbgContext, + rng: var HmacDrbgContext, output: var openArray[byte], outlen: var int, flag: byte = 0, @@ -251,7 +249,7 @@ proc ackMessagePreEIP8(h: var Handshake, ok() proc ackMessageEIP8(h: var Handshake, - rng: var BrHmacDrbgContext, + rng: var HmacDrbgContext, output: var openArray[byte], outlen: var int, flag: byte = 0, @@ -268,7 +266,7 @@ proc ackMessageEIP8(h: var Handshake, outlen = 0 let pencsize = eciesEncryptedLength(len(payload)) while true: - brHmacDrbgGenerate(rng, padsize) + generate(rng, padsize) if int(padsize[0]) > (AckMessageV4Length - (pencsize + 2)): break # It is possible to make packet size constant by uncommenting this line @@ -276,8 +274,7 @@ proc ackMessageEIP8(h: var Handshake, let wosize = pencsize + int(padsize[0]) let fullsize = wosize + 2 if int(padsize[0]) > 0: - brHmacDrbgGenerate( - rng, toa(buffer, PlainAckMessageEIP8Length, int(padsize[0]))) + rng.generate(toa(buffer, PlainAckMessageEIP8Length, int(padsize[0]))) copyMem(addr buffer[0], addr payload[0], len(payload)) if encrypt: @@ -312,7 +309,7 @@ template ackSize*(h: Handshake, encrypt: bool = true): int = else: if encrypt: (AckMessageV4Length) else: (PlainAckMessageV4Length) -proc authMessage*(h: var Handshake, rng: var BrHmacDrbgContext, +proc authMessage*(h: var Handshake, rng: var HmacDrbgContext, pubkey: PublicKey, output: var openArray[byte], outlen: var int, flag: byte = 0, @@ -324,7 +321,7 @@ proc authMessage*(h: var Handshake, rng: var BrHmacDrbgContext, else: authMessagePreEIP8(h, rng, pubkey, output, outlen, flag, encrypt) -proc ackMessage*(h: var Handshake, rng: var BrHmacDrbgContext, +proc ackMessage*(h: var Handshake, rng: var HmacDrbgContext, output: var openArray[byte], outlen: var int, flag: byte = 0, encrypt: bool = true): AuthResult[void] = diff --git a/vendor/nim-eth/eth/p2p/bootnodes.nim b/vendor/nim-eth/eth/p2p/bootnodes.nim index e8912a1d8..27b661d32 100644 --- a/vendor/nim-eth/eth/p2p/bootnodes.nim +++ b/vendor/nim-eth/eth/p2p/bootnodes.nim @@ -9,15 +9,13 @@ const "enode://5d6d7cd20d6da4bb83a1d28cadb5d409b64edf314c0335df658c1a54e32c7c4a7ab7823d57c39b6a757556e68ff1df17c748b698544a55cb488b52479a92b60f@104.42.217.25:30303", # bootnode-azure-westus-001 "enode://2b252ab6a1d0f971d9722cb839a42cb81db019ba44c08754628ab4a823487071b5695317c8ccd085219c3a03af063495b2f1da8d18218da2d6a82981b45e6ffc@65.108.70.101:30303", # bootnode-hetzner-hel "enode://4aeb4ab6c14b23e2c4cfdce879c04b0748a20d8e9b59e25ded2a08143e265c6c25936e74cbc8e641e3312ca288673d91f2f93f8e277de3cfa444ecdaaf982052@157.90.35.166:30303", # bootnode-hetzner-fsn - # Ethereum Foundation C++ Bootnodes - "enode://979b7fa28feeb35a4741660a16076f1943202cb72b6af70d327f053e248bab9ba81760f39d0701ef1d8f89cc1fbd2cacba0710a12cd5314d5e0c9021aa3637f9@5.1.83.226:30303" # DE ] RopstenBootnodes* = [ "enode://30b7ab30a01c124a6cceca36863ece12c4f5fa68e3ba9b0b51407ccc002eeed3b3102d20a88f1c1d3c3154e2449317b8ef95090e77b312d5cc39354f86d5d606@52.176.7.10:30303", # US-Azure geth "enode://865a63255b3bb68023b6bffd5095118fcc13e79dcf014fe4e47e065c350c7cc72af2e53eff895f11ba1bbb6a2b33271c1116ee870f266618eadfc2e78aa7349c@52.176.100.77:30303", # US-Azure parity "enode://6332792c4a00e3e4ee0926ed89e0d27ef985424d97b6a45bf0f23e51f0dcb5e66b875777506458aea7af6f9e4ffb69f43f3778ee73c81ed9d34c51c4b16b0b0f@52.232.243.152:30303", # Parity - "enode://94c15d1b9e2fe7ce56e458b9a3b672ef11894ddedd0c6f247e0f1d3487f52b66208fb4aeb8179fce6e3a749ea93ed147c37976d67af557508d199d9594c35f09@192.81.208.223:30303" # @gpip + "enode://94c15d1b9e2fe7ce56e458b9a3b672ef11894ddedd0c6f247e0f1d3487f52b66208fb4aeb8179fce6e3a749ea93ed147c37976d67af557508d199d9594c35f09@192.81.208.223:30303", # @gpip ] RinkebyBootnodes* = [ @@ -27,20 +25,21 @@ const ] GoerliBootnodes* = [ + # Upstream bootnodes "enode://011f758e6552d105183b1761c5e2dea0111bc20fd5f6422bc7f91e0fabbec9a6595caf6239b37feb773dddd3f87240d99d859431891e4a642cf2a0a9e6cbb98a@51.141.78.53:30303", "enode://176b9417f511d05b6b2cf3e34b756cf0a7096b3094572a8f6ef4cdcb9d1f9d00683bf0f83347eebdf3b81c3521c2332086d9592802230bf528eaf606a1d9677b@13.93.54.137:30303", "enode://46add44b9f13965f7b9875ac6b85f016f341012d84f975377573800a863526f4da19ae2c620ec73d11591fa9510e992ecc03ad0751f53cc02f7c7ed6d55c7291@94.237.54.114:30313", - "enode://c1f8b7c2ac4453271fa07d8e9ecf9a2e8285aa0bd0c07df0131f47153306b0736fd3db8924e7a9bf0bed6b1d8d4f87362a71b033dc7c64547728d953e43e59b2@52.64.155.147:30303", - "enode://f4a9c6ee28586009fb5a96c8af13a58ed6d8315a9eee4772212c1d4d9cebe5a8b8a78ea4434f318726317d04a3f531a1ef0420cf9752605a562cfe858c46e263@213.186.16.82:30303", + "enode://b5948a2d3e9d486c4d75bf32713221c2bd6cf86463302339299bd227dc2e276cd5a1c7ca4f43a0e9122fe9af884efed563bd2a1fd28661f3b5f5ad7bf1de5949@18.218.250.66:30303", # Ethereum Foundation bootnode - "enode://a61215641fb8714a373c80edbfa0ea8878243193f57c96eeb44d0bc019ef295abd4e044fd619bfc4c59731a73fb79afe84e9ab6da0c743ceb479cbb6d263fa91@3.11.147.67:30303" + "enode://a61215641fb8714a373c80edbfa0ea8878243193f57c96eeb44d0bc019ef295abd4e044fd619bfc4c59731a73fb79afe84e9ab6da0c743ceb479cbb6d263fa91@3.11.147.67:30303", + # Goerli Initiative bootnodes + "enode://d4f764a48ec2a8ecf883735776fdefe0a3949eb0ca476bd7bc8d0954a9defe8fea15ae5da7d40b5d2d59ce9524a99daedadf6da6283fca492cc80b53689fb3b3@46.4.99.122:32109", + "enode://d2b720352e8216c9efc470091aa91ddafc53e222b32780f505c817ceef69e01d5b0b0797b69db254c586f493872352f5a022b4d8479a00fc92ec55f9ad46a27e@88.99.70.182:30303", ] - DiscoveryV5Bootnodes* = [ - "enode://06051a5573c81934c9554ef2898eb13b33a34b94cf36b202b69fde139ca17a85051979867720d4bdae4323d4943ddf9aeeb6643633aa656e0be843659795007a@35.177.226.168:30303", - "enode://0cc5f5ffb5d9098c8b8c62325f3797f56509bff942704687b6530992ac706e2cb946b90a34f1f19548cd3c7baccbcaea354531e5983c7d1bc0dee16ce4b6440b@40.118.3.223:30304", - "enode://1c7a64d76c0334b0418c004af2f67c50e36a3be60b5e4790bdac0439d21603469a85fad36f2473c9a80eb043ae60936df905fa28f1ff614c3e5dc34f15dcd2dc@40.118.3.223:30306", - "enode://85c85d7143ae8bb96924f2b54f1b3e70d8c4d367af305325d30a61385a432f247d2c75c45c6b4a60335060d072d7f5b35dd1d4c45f76941f62a4f83b6e75daaf@40.118.3.223:30307" + SepoliaBootnodes* = [ + "enode://9246d00bc8fd1742e5ad2428b80fc4dc45d786283e05ef6edbd9002cbc335d40998444732fbe921cb88e1d2c73d1b1de53bae6a2237996e9bfe14f871baf7066@18.168.182.86:30303", + "enode://ec66ddcf1a974950bd4c782789a7e04f8aa7110a72569b6e65fcd51e937e74eed303b1ea734e4d19cfaec9fbff9b6ee65bf31dcb50ba79acce9dd63a6aca61c7@52.14.151.177:30303", ] KovanBootnodes* = [ @@ -50,27 +49,3 @@ const "enode://7e2e7f00784f516939f94e22bdc6cf96153603ca2b5df1c7cc0f90a38e7a2f218ffb1c05b156835e8b49086d11fdd1b3e2965be16baa55204167aa9bf536a4d9@52.243.47.56:30303", "enode://0518a3d35d4a7b3e8c433e7ffd2355d84a1304ceb5ef349787b556197f0c87fad09daed760635b97d52179d645d3e6d16a37d2cc0a9945c2ddf585684beb39ac@40.68.248.100:30303" ] - - # curl -s https://fleets.status.im | jq '"\"" + .fleets["eth.prod"].boot[] + "\","' -r - StatusBootNodes* = [ - "enode://6e6554fb3034b211398fcd0f0082cbb6bd13619e1a7e76ba66e1809aaa0c5f1ac53c9ae79cf2fd4a7bacb10d12010899b370c75fed19b991d9c0cdd02891abad@47.75.99.169:443", - "enode://436cc6f674928fdc9a9f7990f2944002b685d1c37f025c1be425185b5b1f0900feaf1ccc2a6130268f9901be4a7d252f37302c8335a2c1a62736e9232691cc3a@178.128.138.128:443", - "enode://32ff6d88760b0947a3dee54ceff4d8d7f0b4c023c6dad34568615fcae89e26cc2753f28f12485a4116c977be937a72665116596265aa0736b53d46b27446296a@34.70.75.208:443", - "enode://23d0740b11919358625d79d4cac7d50a34d79e9c69e16831c5c70573757a1f5d7d884510bc595d7ee4da3c1508adf87bbc9e9260d804ef03f8c1e37f2fb2fc69@47.52.106.107:443", - "enode://5395aab7833f1ecb671b59bf0521cf20224fe8162fc3d2675de4ee4d5636a75ec32d13268fc184df8d1ddfa803943906882da62a4df42d4fccf6d17808156a87@178.128.140.188:443", - "enode://5405c509df683c962e7c9470b251bb679dd6978f82d5b469f1f6c64d11d50fbd5dd9f7801c6ad51f3b20a5f6c7ffe248cc9ab223f8bcbaeaf14bb1c0ef295fd0@35.223.215.156:443", - ] - - # curl -s https://fleets.status.im | jq '"\"" + .fleets["eth.staging"].boot[] + "\","' -r - StatusBootNodesStaging* = [ - "enode://630b0342ca4e9552f50714b6c8e28d6955bc0fd14e7950f93bc3b2b8cc8c1f3b6d103df66f51a13d773b5db0f130661fb5c7b8fa21c48890c64c79b41a56a490@47.91.229.44:443", - "enode://f79fb3919f72ca560ad0434dcc387abfe41e0666201ebdada8ede0462454a13deb05cda15f287d2c4bd85da81f0eb25d0a486bbbc8df427b971ac51533bd00fe@174.138.107.239:443", - "enode://10a78c17929a7019ef4aa2249d7302f76ae8a06f40b2dc88b7b31ebff4a623fbb44b4a627acba296c1ced3775d91fbe18463c15097a6a36fdb2c804ff3fc5b35@35.238.97.234:443", - ] - - # curl -s https://fleets.status.im | jq '"\"" + .fleets["eth.test"].boot[] + "\","' -r - StatusBootNodesTest* = [ - "enode://daae2e72820e86e942fa2a8aa7d6e9954d4043a753483d8bd338e16be82cf962392d5c0e1ae57c3d793c3d3dddd8fd58339262e4234dc966f953cd73b535f5fa@47.52.188.149:443", - "enode://9e0988575eb7717c25dea72fd11c7b37767dc09c1a7686f7c2ec577d308d24b377ceb675de4317474a1a870e47882732967f4fa785b02ba95d669b31d464dec0@206.189.243.164:443", - "enode://c1e5018887c863d64e431b69bf617561087825430e4401733f5ba77c70db14236df381fefb0ebe1ac42294b9e261bbe233dbdb83e32c586c66ae26c8de70cb4c@35.188.168.137:443", - ] diff --git a/vendor/nim-eth/eth/p2p/discovery.nim b/vendor/nim-eth/eth/p2p/discovery.nim index ede632324..0c0000e63 100644 --- a/vendor/nim-eth/eth/p2p/discovery.nim +++ b/vendor/nim-eth/eth/p2p/discovery.nim @@ -9,7 +9,7 @@ import std/times, - chronos, stint, nimcrypto/keccak, chronicles, bearssl, + chronos, stint, nimcrypto/keccak, chronicles, stew/[objects, results], ".."/[keys, rlp], "."/[kademlia, enode] @@ -33,21 +33,25 @@ type privKey: PrivateKey address: Address bootstrapNodes*: seq[Node] - thisNode*: Node + localNode*: Node kademlia*: KademliaProtocol[DiscoveryProtocol] transp: DatagramTransport + bindIp: IpAddress + bindPort: Port CommandId = enum cmdPing = 1 cmdPong = 2 cmdFindNode = 3 cmdNeighbours = 4 + cmdENRRequest = 5 + cmdENRResponse = 6 DiscProtocolError* = object of CatchableError DiscResult*[T] = Result[T, cstring] -const MinListLen: array[CommandId, int] = [4, 3, 2, 2] +const MinListLen: array[CommandId, int] = [4, 3, 2, 2, 1, 2] proc append*(w: var RlpWriter, a: IpAddress) = case a.family @@ -154,16 +158,26 @@ proc sendNeighbours*(d: DiscoveryProtocol, node: Node, neighbours: seq[Node]) = if nodes.len != 0: flush() -proc newDiscoveryProtocol*(privKey: PrivateKey, address: Address, - bootstrapNodes: openArray[ENode], rng = newRng() - ): DiscoveryProtocol = - result.new() - result.privKey = privKey - result.address = address - result.bootstrapNodes = newSeqOfCap[Node](bootstrapNodes.len) - for n in bootstrapNodes: result.bootstrapNodes.add(newNode(n)) - result.thisNode = newNode(privKey.toPublicKey(), address) - result.kademlia = newKademliaProtocol(result.thisNode, result, rng = rng) +proc newDiscoveryProtocol*( + privKey: PrivateKey, address: Address, + bootstrapNodes: openArray[ENode], + bindPort: Port, bindIp = IPv4_any(), + rng = newRng()): DiscoveryProtocol = + let + localNode = newNode(privKey.toPublicKey(), address) + discovery = DiscoveryProtocol( + privKey: privKey, + address: address, + localNode: localNode, + bindIp: bindIp, + bindPort: bindPort) + kademlia = newKademliaProtocol(localNode, discovery, rng = rng) + + discovery.kademlia = kademlia + + for n in bootstrapNodes: discovery.bootstrapNodes.add(newNode(n)) + + discovery proc recvPing(d: DiscoveryProtocol, node: Node, msgHash: MDigest[256]) {.raises: [ValueError, Defect].} = @@ -255,6 +269,9 @@ proc receive*(d: DiscoveryProtocol, a: Address, msg: openArray[byte]) d.recvNeighbours(node, payload) of cmdFindNode: d.recvFindNode(node, payload) + of cmdENRRequest, cmdENRResponse: + # TODO: Implement EIP-868 + discard else: trace "Received msg already expired", cmdId, a else: @@ -281,8 +298,8 @@ proc processClient(transp: DatagramTransport, raddr: TransportAddress): debug "Receive failed", exc = e.name, err = e.msg proc open*(d: DiscoveryProtocol) {.raises: [Defect, CatchableError].} = - # TODO allow binding to specific IP / IPv6 / etc - let ta = initTAddress(IPv4_any(), d.address.udpPort) + # TODO: allow binding to both IPv4 and IPv6 + let ta = initTAddress(d.bindIp, d.bindPort) d.transp = newDatagramTransport(processClient, udata = d, local = ta) proc lookupRandom*(d: DiscoveryProtocol): Future[seq[Node]] = @@ -341,10 +358,10 @@ when isMainModule: let listenPort = Port(30310) var address = Address(udpPort: listenPort, tcpPort: listenPort) address.ip.family = IpAddressFamily.IPv4 - let discovery = newDiscoveryProtocol(privkey, address, bootnodes) + let discovery = newDiscoveryProtocol(privkey, address, bootnodes, listenPort) - echo discovery.thisNode.node.pubkey - echo "this_node.id: ", discovery.thisNode.id.toHex() + echo discovery.localNode.node.pubkey + echo "this_node.id: ", discovery.localNode.id.toHex() discovery.open() diff --git a/vendor/nim-eth/eth/p2p/discoveryv5/encoding.nim b/vendor/nim-eth/eth/p2p/discoveryv5/encoding.nim index 20be9bcd1..3b2768291 100644 --- a/vendor/nim-eth/eth/p2p/discoveryv5/encoding.nim +++ b/vendor/nim-eth/eth/p2p/discoveryv5/encoding.nim @@ -15,7 +15,8 @@ import std/[tables, options, hashes, net], - nimcrypto, stint, chronicles, bearssl, stew/[results, byteutils], metrics, + nimcrypto/[bcmode, rijndael, sha2], stint, chronicles, + stew/[results, byteutils], metrics, ".."/../[rlp, keys], "."/[messages, node, enr, hkdf, sessions] @@ -44,6 +45,11 @@ const staticHeaderSize = protocolId.len + 2 + 2 + 1 + gcmNonceSize authdataHeadSize = sizeof(NodeId) + 1 + 1 whoareyouSize = ivSize + staticHeaderSize + idNonceSize + 8 + # It's mentioned in the specification that 1280 is the maximum size for the + # discovery v5 packet, not for the UDP datagram. Thus this limit is applied on + # the UDP payload and the UDP header is not taken into account. + # https://github.com/ethereum/devp2p/blob/26e380b1f3a57db16fbdd4528dde82104c77fa38/discv5/discv5-wire.md#udp-communication + maxDiscv5PacketSize* = 1280 type AESGCMNonce* = array[gcmNonceSize, byte] @@ -189,18 +195,19 @@ proc encodeStaticHeader*(flag: Flag, nonce: AESGCMNonce, authSize: int): # TODO: assert on authSize of > 2^16? result.add((uint16(authSize)).toBytesBE()) -proc encodeMessagePacket*(rng: var BrHmacDrbgContext, c: var Codec, +proc encodeMessagePacket*(rng: var HmacDrbgContext, c: var Codec, toId: NodeId, toAddr: Address, message: openArray[byte]): (seq[byte], AESGCMNonce) = - var nonce: AESGCMNonce - brHmacDrbgGenerate(rng, nonce) # Random AESGCM nonce - var iv: array[ivSize, byte] - brHmacDrbgGenerate(rng, iv) # Random IV + let + nonce = rng.generate(AESGCMNonce) # Random AESGCM nonce + iv = rng.generate(array[ivSize, byte]) # Random IV # static-header - let authdata = c.localNode.id.toByteArrayBE() - let staticHeader = encodeStaticHeader(Flag.OrdinaryMessage, nonce, - authdata.len()) + let + authdata = c.localNode.id.toByteArrayBE() + staticHeader = encodeStaticHeader(Flag.OrdinaryMessage, nonce, + authdata.len()) + # header = static-header || authdata var header: seq[byte] header.add(staticHeader) @@ -220,8 +227,7 @@ proc encodeMessagePacket*(rng: var BrHmacDrbgContext, c: var Codec, # message. 16 bytes for the gcm tag and 4 bytes for ping with requestId of # 1 byte (e.g "01c20101"). Could increase to 27 for 8 bytes requestId in # case this must not look like a random packet. - var randomData: array[gcmTagSize + 4, byte] - brHmacDrbgGenerate(rng, randomData) + let randomData = rng.generate(array[gcmTagSize + 4, byte]) messageEncrypted.add(randomData) discovery_session_lru_cache_misses.inc() @@ -234,11 +240,11 @@ proc encodeMessagePacket*(rng: var BrHmacDrbgContext, c: var Codec, return (packet, nonce) -proc encodeWhoareyouPacket*(rng: var BrHmacDrbgContext, c: var Codec, +proc encodeWhoareyouPacket*(rng: var HmacDrbgContext, c: var Codec, toId: NodeId, toAddr: Address, requestNonce: AESGCMNonce, recordSeq: uint64, pubkey: Option[PublicKey]): seq[byte] = - var idNonce: IdNonce - brHmacDrbgGenerate(rng, idNonce) + let + idNonce = rng.generate(IdNonce) # authdata var authdata: seq[byte] @@ -254,10 +260,9 @@ proc encodeWhoareyouPacket*(rng: var BrHmacDrbgContext, c: var Codec, header.add(staticHeader) header.add(authdata) - var iv: array[ivSize, byte] - brHmacDrbgGenerate(rng, iv) # Random IV - - let maskedHeader = encryptHeader(toId, iv, header) + let + iv = rng.generate(array[ivSize, byte]) # Random IV + maskedHeader = encryptHeader(toId, iv, header) var packet: seq[byte] packet.add(iv) @@ -276,14 +281,12 @@ proc encodeWhoareyouPacket*(rng: var BrHmacDrbgContext, c: var Codec, return packet -proc encodeHandshakePacket*(rng: var BrHmacDrbgContext, c: var Codec, +proc encodeHandshakePacket*(rng: var HmacDrbgContext, c: var Codec, toId: NodeId, toAddr: Address, message: openArray[byte], whoareyouData: WhoareyouData, pubkey: PublicKey): seq[byte] = - var header: seq[byte] - var nonce: AESGCMNonce - brHmacDrbgGenerate(rng, nonce) - var iv: array[ivSize, byte] - brHmacDrbgGenerate(rng, iv) # Random IV + let + nonce = rng.generate(AESGCMNonce) + iv = rng.generate(array[ivSize, byte]) # Random IV var authdata: seq[byte] var authdataHead: seq[byte] @@ -312,6 +315,7 @@ proc encodeHandshakePacket*(rng: var BrHmacDrbgContext, c: var Codec, let staticHeader = encodeStaticHeader(Flag.HandshakeMessage, nonce, authdata.len()) + var header: seq[byte] header.add(staticHeader) header.add(authdata) @@ -580,7 +584,10 @@ proc decodePacket*(c: var Codec, fromAddr: Address, input: openArray[byte]): ## WHOAREYOU packet. In case of the latter a `newNode` might be provided. # Smallest packet is Whoareyou packet so that is the minimum size if input.len() < whoareyouSize: - return err("Packet size too short") + return err("Packet size too small") + + if input.len() > maxDiscv5PacketSize: + return err("Packet size too big") # TODO: Just pass in the full input? Makes more sense perhaps. let (staticHeader, header) = ? decodeHeader(c.localNode.id, @@ -604,9 +611,9 @@ proc decodePacket*(c: var Codec, fromAddr: Address, input: openArray[byte]): input.toOpenArray(0, ivSize - 1), header, input.toOpenArray(ivSize + header.len, input.high)) -proc init*(T: type RequestId, rng: var BrHmacDrbgContext): T = +proc init*(T: type RequestId, rng: var HmacDrbgContext): T = var reqId = RequestId(id: newSeq[byte](8)) # RequestId must be <= 8 bytes - brHmacDrbgGenerate(rng, reqId.id) + rng.generate(reqId.id) reqId proc numFields(T: typedesc): int = diff --git a/vendor/nim-eth/eth/p2p/discoveryv5/enr.nim b/vendor/nim-eth/eth/p2p/discoveryv5/enr.nim index acb50fefe..1cad2f74e 100644 --- a/vendor/nim-eth/eth/p2p/discoveryv5/enr.nim +++ b/vendor/nim-eth/eth/p2p/discoveryv5/enr.nim @@ -12,7 +12,7 @@ import std/[strutils, macros, algorithm, options], - stew/shims/net, stew/[base64, results], nimcrypto, + nimcrypto/[keccak, utils], stew/shims/net, stew/[base64, results], ".."/../[rlp, keys] export options, results, keys diff --git a/vendor/nim-eth/eth/p2p/discoveryv5/hkdf.nim b/vendor/nim-eth/eth/p2p/discoveryv5/hkdf.nim index 88ee7c9ca..6332694fb 100644 --- a/vendor/nim-eth/eth/p2p/discoveryv5/hkdf.nim +++ b/vendor/nim-eth/eth/p2p/discoveryv5/hkdf.nim @@ -1,4 +1,7 @@ -import nimcrypto +import + nimcrypto/[hmac, hash] + +export hmac, hash proc hkdf*(HashType: typedesc, ikm, salt, info: openArray[byte], output: var openArray[byte]) = diff --git a/vendor/nim-eth/eth/p2p/discoveryv5/node.nim b/vendor/nim-eth/eth/p2p/discoveryv5/node.nim index 3b311b953..eda62ac67 100644 --- a/vendor/nim-eth/eth/p2p/discoveryv5/node.nim +++ b/vendor/nim-eth/eth/p2p/discoveryv5/node.nim @@ -9,7 +9,7 @@ import std/hashes, - nimcrypto, stint, chronos, stew/shims/net, chronicles, + nimcrypto/[keccak], stint, chronos, stew/shims/net, chronicles, ../../keys, ../../net/utils, ./enr @@ -86,11 +86,8 @@ func `==`*(a, b: Node): bool = func hash*(id: NodeId): Hash = hash(id.toByteArrayBE) -proc random*(T: type NodeId, rng: var BrHmacDrbgContext): T = - var id: NodeId - brHmacDrbgGenerate(addr rng, addr id, csize_t(sizeof(id))) - - id +proc random*(T: type NodeId, rng: var HmacDrbgContext): T = + rng.generate(T) func `$`*(id: NodeId): string = id.toHex() diff --git a/vendor/nim-eth/eth/p2p/discoveryv5/protocol.nim b/vendor/nim-eth/eth/p2p/discoveryv5/protocol.nim index 3782c2e61..4e09c32ed 100644 --- a/vendor/nim-eth/eth/p2p/discoveryv5/protocol.nim +++ b/vendor/nim-eth/eth/p2p/discoveryv5/protocol.nim @@ -1,5 +1,5 @@ # nim-eth - Node Discovery Protocol v5 -# Copyright (c) 2020-2021 Status Research & Development GmbH +# Copyright (c) 2020-2022 Status Research & Development GmbH # Licensed and distributed under either of # * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). # * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). @@ -52,37 +52,44 @@ ## https://github.com/ethereum/devp2p/blob/master/discv5/discv5-rationale.md#115-guard-against-kademlia-implementation-flaws ## ## The result is that in an implementation which just stores buckets per -## logarithmic distance, it simply needs to return the right bucket. In our +## logarithmic distance, it simply needs to return the right bucket. In this ## split-bucket implementation, this cannot be done as such and thus the closest ## neighbours search is still done. And to do this, a reverse calculation of an ## id at given logarithmic distance is needed (which is why there is the ## `idAtDistance` proc). Next, nodes with invalid distances need to be filtered ## out to be compliant to the specification. This can most likely get further -## optimised, but it sounds likely better to switch away from the split-bucket -## approach. I believe that the main benefit it has is improved lookups -## (due to no unbalanced branches), and it looks like this will be negated by -## limiting the returned nodes to only the ones of the requested logarithmic -## distance for the `FindNode` call. +## optimised, but if it would turn out to be an issue, it is probably easier to +## switch away from the split-bucket approach. The main benefit that the split +## bucket approach has is improved lookups (less hops due to no unbalanced +## branches), but lookup functionality of Kademlia is not something that is +## typically used in discv5. It is mostly used as a secure mechanism to find & +## select peers. -## This `FindNode` change in discovery v5 will also have an effect on the +## This `FindNode` change in discovery v5 could also have an effect on the ## efficiency of the network. Work will be moved from the receiver of -## `FindNodes` to the requester. But this also means more network traffic, -## as less nodes will potentially be passed around per `FindNode` call, and thus -## more requests will be needed for a lookup (adding bandwidth and latency). -## This might be a concern for mobile devices. +## `FindNodes` to the requester. But this could also mean more network traffic, +## as less nodes may potentially be passed around per `FindNode` call, and thus +## more requests may be needed for a lookup (adding bandwidth and latency). +## For this reason Discovery v5.1 has added the possibility to send a `FindNode` +## request with multiple distances specified. This implementation will +## underneath still use the neighbours search, specifically for the first +## distance provided. This means that if distances with wide gaps are provided, +## it could be that only nodes matching the first distance are returned. +## When distance 0 is provided in the requested list of distances, only the own +## ENR will be returned. {.push raises: [Defect].} import std/[tables, sets, options, math, sequtils, algorithm], stew/shims/net as stewNet, json_serialization/std/net, - stew/[endians2, results], chronicles, chronos, stint, bearssl, metrics, + stew/[endians2, results], chronicles, chronos, stint, metrics, ".."/../[rlp, keys, async_utils], - "."/[messages, encoding, node, routing_table, enr, random2, sessions, ip_vote, nodes_verification] + "."/[messages, encoding, node, routing_table, enr, random2, sessions, ip_vote, + nodes_verification] -import nimcrypto except toHex - -export options, results, node, enr +export + options, results, node, enr, encoding.maxDiscv5PacketSize declareCounter discovery_message_requests_outgoing, "Discovery protocol outgoing message requests", labels = ["response"] @@ -110,15 +117,17 @@ const ipMajorityInterval = 5.minutes ## Interval for checking the latest IP:Port ## majority and updating this when ENR auto update is set. initialLookups = 1 ## Amount of lookups done when populating the routing table - handshakeTimeout* = 2.seconds ## timeout for the reply on the + defaultHandshakeTimeout* = 2.seconds ## timeout for the reply on the ## whoareyou message - responseTimeout* = 4.seconds ## timeout for the response of a request-response + defaultResponseTimeout* = 4.seconds ## timeout for the response of a request-response ## call type DiscoveryConfig* = object tableIpLimits*: TableIpLimits bitsPerHop*: int + handshakeTimeout: Duration + responseTimeout: Duration Protocol* = ref object transp: DatagramTransport @@ -138,13 +147,17 @@ type enrAutoUpdate: bool talkProtocols*: Table[seq[byte], TalkProtocol] # TODO: Table is a bit of # overkill here, use sequence - rng*: ref BrHmacDrbgContext + handshakeTimeout: Duration + responseTimeout: Duration + rng*: ref HmacDrbgContext PendingRequest = object node: Node message: seq[byte] - TalkProtocolHandler* = proc(p: TalkProtocol, request: seq[byte], fromId: NodeId, fromUdpAddress: Address): seq[byte] + TalkProtocolHandler* = proc( + p: TalkProtocol, request: seq[byte], + fromId: NodeId, fromUdpAddress: Address): seq[byte] {.gcsafe, raises: [Defect].} TalkProtocol* = ref object of RootObj @@ -155,7 +168,10 @@ type const defaultDiscoveryConfig* = DiscoveryConfig( tableIpLimits: DefaultTableIpLimits, - bitsPerHop: DefaultBitsPerHop) + bitsPerHop: DefaultBitsPerHop, + handshakeTimeout: defaultHandshakeTimeout, + responseTimeout: defaultResponseTimeout + ) proc addNode*(d: Protocol, node: Node): bool = ## Add `Node` to discovery routing table. @@ -381,7 +397,7 @@ proc sendWhoareyou(d: Protocol, toId: NodeId, a: Address, let data = encodeWhoareyouPacket(d.rng[], d.codec, toId, a, requestNonce, recordSeq, pubkey) - sleepAsync(handshakeTimeout).addCallback() do(data: pointer): + sleepAsync(d.handshakeTimeout).addCallback() do(data: pointer): # TODO: should we still provide cancellation in case handshake completes # correctly? d.codec.handshakes.del(key) @@ -476,7 +492,7 @@ proc registerRequest(d: Protocol, n: Node, message: seq[byte], nonce: AESGCMNonce) = let request = PendingRequest(node: n, message: message) if not d.pendingRequests.hasKeyOrPut(nonce, request): - sleepAsync(responseTimeout).addCallback() do(data: pointer): + sleepAsync(d.responseTimeout).addCallback() do(data: pointer): d.pendingRequests.del(nonce) proc waitMessage(d: Protocol, fromNode: Node, reqId: RequestId): @@ -484,7 +500,7 @@ proc waitMessage(d: Protocol, fromNode: Node, reqId: RequestId): result = newFuture[Option[Message]]("waitMessage") let res = result let key = (fromNode.id, reqId) - sleepAsync(responseTimeout).addCallback() do(data: pointer): + sleepAsync(d.responseTimeout).addCallback() do(data: pointer): d.awaitedMessages.del(key) if not res.finished: res.complete(none(Message)) @@ -842,6 +858,22 @@ proc refreshLoop(d: Protocol) {.async.} = except CancelledError: trace "refreshLoop canceled" +proc updateExternalIp*(d: Protocol, extIp: ValidIpAddress, udpPort: Port): bool = + var success = false + let + previous = d.localNode.address + res = d.localNode.update(d.privateKey, + ip = some(extIp), udpPort = some(udpPort)) + + if res.isErr: + warn "Failed updating ENR with newly discovered external address", + previous, newExtIp = extIp, newUdpPort = udpPort, error = res.error + else: + success = true + info "Updated ENR with newly discovered external address", + previous, newExtIp = extIp, newUdpPort = udpPort, uri = toURI(d.localNode.record) + return success + proc ipMajorityLoop(d: Protocol) {.async.} = ## When `enrAutoUpdate` is enabled, the IP:port combination returned ## by the majority will be used to update the local ENR. @@ -869,15 +901,9 @@ proc ipMajorityLoop(d: Protocol) {.async.} = let address = majority.get() let previous = d.localNode.address if d.enrAutoUpdate: - let res = d.localNode.update(d.privateKey, - ip = some(address.ip), udpPort = some(address.port)) - if res.isErr: - warn "Failed updating ENR with newly discovered external address", - majority, previous, error = res.error - else: + let success = d.updateExternalIp(address.ip, address.port) + if success: discovery_enr_auto_update.inc() - info "Updated ENR with newly discovered external address", - majority, previous, uri = toURI(d.localNode.record) else: warn "Discovered new external address but ENR auto update is off", majority, previous @@ -893,13 +919,32 @@ func init*( T: type DiscoveryConfig, tableIpLimit: uint, bucketIpLimit: uint, - bitsPerHop: int): T = + bitsPerHop: int, + handshakeTimeout: Duration, + responseTimeout: Duration + ): T = DiscoveryConfig( tableIpLimits: TableIpLimits( tableIpLimit: tableIpLimit, bucketIpLimit: bucketIpLimit), - bitsPerHop: bitsPerHop + bitsPerHop: bitsPerHop, + handshakeTimeout: handshakeTimeout, + responseTimeout: responseTimeout + ) + +func init*( + T: type DiscoveryConfig, + tableIpLimit: uint, + bucketIpLimit: uint, + bitsPerHop: int): T = + + DiscoveryConfig.init( + tableIpLimit, + bucketIpLimit, + bitsPerHop, + defaultHandshakeTimeout, + defaultResponseTimeout ) proc newProtocol*( @@ -963,6 +1008,8 @@ proc newProtocol*( enrAutoUpdate: enrAutoUpdate, routingTable: RoutingTable.init( node, config.bitsPerHop, config.tableIpLimits, rng), + handshakeTimeout: config.handshakeTimeout, + responseTimeout: config.responseTimeout, rng: rng) template listeningAddress*(p: Protocol): Address = diff --git a/vendor/nim-eth/eth/p2p/discoveryv5/random2.nim b/vendor/nim-eth/eth/p2p/discoveryv5/random2.nim index 0ec72f0f4..02d69e4f8 100644 --- a/vendor/nim-eth/eth/p2p/discoveryv5/random2.nim +++ b/vendor/nim-eth/eth/p2p/discoveryv5/random2.nim @@ -1,22 +1,25 @@ -import bearssl +import + bearssl/rand -## Random helpers: similar as in stdlib, but with BrHmacDrbgContext rng +export rand + +## Random helpers: similar as in stdlib, but with HmacDrbgContext rng # TODO: Move these somewhere else? const randMax = 18_446_744_073_709_551_615'u64 -proc rand*(rng: var BrHmacDrbgContext, max: Natural): int = +proc rand*(rng: var HmacDrbgContext, max: Natural): int = if max == 0: return 0 var x: uint64 while true: - brHmacDrbgGenerate(addr rng, addr x, csize_t(sizeof(x))) + rng.generate(x) if x < randMax - (randMax mod (uint64(max) + 1'u64)): # against modulo bias return int(x mod (uint64(max) + 1'u64)) -proc sample*[T](rng: var BrHmacDrbgContext, a: openArray[T]): T = - result = a[rng.rand(a.high)] +proc sample*[T](rng: var HmacDrbgContext, a: openArray[T]): T = + a[rng.rand(a.high)] -proc shuffle*[T](rng: var BrHmacDrbgContext, a: var openArray[T]) = +proc shuffle*[T](rng: var HmacDrbgContext, a: var openArray[T]) = for i in countdown(a.high, 1): let j = rng.rand(i) swap(a[i], a[j]) diff --git a/vendor/nim-eth/eth/p2p/discoveryv5/routing_table.nim b/vendor/nim-eth/eth/p2p/discoveryv5/routing_table.nim index 136ad39f2..00f2965ed 100644 --- a/vendor/nim-eth/eth/p2p/discoveryv5/routing_table.nim +++ b/vendor/nim-eth/eth/p2p/discoveryv5/routing_table.nim @@ -9,7 +9,8 @@ import std/[algorithm, times, sequtils, bitops, sets, options], - stint, chronicles, metrics, bearssl, chronos, stew/shims/net as stewNet, + bearssl/rand, + stint, chronicles, metrics, chronos, stew/shims/net as stewNet, ../../net/utils, "."/[node, random2, enr] @@ -42,7 +43,7 @@ type ipLimits: IpLimits ## IP limits for total routing table: all buckets and ## replacement caches. distanceCalculator: DistanceCalculator - rng: ref BrHmacDrbgContext + rng: ref HmacDrbgContext KBucket = ref object istart, iend: NodeId ## Range of NodeIds this KBucket covers. This is not a @@ -260,7 +261,7 @@ proc computeSharedPrefixBits(nodes: openArray[NodeId]): int = doAssert(false, "Unable to calculate number of shared prefix bits") proc init*(T: type RoutingTable, localNode: Node, bitsPerHop = DefaultBitsPerHop, - ipLimits = DefaultTableIpLimits, rng: ref BrHmacDrbgContext, + ipLimits = DefaultTableIpLimits, rng: ref HmacDrbgContext, distanceCalculator = XorDistanceCalculator): T = ## Initialize the routing table for provided `Node` and bitsPerHop value. ## `bitsPerHop` is default set to 5 as recommended by original Kademlia paper. diff --git a/vendor/nim-eth/eth/p2p/ecies.nim b/vendor/nim-eth/eth/p2p/ecies.nim index d32167ab9..164cc3ccc 100644 --- a/vendor/nim-eth/eth/p2p/ecies.nim +++ b/vendor/nim-eth/eth/p2p/ecies.nim @@ -13,7 +13,7 @@ {.push raises: [Defect].} import - bearssl, stew/[results, endians2], + stew/[results, endians2], nimcrypto/[rijndael, bcmode, hash, hmac, sha2, utils], ../keys @@ -93,7 +93,7 @@ proc kdf*(data: openArray[byte]): array[KeyLength, byte] {.noinit.} = ctx.clear() # clean ctx copyMem(addr result[0], addr storage[0], KeyLength) -proc eciesEncrypt*(rng: var BrHmacDrbgContext, input: openArray[byte], +proc eciesEncrypt*(rng: var HmacDrbgContext, input: openArray[byte], output: var openArray[byte], pubkey: PublicKey, sharedmac: openArray[byte] = emptyMac): EciesResult[void] = ## Encrypt data with ECIES method using given public key `pubkey`. @@ -107,13 +107,10 @@ proc eciesEncrypt*(rng: var BrHmacDrbgContext, input: openArray[byte], encKey: array[aes128.sizeKey, byte] cipher: CTR[aes128] ctx: HMAC[sha256] - iv: array[aes128.sizeBlock, byte] if len(output) < eciesEncryptedLength(len(input)): return err(BufferOverrun) - brHmacDrbgGenerate(rng, iv) - var ephemeral = KeyPair.random(rng) secret = ecdhRaw(ephemeral.seckey, pubkey) @@ -130,13 +127,13 @@ proc eciesEncrypt*(rng: var BrHmacDrbgContext, input: openArray[byte], var header = cast[ptr EciesHeader](addr output[0]) header.version = 0x04 header.pubkey = ephemeral.pubkey.toRaw() - header.iv = iv + rng.generate(header[].iv) clear(ephemeral) var so = eciesDataPos() var eo = so + len(input) - cipher.init(encKey, iv) + cipher.init(encKey, header.iv) cipher.encrypt(input, toOpenArray(output, so, eo)) burnMem(encKey) cipher.clear() diff --git a/vendor/nim-eth/eth/p2p/kademlia.nim b/vendor/nim-eth/eth/p2p/kademlia.nim index c904647cb..c75b5021c 100644 --- a/vendor/nim-eth/eth/p2p/kademlia.nim +++ b/vendor/nim-eth/eth/p2p/kademlia.nim @@ -9,7 +9,7 @@ import std/[tables, hashes, times, algorithm, sets, sequtils, random], - chronos, bearssl, chronicles, stint, nimcrypto/keccak, + chronos, chronicles, stint, nimcrypto/keccak, ../keys, ./enode @@ -26,7 +26,7 @@ type pongFutures: Table[seq[byte], Future[bool]] pingFutures: Table[Node, Future[bool]] neighboursCallbacks: Table[Node, proc(n: seq[Node]) {.gcsafe, raises: [Defect].}] - rng: ref BrHmacDrbgContext + rng: ref HmacDrbgContext NodeId* = UInt256 @@ -452,12 +452,7 @@ proc lookup*(k: KademliaProtocol, nodeId: NodeId): Future[seq[Node]] {.async.} = result = closest proc lookupRandom*(k: KademliaProtocol): Future[seq[Node]] = - var id: NodeId - var buf: array[sizeof(id), byte] - brHmacDrbgGenerate(k.rng[], buf) - copyMem(addr id, addr buf[0], sizeof(id)) - - k.lookup(id) + k.lookup(k.rng[].generate(NodeId)) proc resolve*(k: KademliaProtocol, id: NodeId): Future[Node] {.async.} = let closest = await k.lookup(id) diff --git a/vendor/nim-eth/eth/p2p/peer_pool.nim b/vendor/nim-eth/eth/p2p/peer_pool.nim index d8853cce0..9a5fb183e 100644 --- a/vendor/nim-eth/eth/p2p/peer_pool.nim +++ b/vendor/nim-eth/eth/p2p/peer_pool.nim @@ -14,16 +14,15 @@ import std/[os, tables, times, random, sequtils, options], chronos, chronicles, ".."/[rlp, keys, common], - ./private/p2p_types, "."/[discovery, kademlia, rlpx] + ./private/p2p_types, "."/[discovery, kademlia, rlpx, enode] const lookupInterval = 5 connectLoopSleep = chronos.milliseconds(2000) -proc newPeerPool*(network: EthereumNode, - networkId: NetworkId, keyPair: KeyPair, - discovery: DiscoveryProtocol, clientId: string, - listenPort = Port(30303), minPeers = 10): PeerPool = +proc newPeerPool*( + network: EthereumNode, networkId: NetworkId, keyPair: KeyPair, + discovery: DiscoveryProtocol, clientId: string, minPeers = 10): PeerPool = new result result.network = network result.keyPair = keyPair @@ -33,12 +32,11 @@ proc newPeerPool*(network: EthereumNode, result.connectedNodes = initTable[Node, Peer]() result.connectingNodes = initHashSet[Node]() result.observers = initTable[int, PeerObserver]() - result.listenPort = listenPort proc nodesToConnect(p: PeerPool): seq[Node] = p.discovery.randomNodes(p.minPeers).filterIt(it notin p.discovery.bootstrapNodes) -proc addObserver(p: PeerPool, observerId: int, observer: PeerObserver) = +proc addObserver*(p: PeerPool, observerId: int, observer: PeerObserver) = doAssert(observerId notin p.observers) p.observers[observerId] = observer if not observer.onPeerConnected.isNil: @@ -46,7 +44,7 @@ proc addObserver(p: PeerPool, observerId: int, observer: PeerObserver) = if observer.protocol.isNil or peer.supports(observer.protocol): observer.onPeerConnected(peer) -proc delObserver(p: PeerPool, observerId: int) = +proc delObserver*(p: PeerPool, observerId: int) = p.observers.del(observerId) proc addObserver*(p: PeerPool, observerId: ref, observer: PeerObserver) = @@ -125,9 +123,12 @@ proc connectToNode*(p: PeerPool, n: Node) {.async.} = trace "Connection established (outgoing)", peer p.addPeer(peer) +proc connectToNode*(p: PeerPool, n: ENode) {.async.} = + await p.connectToNode(newNode(n)) + proc connectToNodes(p: PeerPool, nodes: seq[Node]) {.async.} = for node in nodes: - discard p.connectToNode(node) + await p.connectToNode(node) # # TODO: Consider changing connect() to raise an exception instead of # # returning None, as discussed in @@ -169,6 +170,8 @@ proc run(p: PeerPool) {.async.} = trace "Running PeerPool..." p.running = true while p.running: + + debug "Amount of peers", amount = p.connectedNodes.len() var dropConnections = false try: await p.maybeConnectToMorePeers() @@ -213,3 +216,16 @@ iterator peers*(p: PeerPool, Protocol: type): Peer = if peer.supports(Protocol): yield peer +func numPeers*(p: PeerPool): int = + p.connectedNodes.len + +func contains*(p: PeerPool, n: ENode): bool = + for remote, _ in p.connectedNodes: + if remote.node == n: + return true + +func contains*(p: PeerPool, n: Node): bool = + n in p.connectedNodes + +func contains*(p: PeerPool, n: Peer): bool = + n.remote in p.connectedNodes diff --git a/vendor/nim-eth/eth/p2p/private/p2p_types.nim b/vendor/nim-eth/eth/p2p/private/p2p_types.nim index e0bb92555..d0ea28611 100644 --- a/vendor/nim-eth/eth/p2p/private/p2p_types.nim +++ b/vendor/nim-eth/eth/p2p/private/p2p_types.nim @@ -1,3 +1,4 @@ + # nim-eth # Copyright (c) 2018-2021 Status Research & Development GmbH # Licensed and distributed under either of @@ -7,10 +8,14 @@ import std/[deques, tables], - bearssl, chronos, - ".."/../[rlp, keys], ".."/../common/eth_types, + chronos, + stew/results, + ../../common/chaindb, + ".."/../[rlp, keys], ".."/[enode, kademlia, discovery, rlpxcrypt] +export chaindb + const useSnappy* = defined(useSnappy) @@ -25,6 +30,8 @@ type keys*: KeyPair address*: Address # The external address that the node will be advertising peerPool*: PeerPool + bindIp*: IpAddress + bindPort*: Port # Private fields: capabilities*: seq[Capability] @@ -34,7 +41,7 @@ type discovery*: DiscoveryProtocol when useSnappy: protocolVersion*: uint - rng*: ref BrHmacDrbgContext + rng*: ref HmacDrbgContext Peer* = ref object remote*: Node @@ -64,7 +71,6 @@ type connectedNodes*: Table[Node, Peer] connectingNodes*: HashSet[Node] running*: bool - listenPort*: Port observers*: Table[int, PeerObserver] PeerObserver* = object diff --git a/vendor/nim-eth/eth/p2p/rlpx.nim b/vendor/nim-eth/eth/p2p/rlpx.nim index bc0bb33ec..a69d06ca1 100644 --- a/vendor/nim-eth/eth/p2p/rlpx.nim +++ b/vendor/nim-eth/eth/p2p/rlpx.nim @@ -9,10 +9,21 @@ import std/[tables, algorithm, deques, hashes, options, typetraits], - stew/shims/macros, chronicles, nimcrypto, chronos, + stew/shims/macros, chronicles, nimcrypto/utils, chronos, ".."/[rlp, common, keys, async_utils], ./private/p2p_types, "."/[kademlia, auth, rlpxcrypt, enode, p2p_protocol_dsl] +const + # Insane kludge for suppporting chunked messages when syncing against clients + # like Nethermind. + # + # The original specs which are now obsoleted can be found here: + # github.com/ethereum/devp2p/commit/6504d410bc4b8dda2b43941e1cb48c804b90cf22. + # + # The current requirement is stated at + # github.com/ethereum/devp2p/blob/master/rlpx.md#framing + allowObsoletedChunkedMessages = defined(chunked_rlpx_enabled) + when useSnappy: import snappy const devp2pSnappyVersion* = 5 @@ -43,6 +54,37 @@ type DisconnectionReasonList = object value: DisconnectionReason +proc read(rlp: var Rlp; T: type DisconnectionReasonList): T + {.gcsafe, raises: [RlpError, Defect].} = + ## Rlp mixin: `DisconnectionReasonList` parser + + if rlp.isList: + # Be strict here: The expression `rlp.read(DisconnectionReasonList)` + # accepts lists with at least one item. The array expression wants + # exactly one item. + if rlp.rawData.len < 3: + # avoids looping through all items when parsing for an overlarge array + return DisconnectionReasonList( + value: rlp.read(array[1,DisconnectionReason])[0]) + + # Also accepted: a single byte reason code. Is is typically used + # by variants of the reference implementation `Geth` + elif rlp.blobLen <= 1: + return DisconnectionReasonList( + value: rlp.read(DisconnectionReason)) + + # Also accepted: a blob of a list (aka object) of reason code. It is + # used by `bor`, a `geth` fork + elif rlp.blobLen < 4: + var subList = rlp.toBytes.rlpFromBytes + if subList.isList: + # Ditto, see above. + return DisconnectionReasonList( + value: subList.read(array[1,DisconnectionReason])[0]) + + raise newException(RlpTypeMismatch, "Single entry list expected") + + const devp2pVersion* = 4 maxMsgSize = 1024 * 1024 * 10 @@ -207,7 +249,8 @@ proc getDispatcher(node: EthereumNode, proc getMsgName*(peer: Peer, msgId: int): string = if not peer.dispatcher.isNil and - msgId < peer.dispatcher.messages.len: + msgId < peer.dispatcher.messages.len and + not peer.dispatcher.messages[msgId].isNil: return peer.dispatcher.messages[msgId].name else: return case msgId @@ -452,6 +495,43 @@ proc resolveResponseFuture(peer: Peer, msgId: int, msg: pointer, reqId: int) = debug "late or duplicate reply for a RLPx request" +proc getRlpxHeaderData(header: RlpxHeader): (int,int,int) = + ## Helper for `recvMsg()` + # This is insane. Some clients like Nethermind use the now obsoleted + # chunked message frame protocol, see + # github.com/ethereum/devp2p/commit/6504d410bc4b8dda2b43941e1cb48c804b90cf22. + result = (-1, -1, 0) + proc datagramSize: int = + # For logging only + (header[0].int shl 16) or (header[1].int shl 8) or header[1].int + try: + let optsLen = max(0, header[3].int - 0xc0) + var hdrData = header[4 ..< 4 + optsLen].rlpFromBytes + result[0] = hdrData.read(int) # capability ID + result[1] = hdrData.read(int) # context ID + if hdrData.isBlob: + result[2] = hdrData.read(int) # total packet size + trace "RLPx message first chunked header-data", + capabilityId = result[0], + contextId = result[1], + totalPacketSize = result[2], + datagramSize = datagramSize() + #[ + elif 0 < result[1]: + # This should be all zero according to latest specs + trace "RLPx message chunked next header-data", + capabilityId = result[0], + contextId = result[1], + datagramSize = datagramSize() + #]# + except: + error "RLPx message header-data options, parse error", + capabilityId = result[0], + contextId = result[1], + totalPacketSize = result[2], + datagramSize = datagramSize() + result = (-1, -1, -1) + proc recvMsg*(peer: Peer): Future[tuple[msgId: int, msgData: Rlp]] {.async.} = ## This procs awaits the next complete RLPx message in the TCP stream @@ -459,8 +539,9 @@ proc recvMsg*(peer: Peer): Future[tuple[msgId: int, msgData: Rlp]] {.async.} = await peer.transport.readExactly(addr headerBytes[0], 32) var msgSize: int + var msgHeader: RlpxHeader if decryptHeaderAndGetMsgSize(peer.secretsState, - headerBytes, msgSize).isErr(): + headerBytes, msgSize, msgHeader).isErr(): await peer.disconnectAndRaise(BreachOfProtocol, "Cannot decrypt RLPx frame header") @@ -496,16 +577,104 @@ proc recvMsg*(peer: Peer): Future[tuple[msgId: int, msgData: Rlp]] {.async.} = if decryptedBytes.len == 0: await peer.disconnectAndRaise(BreachOfProtocol, "Snappy uncompress encountered malformed data") + + # Check embedded header-data for start of an obsoleted chunked message. + # + # The current RLPx requirements need all triple entries <= 0, see + # github.com/ethereum/devp2p/blob/master/rlpx.md#framing + let (capaId, ctxId, totalMsgSize) = msgHeader.getRlpxHeaderData + + when not allowObsoletedChunkedMessages: + # Note that the check should come *before* the `msgId` is read. For + # instance, if this is a malformed packet, then the `msgId` might be + # random which in turn might try to access a `peer.dispatcher.messages[]` + # slot with a `nil` entry. + if 0 < capaId or 0 < ctxId or 0 < totalMsgSize: + await peer.disconnectAndRaise( + BreachOfProtocol, "Rejected obsoleted chunked message header") + var rlp = rlpFromBytes(decryptedBytes) + var msgId: int32 try: # int32 as this seems more than big enough for the amount of msgIds - let msgId = rlp.read(int32) - return (msgId.int, rlp) + msgId = rlp.read(int32) + result = (msgId.int, rlp) except RlpError: await peer.disconnectAndRaise(BreachOfProtocol, "Cannot read RLPx message id") + # Handle chunked messages + when allowObsoletedChunkedMessages: + # Snappy with obsolete chunked RLPx message datagrams is unsupported here + when useSnappy: + if peer.snappyEnabled: + return + + # This also covers totalMessageSize <= 0 + if totalMsgSize <= msgSize: + return + + # Loop over chunked RLPx datagram fragments + var moreData = totalMsgSize - msgSize + while 0 < moreData: + + # Load and parse next header + block: + await peer.transport.readExactly(addr headerBytes[0], 32) + if decryptHeaderAndGetMsgSize(peer.secretsState, + headerBytes, msgSize, msgHeader).isErr(): + trace "RLPx next chunked header-data failed", + peer, msgId, ctxId, maxSize = moreData + await peer.disconnectAndRaise( + BreachOfProtocol, "Cannot decrypt next chunked RLPx header") + + # Verify that this is really the next chunk + block: + let (_, ctyId, totalSize) = msgHeader.getRlpxHeaderData + if ctyId != ctxId or 0 < totalSize: + trace "Malformed RLPx next chunked header-data", + peer, msgId, msgSize, ctxtId = ctyId, expCtxId = ctxId, totalSize + await peer.disconnectAndRaise( + BreachOfProtocol, "Malformed next chunked RLPx header") + + # Append payload to `decryptedBytes` collector + block: + var encBytes = newSeq[byte](msgSize.encryptedLength - 32) + await peer.transport.readExactly(addr encBytes[0], encBytes.len) + var + dcrBytes = newSeq[byte](msgSize.decryptedLength) + dcrBytesCount = 0 + # TODO: This should be improved by passing a reference into + # `decryptedBytes` where to append the data. + if decryptBody(peer.secretsState, encBytes, msgSize, + dcrBytes, dcrBytesCount).isErr(): + await peer.disconnectAndRaise( + BreachOfProtocol, "Cannot decrypt next chunked RLPx frame body") + decryptedBytes.add dcrBytes[0 ..< dcrBytesCount] + moreData -= msgSize + #[ + trace "RLPx next chunked datagram fragment", + peer, msgId = result[0], ctxId, msgSize, moreData, totalMsgSize, + dcrBytesCount, payloadSoFar = decryptedBytes.len + #]# + + # End While + + if moreData != 0: + await peer.disconnectAndRaise( + BreachOfProtocol, "Malformed assembly of chunked RLPx message") + + # Pass back extended message (first entry remains `msgId`) + result[1] = decryptedBytes.rlpFromBytes + result[1].position = rlp.position + + trace "RLPx chunked datagram payload", + peer, msgId, ctxId, totalMsgSize, moreData, payload = decryptedBytes.len + + # End `allowObsoletedChunkedMessages` + + proc checkedRlpRead(peer: Peer, r: var Rlp, MsgType: type): auto {.raises: [RlpError, Defect].} = when defined(release): @@ -518,7 +687,7 @@ proc checkedRlpRead(peer: Peer, r: var Rlp, MsgType: type): peer = peer, dataType = MsgType.name, exception = e.msg - # rlpData = r.inspect + # rlpData = r.inspect -- don't use (might crash) raise e @@ -1048,22 +1217,19 @@ template baseProtocolVersion(peer: Peer): uint = proc rlpxConnect*(node: EthereumNode, remote: Node): Future[Peer] {.async.} = initTracing(devp2pInfo, node.protocols) - new result - result.network = node - result.remote = remote - + let peer = Peer(remote: remote, network: node) let ta = initTAddress(remote.node.address.ip, remote.node.address.tcpPort) var ok = false try: - result.transport = await connect(ta) - var handshake = Handshake.tryInit( - node.rng[], node.keys, {Initiator, EIP8}, node.baseProtocolVersion).tryGet() + peer.transport = await connect(ta) + var handshake = Handshake.init( + node.rng[], node.keys, {Initiator, EIP8}, node.baseProtocolVersion) var authMsg: array[AuthMessageMaxEIP8, byte] var authMsgLen = 0 authMessage( handshake, node.rng[], remote.node.pubkey, authMsg, authMsgLen).tryGet() - var res = await result.transport.write(addr authMsg[0], authMsgLen) + var res = await peer.transport.write(addr authMsg[0], authMsgLen) if res != authMsgLen: raisePeerDisconnected("Unexpected disconnect while authenticating", TcpError) @@ -1072,33 +1238,41 @@ proc rlpxConnect*(node: EthereumNode, remote: Node): Future[Peer] {.async.} = var ackMsg = newSeqOfCap[byte](1024) ackMsg.setLen(initialSize) - await result.transport.readExactly(addr ackMsg[0], len(ackMsg)) + # TODO: Should we not set some timeouts on these `readExactly`s? + await peer.transport.readExactly(addr ackMsg[0], len(ackMsg)) var ret = handshake.decodeAckMessage(ackMsg) if ret.isErr and ret.error == AuthError.IncompleteError: ackMsg.setLen(handshake.expectedLength) - await result.transport.readExactly(addr ackMsg[initialSize], + await peer.transport.readExactly(addr ackMsg[initialSize], len(ackMsg) - initialSize) ret = handshake.decodeAckMessage(ackMsg) - ret.tryGet() # for the raise! - node.checkSnappySupport(handshake, result) - initSecretState(handshake, ^authMsg, ackMsg, result) + if ret.isErr(): + debug "rlpxConnect handshake error", error = ret.error + if not isNil(peer.transport): + peer.transport.close() + return nil + + ret.get() + + node.checkSnappySupport(handshake, peer) + initSecretState(handshake, ^authMsg, ackMsg, peer) # if handshake.remoteHPubkey != remote.node.pubKey: # raise newException(Exception, "Remote pubkey is wrong") - logConnectedPeer result + logConnectedPeer peer - var sendHelloFut = result.hello( + var sendHelloFut = peer.hello( handshake.getVersion(), node.clientId, node.capabilities, uint(node.address.tcpPort), node.keys.pubkey.toRaw()) - var response = await result.handshakeImpl( + var response = await peer.handshakeImpl( sendHelloFut, - result.waitSingleMsg(DevP2P.hello), + peer.waitSingleMsg(DevP2P.hello), 10.seconds) if not validatePubKeyInHello(response, remote.node.pubkey): @@ -1107,7 +1281,7 @@ proc rlpxConnect*(node: EthereumNode, remote: Node): Future[Peer] {.async.} = trace "DevP2P handshake completed", peer = remote, clientId = response.clientId - await postHelloSteps(result, response) + await postHelloSteps(peer, response) ok = true trace "Peer fully connected", peer = remote, clientId = response.clientId except PeerDisconnected as e: @@ -1132,39 +1306,47 @@ proc rlpxConnect*(node: EthereumNode, remote: Node): Future[Peer] {.async.} = err = e.msg if not ok: - if not isNil(result.transport): - result.transport.close() - result = nil + if not isNil(peer.transport): + peer.transport.close() + return nil + else: + return peer proc rlpxAccept*(node: EthereumNode, transport: StreamTransport): Future[Peer] {.async.} = initTracing(devp2pInfo, node.protocols) - new result - result.transport = transport - result.network = node - - var handshake = - Handshake.tryInit(node.rng[], node.keys, {auth.Responder}).tryGet - + let peer = Peer(transport: transport, network: node) + var handshake = Handshake.init(node.rng[], node.keys, {auth.Responder}) var ok = false try: let initialSize = handshake.expectedLength var authMsg = newSeqOfCap[byte](1024) authMsg.setLen(initialSize) + # TODO: Should we not set some timeouts on these `readExactly`s? await transport.readExactly(addr authMsg[0], len(authMsg)) var ret = handshake.decodeAuthMessage(authMsg) if ret.isErr and ret.error == AuthError.IncompleteError: - # Eip8 auth message is likely + # Eip8 auth message is possible, but not likely authMsg.setLen(handshake.expectedLength) await transport.readExactly(addr authMsg[initialSize], len(authMsg) - initialSize) ret = handshake.decodeAuthMessage(authMsg) - ret.tryGet() # for the raise! - node.checkSnappySupport(handshake, result) - handshake.version = uint8(result.baseProtocolVersion) + if ret.isErr(): + # It is likely that errors on the handshake Auth is just garbage arriving + # on the TCP port as it is the first data on the incoming connection, + # hence log them as trace. + trace "rlpxAccept handshake error", error = ret.error + if not isNil(peer.transport): + peer.transport.close() + return nil + + ret.get() + + node.checkSnappySupport(handshake, peer) + handshake.version = uint8(peer.baseProtocolVersion) var ackMsg: array[AckMessageMaxEIP8, byte] var ackMsgLen: int @@ -1174,22 +1356,22 @@ proc rlpxAccept*(node: EthereumNode, raisePeerDisconnected("Unexpected disconnect while authenticating", TcpError) - initSecretState(handshake, authMsg, ^ackMsg, result) + initSecretState(handshake, authMsg, ^ackMsg, peer) let listenPort = transport.localAddress().port - logAcceptedPeer result + logAcceptedPeer peer - var sendHelloFut = result.hello( - result.baseProtocolVersion, + var sendHelloFut = peer.hello( + peer.baseProtocolVersion, node.clientId, node.capabilities, listenPort.uint, node.keys.pubkey.toRaw()) - var response = await result.handshakeImpl( + var response = await peer.handshakeImpl( sendHelloFut, - result.waitSingleMsg(DevP2P.hello), + peer.waitSingleMsg(DevP2P.hello), 10.seconds) trace "Received Hello", version=response.version, id=response.clientId @@ -1200,36 +1382,36 @@ proc rlpxAccept*(node: EthereumNode, let remote = transport.remoteAddress() let address = Address(ip: remote.address, tcpPort: remote.port, udpPort: remote.port) - result.remote = newNode( + peer.remote = newNode( ENode(pubkey: handshake.remoteHPubkey, address: address)) - trace "devp2p handshake completed", peer = result.remote, + trace "devp2p handshake completed", peer = peer.remote, clientId = response.clientId # In case there is an outgoing connection started with this peer we give # precedence to that one and we disconnect here with `AlreadyConnected` - if result.remote in node.peerPool.connectedNodes or - result.remote in node.peerPool.connectingNodes: + if peer.remote in node.peerPool.connectedNodes or + peer.remote in node.peerPool.connectingNodes: trace "Duplicate connection in rlpxAccept" raisePeerDisconnected("Peer already connecting or connected", AlreadyConnected) - node.peerPool.connectingNodes.incl(result.remote) + node.peerPool.connectingNodes.incl(peer.remote) - await postHelloSteps(result, response) + await postHelloSteps(peer, response) ok = true - trace "Peer fully connected", peer = result.remote, clientId = response.clientId + trace "Peer fully connected", peer = peer.remote, clientId = response.clientId except PeerDisconnected as e: case e.reason of AlreadyConnected, TooManyPeers, MessageTimeout: - trace "Disconnect during rlpxAccept", reason = e.reason, peer = result.remote + trace "Disconnect during rlpxAccept", reason = e.reason, peer = peer.remote else: debug "Unexpected disconnect during rlpxAccept", reason = e.reason, - msg = e.msg, peer = result.remote + msg = e.msg, peer = peer.remote except TransportIncompleteError: - trace "Connection dropped in rlpxAccept", remote = result.remote + trace "Connection dropped in rlpxAccept", remote = peer.remote except UselessPeerError: - trace "Disconnecting useless peer", peer = result.remote + trace "Disconnecting useless peer", peer = peer.remote except RlpTypeMismatch: # Some peers report capabilities with names longer than 3 chars. We ignore # those for now. Maybe we should allow this though. @@ -1240,9 +1422,11 @@ proc rlpxAccept*(node: EthereumNode, error "Unexpected exception in rlpxAccept", exc = e.name, err = e.msg if not ok: - if not isNil(result.transport): - result.transport.close() - result = nil + if not isNil(peer.transport): + peer.transport.close() + return nil + else: + return peer when isMainModule: diff --git a/vendor/nim-eth/eth/p2p/rlpx_protocols/bzz_protocol.nim b/vendor/nim-eth/eth/p2p/rlpx_protocols/bzz_protocol.nim deleted file mode 100644 index 49544c4b7..000000000 --- a/vendor/nim-eth/eth/p2p/rlpx_protocols/bzz_protocol.nim +++ /dev/null @@ -1,86 +0,0 @@ -import - chronos, chronicles, - ../../p2p - -# Limited bzz protocol that allows for doing a handshake with a peer running -# ethersphere/swarm client rev. c535b271536d0dee5bd97c2541ca32a42f272d4f - -const - bzzVersion = 12 - hiveVersion = 10 - swarmNetworkId* = 4 - # Faking our capabilities to make handshake work, "bit" 0, 1, 4, 5, 15. - supportedCapabilities = [1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] - -type - # Need object (or extra seq) here as swarm expects list(list(Capability)) - Capabilities = object - caps: seq[Capability] - - Capability = object - id: uint - # Swarm expects here list(bool), thus bool or int (values <= 1 byte, as rlp - # writer has currently no int8 support). Guess this could be a bitvector. - # Also looks like per id the list can have a different size, so lets stick - # with seq instead of array. - value: seq[int] - - OverlayAddress = array[32, byte] - - AddressData = object - oaddr: OverlayAddress - uaddr: string - - Handshake = object - version: uint - networkId: uint - addressData: AddressData - capabilities: Capabilities - - BzzNetwork = ref object - thisENode*: ENode - -p2pProtocol Hive(version = hiveVersion, - rlpxName = "hive"): - - proc peersMsg(peer: Peer) - proc subPeersMsg(peer:Peer) - - onPeerConnected do (peer: Peer): - debug "Hive peer connected" - -proc initProtocolState*(network: BzzNetwork, node: EthereumNode) {.gcsafe.} = - network.thisENode = node.toENode() - -p2pProtocol Bzz(version = bzzVersion, - rlpxName = "bzz", - networkState = BzzNetwork): - - handshake: - proc hs(peer: Peer, hs: Handshake) = - trace "Incoming bzz handshake", version = hs.version, - addressData = hs.addressData - - onPeerConnected do (peer: Peer): - debug "Bzz peer connected" - - # Now all zeroes, this needs to be the Hash of the ECDSA Public Key - # of the used Ethereum account - var oaddr: OverlayAddress - let - # TODO: could do ENode RLP serialisation - # Why do we need to send the ENode? Doesn't the peer already have this? - # Or should it be a different one? - uaddr = $peer.networkState.thisENode - addressData = AddressData(oaddr: oaddr, - uaddr: uaddr) - - caps = Capabilities(caps: @[Capability(id: 0, - value: @supportedCapabilities)]) - handshake = Handshake(version: bzzVersion, - networkId: swarmNetworkId, - addressData: addressData, - capabilities: caps) - - m = await peer.hs(handshake, timeout = chronos.seconds(10)) - # TODO: validate the handshake... diff --git a/vendor/nim-eth/eth/p2p/rlpx_protocols/whisper/whisper_types.nim b/vendor/nim-eth/eth/p2p/rlpx_protocols/whisper/whisper_types.nim index b14fadbb9..2c5dec11a 100644 --- a/vendor/nim-eth/eth/p2p/rlpx_protocols/whisper/whisper_types.nim +++ b/vendor/nim-eth/eth/p2p/rlpx_protocols/whisper/whisper_types.nim @@ -9,7 +9,7 @@ import std/[algorithm, bitops, math, options, tables, times, hashes], - chronicles, stew/[byteutils, endians2], metrics, bearssl, + chronicles, stew/[byteutils, endians2], metrics, nimcrypto/[bcmode, hash, keccak, rijndael], ".."/../../[keys, rlp, p2p], ../../ecies @@ -160,10 +160,8 @@ proc topicBloom*(topic: Topic): Bloom = doAssert idx <= 511 result[idx div 8] = result[idx div 8] or byte(1 shl (idx and 7'u16)) -proc generateRandomID*(rng: var BrHmacDrbgContext): string = - var bytes: array[256 div 8, byte] - brHmacDrbgGenerate(rng, bytes) - toHex(bytes) +proc generateRandomID*(rng: var HmacDrbgContext): string = + toHex(rng.generate(array[256 div 8, byte])) proc `or`(a, b: Bloom): Bloom = for i in 0..= 32: t.prune(data.keccak.data) + if data.len >= 32: t.prune(data.keccakHash.data) proc dbPut(db: DB, data: openArray[byte]): TrieNodeKey {.raises: [Defect].} = - result.hash = data.keccak + result.hash = data.keccakHash result.usedBytes = 32 put(db, result.asDbKey, data) @@ -549,7 +546,7 @@ proc mergeAt(self: var HexaryTrie, orig: Rlp, origHash: KeccakHash, proc mergeAt(self: var HexaryTrie, rlp: Rlp, key: NibblesSeq, value: openArray[byte], isInline = false): seq[byte] = - self.mergeAt(rlp, rlp.rawData.keccak, key, value, isInline) + self.mergeAt(rlp, rlp.rawData.keccakHash, key, value, isInline) proc mergeAtAux(self: var HexaryTrie, output: var RlpWriter, orig: Rlp, key: NibblesSeq, value: openArray[byte]) = @@ -662,13 +659,13 @@ proc put*(self: var HexaryTrie; key, value: openArray[byte]) = self.root = self.db.dbPut(newRootBytes) proc put*(self: var SecureHexaryTrie; key, value: openArray[byte]) = - put(HexaryTrie(self), key.keccak.data, value) + put(HexaryTrie(self), key.keccakHash.data, value) proc get*(self: SecureHexaryTrie; key: openArray[byte]): seq[byte] = - return get(HexaryTrie(self), key.keccak.data) + return get(HexaryTrie(self), key.keccakHash.data) proc del*(self: var SecureHexaryTrie; key: openArray[byte]) = - del(HexaryTrie(self), key.keccak.data) + del(HexaryTrie(self), key.keccakHash.data) proc rootHash*(self: SecureHexaryTrie): KeccakHash {.borrow.} proc rootHashHex*(self: SecureHexaryTrie): string {.borrow.} @@ -686,7 +683,7 @@ proc isValidBranch*(branch: seq[seq[byte]], rootHash: KeccakHash, key, value: se var db = newMemoryDB() for node in branch: doAssert(node.len != 0) - let nodeHash = hexary.keccak(node) + let nodeHash = keccakHash(node) db.put(nodeHash.data, node) var trie = initHexaryTrie(db, rootHash) diff --git a/vendor/nim-eth/eth/trie/sparse_proofs.nim b/vendor/nim-eth/eth/trie/sparse_proofs.nim index c72a689f8..14c3edaa9 100644 --- a/vendor/nim-eth/eth/trie/sparse_proofs.nim +++ b/vendor/nim-eth/eth/trie/sparse_proofs.nim @@ -29,9 +29,9 @@ proc verifyProofAux*(proof: seq[seq[byte]], root, key, value: openArray[byte]): if node.len != 32: return false if path[i]: # right # reuse curHash without more alloc - curHash.data.keccakHash(node, curHash.data) + curHash = keccakHash(node, curHash.data) else: - curHash.data.keccakHash(curHash.data, node) + curHash = keccakHash(curHash.data, node) result = curHash.data == root diff --git a/vendor/nim-eth/eth/trie/trie_defs.nim b/vendor/nim-eth/eth/trie/trie_defs.nim index 9a317e178..df0c137bf 100644 --- a/vendor/nim-eth/eth/trie/trie_defs.nim +++ b/vendor/nim-eth/eth/trie/trie_defs.nim @@ -1,10 +1,9 @@ import - nimcrypto/hash, - ../rlp + ../common/eth_hash_rlp + +export eth_hash_rlp type - KeccakHash* = MDigest[256] - TrieError* = object of CatchableError # A common base type of all Trie errors. @@ -21,9 +20,3 @@ const blankStringHash* = "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470".toDigest emptyRlp* = @[128.byte] emptyRlpHash* = "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".toDigest - -proc read*(rlp: var Rlp, T: typedesc[MDigest]): T {.inline.} = - result.data = rlp.read(type(result.data)) - -proc append*(rlpWriter: var RlpWriter, a: MDigest) {.inline.} = - rlpWriter.append(a.data) diff --git a/vendor/nim-eth/eth/trie/trie_utils.nim b/vendor/nim-eth/eth/trie/trie_utils.nim index 7bb8e2c3c..e87a85a3f 100644 --- a/vendor/nim-eth/eth/trie/trie_utils.nim +++ b/vendor/nim-eth/eth/trie/trie_utils.nim @@ -1,8 +1,9 @@ import stew/byteutils, - nimcrypto/[hash, keccak], ./trie_defs +export trie_defs + template checkValidHashZ*(x: untyped) = when x.type isnot KeccakHash: doAssert(x.len == 32 or x.len == 0) @@ -14,21 +15,3 @@ proc hashFromHex*(bits: static[int], input: string): MDigest[bits] = MDigest(data: hexToByteArray[bits div 8](input)) template hashFromHex*(s: static[string]): untyped = hashFromHex(s.len * 4, s) - -proc keccakHash*(input: openArray[byte]): KeccakHash = - keccak256.digest(input) - -proc keccakHash*(dest: var openArray[byte], a, b: openArray[byte]) = - var ctx: keccak256 - ctx.init() - if a.len != 0: - ctx.update(a[0].unsafeAddr, uint(a.len)) - if b.len != 0: - ctx.update(b[0].unsafeAddr, uint(b.len)) - ctx.finish dest - ctx.clear() - -proc keccakHash*(a, b: openArray[byte]): KeccakHash = - var s: array[32, byte] - keccakHash(s, a, b) - KeccakHash(data: s) diff --git a/vendor/nim-eth/eth/utp/growable_buffer.nim b/vendor/nim-eth/eth/utp/growable_buffer.nim index 0babfafbf..093ce5bda 100644 --- a/vendor/nim-eth/eth/utp/growable_buffer.nim +++ b/vendor/nim-eth/eth/utp/growable_buffer.nim @@ -5,7 +5,7 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. import - std/[options, math, sugar] + std/[options, math] export options @@ -19,32 +19,32 @@ export options type GrowableCircularBuffer*[A] = object items: seq[Option[A]] - mask: int + mask: uint32 # provided size will always be adjusted to next power of two -proc init*[A](T: type GrowableCircularBuffer[A], size: Natural = 16): T = - let powOfTwoSize = nextPowerOfTwo(size) +proc init*[A](T: type GrowableCircularBuffer[A], size: uint32 = 16): T = + let powOfTwoSize = nextPowerOfTwo(int(size)) T( - items: newSeq[Option[A]](size), - mask: powOfTwoSize - 1 + items: newSeq[Option[A]](powOfTwoSize), + mask: uint32(powOfTwoSize - 1) ) -proc get*[A](buff: GrowableCircularBuffer[A], i: Natural): Option[A] = +proc get*[A](buff: GrowableCircularBuffer[A], i: uint32): Option[A] = buff.items[i and buff.mask] -proc putImpl[A](buff: var GrowableCircularBuffer[A], i: Natural, elem: Option[A]) = +proc putImpl[A](buff: var GrowableCircularBuffer[A], i: uint32, elem: Option[A]) = buff.items[i and buff.mask] = elem -proc put*[A](buff: var GrowableCircularBuffer[A], i: Natural, elem: A) = +proc put*[A](buff: var GrowableCircularBuffer[A], i: uint32, elem: A) = buff.putImpl(i, some(elem)) -proc delete*[A](buff: var GrowableCircularBuffer[A], i: Natural) = +proc delete*[A](buff: var GrowableCircularBuffer[A], i: uint32) = buff.putImpl(i, none[A]()) -proc hasKey*[A](buff: GrowableCircularBuffer[A], i: Natural): bool = +proc hasKey*[A](buff: GrowableCircularBuffer[A], i: uint32): bool = buff.get(i).isSome() -proc exists*[A](buff: GrowableCircularBuffer[A], i: Natural, check: proc (x: A): bool): bool = +proc exists*[A](buff: GrowableCircularBuffer[A], i: uint32, check: proc (x: A): bool): bool = let maybeElem = buff.get(i) if (maybeElem.isSome()): let elem = maybeElem.unsafeGet() @@ -52,32 +52,33 @@ proc exists*[A](buff: GrowableCircularBuffer[A], i: Natural, check: proc (x: A): else: false -proc `[]`*[A](buff: var GrowableCircularBuffer[A], i: Natural): var A = +proc `[]`*[A](buff: var GrowableCircularBuffer[A], i: uint32): var A = ## Returns contents of the `var GrowableCircularBuffer`. If it is not set, then an exception ## is thrown. buff.items[i and buff.mask].get() proc len*[A](buff: GrowableCircularBuffer[A]): int = - buff.mask + 1 + int(buff.mask) + 1 + +proc calculateNextMask(currentMask: uint32, index:uint32): uint32 = + # Increase mask,so that index will fit in buffer size i.e mask + 1 + if currentMask == uint32.high: + return currentMask + + var newSize = currentMask + 1 + while true: + newSize = newSize * 2 + if newSize == 0 or index < newSize: + break + return newSize - 1 # Item contains the element we want to make space for # index is the index in the list. -proc ensureSize*[A](buff: var GrowableCircularBuffer[A], item: Natural, index: Natural) = - # Increase size until is next power of 2 which consists given index - proc getNextSize(currentSize: int, index: int): int = - var newSize = currentSize - while true: - newSize = newSize * 2 - if not (index >= newSize): - break - newSize - +proc ensureSize*[A](buff: var GrowableCircularBuffer[A], item: uint32, index: uint32) = if (index > buff.mask): - let currentSize = buff.mask + 1 - let newSize = getNextSize(currentSize, index) - let newMask = newSize - 1 - var newSeq = newSeq[Option[A]](newSize) - var i = 0 + let newMask = calculateNextMask(buff.mask, index) + var newSeq = newSeq[Option[A]](int(newMask) + 1) + var i = 0'u32 while i <= buff.mask: let idx = item - index + i newSeq[idx and newMask] = buff.get(idx) diff --git a/vendor/nim-eth/eth/utp/packets.nim b/vendor/nim-eth/eth/utp/packets.nim index 79031af22..067fb27cb 100644 --- a/vendor/nim-eth/eth/utp/packets.nim +++ b/vendor/nim-eth/eth/utp/packets.nim @@ -7,13 +7,12 @@ {.push raises: [Defect].} import - std/[monotimes], faststreams, chronos, - stew/[endians2, results, objects, arrayops], bearssl, + stew/[endians2, results, objects], ../p2p/discoveryv5/random2 -export results +export results, random2 const minimalHeaderSize = 20 @@ -80,11 +79,11 @@ proc getMonoTimestamp*(): TimeStampInfo = TimeStampInfo(moment: currentMoment, timestamp: timestamp) # Simple generator, not useful for cryptography -proc randUint16*(rng: var BrHmacDrbgContext): uint16 = +proc randUint16*(rng: var HmacDrbgContext): uint16 = uint16(rand(rng, int(high(uint16)))) # Simple generator, not useful for cryptography -proc randUint32*(rng: var BrHmacDrbgContext): uint32 = +proc randUint32*(rng: var HmacDrbgContext): uint32 = uint32(rand(rng, int(high(uint32)))) proc encodeTypeVer(h: PacketHeaderV1): uint8 = diff --git a/vendor/nim-eth/eth/utp/utp_discv5_protocol.nim b/vendor/nim-eth/eth/utp/utp_discv5_protocol.nim index 3cdc906e6..84df816f6 100644 --- a/vendor/nim-eth/eth/utp/utp_discv5_protocol.nim +++ b/vendor/nim-eth/eth/utp/utp_discv5_protocol.nim @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Status Research & Development GmbH +# Copyright (c) 2021-2022 Status Research & Development GmbH # Licensed and distributed under either of # * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). # * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). @@ -13,12 +13,12 @@ import ./utp_router, ../keys -export utp_router, protocol, chronicles +export utp_router, protocol logScope: topics = "utp_discv5_protocol" -type +type NodeAddress* = object nodeId*: NodeId address*: Address @@ -27,10 +27,10 @@ type prot: protocol.Protocol router: UtpRouter[NodeAddress] -proc init*(T: type NodeAddress, nodeId: NodeId, address: Address): NodeAddress = +proc init*(T: type NodeAddress, nodeId: NodeId, address: Address): NodeAddress = NodeAddress(nodeId: nodeId, address: address) -proc init*(T: type NodeAddress, node: Node): Option[NodeAddress] = +proc init*(T: type NodeAddress, node: Node): Option[NodeAddress] = node.address.map((address: Address) => NodeAddress(nodeId: node.id, address: address)) proc hash(x: NodeAddress): Hash = @@ -48,7 +48,7 @@ proc hash(x: UtpSocketKey[NodeAddress]): Hash = func `$`*(x: UtpSocketKey[NodeAddress]): string = "(remoteId: " & $x.remoteAddress.nodeId & ", remoteAddress: " & $x.remoteAddress.address & - ", rcvId: "& $x.rcvId & + ", rcvId: " & $x.rcvId & ")" proc talkReqDirect(p: protocol.Protocol, n: NodeAddress, protocol, request: seq[byte]): Future[void] = @@ -60,7 +60,7 @@ proc talkReqDirect(p: protocol.Protocol, n: NodeAddress, protocol, request: seq[ trace "Send message packet", dstId = n.nodeId, address = n.address, kind = MessageKind.talkreq p.send(n.address, data) - + proc initSendCallback( t: protocol.Protocol, subProtocolName: seq[byte]): SendCallback[NodeAddress] = return ( @@ -77,7 +77,7 @@ proc initSendCallback( proc messageHandler(protocol: TalkProtocol, request: seq[byte], srcId: NodeId, srcUdpAddress: Address): seq[byte] = - let + let p = UtpDiscv5Protocol(protocol) nodeAddress = NodeAddress.init(srcId, srcUdpAddress) debug "Received utp payload from known node. Start processing", @@ -89,6 +89,7 @@ proc new*( p: protocol.Protocol, subProtocolName: seq[byte], acceptConnectionCb: AcceptConnectionCallback[NodeAddress], + udata: pointer = nil, allowConnectionCb: AllowConnectionCallback[NodeAddress] = nil, socketConfig: SocketConfig = SocketConfig.init()): UtpDiscv5Protocol = doAssert(not(isNil(acceptConnectionCb))) @@ -96,6 +97,7 @@ proc new*( let router = UtpRouter[NodeAddress].new( acceptConnectionCb, allowConnectionCb, + udata, socketConfig, p.rng ) @@ -112,6 +114,24 @@ proc new*( ) prot +proc new*( + T: type UtpDiscv5Protocol, + p: protocol.Protocol, + subProtocolName: seq[byte], + acceptConnectionCb: AcceptConnectionCallback[NodeAddress], + udata: ref, + allowConnectionCb: AllowConnectionCallback[NodeAddress] = nil, + socketConfig: SocketConfig = SocketConfig.init()): UtpDiscv5Protocol = + GC_ref(udata) + UtpDiscv5Protocol.new( + p, + subProtocolName, + acceptConnectionCb, + cast[pointer](udata), + allowConnectionCb, + socketConfig + ) + proc connectTo*(r: UtpDiscv5Protocol, address: NodeAddress): Future[ConnectionResult[NodeAddress]] = return r.router.connectTo(address) diff --git a/vendor/nim-eth/eth/utp/utp_protocol.nim b/vendor/nim-eth/eth/utp/utp_protocol.nim index ab85841f3..332b462d9 100644 --- a/vendor/nim-eth/eth/utp/utp_protocol.nim +++ b/vendor/nim-eth/eth/utp/utp_protocol.nim @@ -7,8 +7,8 @@ {.push raises: [Defect].} import - std/[tables, options, hashes, sugar, math], - chronos, chronicles, bearssl, + std/[tables, options, hashes, math], + chronos, chronicles, ./utp_router, ../keys @@ -75,19 +75,21 @@ proc initSendCallback(t: DatagramTransport): SendCallback[TransportAddress] = ) proc new*( - T: type UtpProtocol, - acceptConnectionCb: AcceptConnectionCallback[TransportAddress], - address: TransportAddress, - socketConfig: SocketConfig = SocketConfig.init(), - allowConnectionCb: AllowConnectionCallback[TransportAddress] = nil, - sendCallbackBuilder: SendCallbackBuilder = nil, - rng = newRng()): UtpProtocol {.raises: [Defect, CatchableError].} = + T: type UtpProtocol, + acceptConnectionCb: AcceptConnectionCallback[TransportAddress], + address: TransportAddress, + udata: pointer = nil, + socketConfig: SocketConfig = SocketConfig.init(), + allowConnectionCb: AllowConnectionCallback[TransportAddress] = nil, + sendCallbackBuilder: SendCallbackBuilder = nil, + rng = newRng()): UtpProtocol {.raises: [Defect, CatchableError].} = doAssert(not(isNil(acceptConnectionCb))) let router = UtpRouter[TransportAddress].new( acceptConnectionCb, allowConnectionCb, + udata, socketConfig, rng ) @@ -101,6 +103,26 @@ proc new*( UtpProtocol(transport: ta, utpRouter: router) +proc new*( + T: type UtpProtocol, + acceptConnectionCb: AcceptConnectionCallback[TransportAddress], + address: TransportAddress, + udata: ref, + socketConfig: SocketConfig = SocketConfig.init(), + allowConnectionCb: AllowConnectionCallback[TransportAddress] = nil, + sendCallbackBuilder: SendCallbackBuilder = nil, + rng = newRng()): UtpProtocol {.raises: [Defect, CatchableError].} = + GC_ref(udata) + UtpProtocol.new( + acceptConnectionCb, + address, + cast[pointer](udata), + socketConfig, + allowConnectionCb, + sendCallbackBuilder, + rng + ) + proc shutdownWait*(p: UtpProtocol): Future[void] {.async.} = ## closes all managed utp sockets and then underlying transport await p.utpRouter.shutdownWait() diff --git a/vendor/nim-eth/eth/utp/utp_router.nim b/vendor/nim-eth/eth/utp/utp_router.nim index 2a5fb646b..e6d690a7f 100644 --- a/vendor/nim-eth/eth/utp/utp_router.nim +++ b/vendor/nim-eth/eth/utp/utp_router.nim @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Status Research & Development GmbH +# Copyright (c) 2021-2022 Status Research & Development GmbH # Licensed and distributed under either of # * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). # * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). @@ -8,15 +8,30 @@ import std/[tables, options, sugar], - chronos, bearssl, chronicles, + chronos, chronicles, metrics, ../keys, ./utp_socket, ./packets +export utp_socket + logScope: topics = "utp_router" -export utp_socket +declareCounter utp_received_packets, + "All correct received uTP packets" +declareCounter utp_failed_packets, + "All received uTP packets which failed decoding" +declareGauge utp_established_connections, + "Current number of established uTP sockets" +declareCounter utp_allowed_incoming, + "Total number of allowed incoming connections" +declareCounter utp_declined_incoming, + "Total number of declined incoming connections" +declareCounter utp_success_outgoing, + "Total number of succesful outgoing connections" +declareCounter utp_failed_outgoing, + "Total number of failed outgoing connections" type # New remote client connection callback @@ -41,7 +56,8 @@ type closed: bool sendCb*: SendCallback[A] allowConnection*: AllowConnectionCallback[A] - rng*: ref BrHmacDrbgContext + udata: pointer + rng*: ref HmacDrbgContext const # Maximal number of tries to generate unique socket while establishing @@ -66,6 +82,8 @@ proc getUtpSocket[A](s: UtpRouter[A], k: UtpSocketKey[A]): Option[UtpSocket[A]] proc deRegisterUtpSocket[A](s: UtpRouter[A], socket: UtpSocket[A]) = s.sockets.del(socket.socketKey) + utp_established_connections.set(int64(len(s.sockets))) + debug "Removed utp socket", dst = socket.socketKey, lenSockets = len(s.sockets) iterator allSockets[A](s: UtpRouter[A]): UtpSocket[A] = for socket in s.sockets.values(): @@ -78,6 +96,8 @@ proc len*[A](s: UtpRouter[A]): int = proc registerUtpSocket[A](p: UtpRouter, s: UtpSocket[A]) = ## Register socket, overwriting already existing one p.sockets[s.socketKey] = s + utp_established_connections.set(int64(len(p.sockets))) + debug "Registered new utp socket", dst = s.socketKey, lenSockets = len(p.sockets) # Install deregister handler, so when socket gets closed, in will be promptly # removed from open sockets table s.registerCloseCallback(proc () = p.deRegisterUtpSocket(s)) @@ -95,6 +115,7 @@ proc new*[A]( T: type UtpRouter[A], acceptConnectionCb: AcceptConnectionCallback[A], allowConnectionCb: AllowConnectionCallback[A], + udata: pointer, socketConfig: SocketConfig = SocketConfig.init(), rng = newRng()): UtpRouter[A] = doAssert(not(isNil(acceptConnectionCb))) @@ -103,6 +124,7 @@ proc new*[A]( acceptConnection: acceptConnectionCb, allowConnection: allowConnectionCb, socketConfig: socketConfig, + udata: udata, rng: rng ) @@ -111,11 +133,35 @@ proc new*[A]( acceptConnectionCb: AcceptConnectionCallback[A], socketConfig: SocketConfig = SocketConfig.init(), rng = newRng()): UtpRouter[A] = - UtpRouter[A].new(acceptConnectionCb, nil, socketConfig, rng) + UtpRouter[A].new(acceptConnectionCb, nil, nil, socketConfig, rng) + +proc new*[A]( + T: type UtpRouter[A], + acceptConnectionCb: AcceptConnectionCallback[A], + allowConnectionCb: AllowConnectionCallback[A], + udata: ref, + socketConfig: SocketConfig = SocketConfig.init(), + rng = newRng()): UtpRouter[A] = + doAssert(not(isNil(acceptConnectionCb))) + GC_ref(udata) + UtpRouter[A].new(acceptConnectionCb, allowConnectionCb, cast[pointer](udata), socketConfig, rng) + +proc new*[A]( + T: type UtpRouter[A], + acceptConnectionCb: AcceptConnectionCallback[A], + udata: ref, + socketConfig: SocketConfig = SocketConfig.init(), + rng = newRng()): UtpRouter[A] = + UtpRouter[A].new(acceptConnectionCb, nil, udata, socketConfig, rng) + +proc getUserData*[A, T](router: UtpRouter[A]): T = + ## Obtain user data stored in ``router`` object. + cast[T](router.udata) # There are different possibilities on how the connection got established, need # to check every case. -proc getSocketOnReset[A](r: UtpRouter[A], sender: A, id: uint16): Option[UtpSocket[A]] = +proc getSocketOnReset[A]( + r: UtpRouter[A], sender: A, id: uint16): Option[UtpSocket[A]] = # id is our recv id let recvKey = UtpSocketKey[A].init(sender, id) @@ -129,7 +175,8 @@ proc getSocketOnReset[A](r: UtpRouter[A], sender: A, id: uint16): Option[UtpSock .orElse(r.getUtpSocket(sendInitKey).filter(s => s.connectionIdSnd == id)) .orElse(r.getUtpSocket(sendNoInitKey).filter(s => s.connectionIdSnd == id)) -proc shouldAllowConnection[A](r: UtpRouter[A], remoteAddress: A, connectionId: uint16): bool = +proc shouldAllowConnection[A]( + r: UtpRouter[A], remoteAddress: A, connectionId: uint16): bool = if r.allowConnection == nil: # if the callback is not configured it means all incoming connections are allowed true @@ -162,19 +209,30 @@ proc processPacket[A](r: UtpRouter[A], p: Packet, sender: A) {.async.}= if (maybeSocket.isSome()): debug "Ignoring SYN for already existing connection" else: + if (len(r.sockets) >= r.socketConfig.maxNumberOfOpenConnections): + debug "New incoming connection not allowed due to connection limit", + lenConnections = len(r.sockets), + limit = r.socketConfig.maxNumberOfOpenConnections + + utp_declined_incoming.inc() + return + if (r.shouldAllowConnection(sender, p.header.connectionId)): debug "Received SYN for new connection. Initiating incoming connection", synSeqNr = p.header.seqNr # Initial ackNr is set to incoming packer seqNr - let incomingSocket = newIncomingSocket[A](sender, r.sendCb, r.socketConfig ,p.header.connectionId, p.header.seqNr, r.rng[]) + let incomingSocket = newIncomingSocket[A]( + sender, r.sendCb, r.socketConfig, + p.header.connectionId, p.header.seqNr, r.rng[]) r.registerUtpSocket(incomingSocket) incomingSocket.startIncomingSocket() - # Based on configuration, socket is passed to upper layer either in SynRecv - # or Connected state - info "Accepting incoming connection", - to = incomingSocket.socketKey + # Based on configuration, socket is passed to upper layer either in + # SynRecv or Connected state + utp_allowed_incoming.inc() + debug "Accepting incoming connection", src = incomingSocket.socketKey asyncSpawn r.acceptConnection(r, incomingSocket) else: + utp_declined_incoming.inc() debug "Connection declined" else: let socketKey = UtpSocketKey[A].init(sender, p.header.connectionId) @@ -184,28 +242,34 @@ proc processPacket[A](r: UtpRouter[A], p: Packet, sender: A) {.async.}= let socket = maybeSocket.unsafeGet() await socket.processPacket(p) else: - # TODO add keeping track of recently send reset packets and do not send reset - # to peers which we recently send reset to. + # TODO add keeping track of recently send reset packets and do not send + # reset to peers which we recently send reset to. debug "Received FIN/DATA/ACK on not known socket sending reset" - let rstPacket = resetPacket(randUint16(r.rng[]), p.header.connectionId, p.header.seqNr) + let rstPacket = resetPacket( + randUint16(r.rng[]), p.header.connectionId, p.header.seqNr) await r.sendCb(sender, encodePacket(rstPacket)) -proc processIncomingBytes*[A](r: UtpRouter[A], bytes: seq[byte], sender: A) {.async.} = +proc processIncomingBytes*[A]( + r: UtpRouter[A], bytes: seq[byte], sender: A) {.async.} = if (not r.closed): - let dec = decodePacket(bytes) - if (dec.isOk()): - await processPacket[A](r, dec.get(), sender) + let decoded = decodePacket(bytes) + if (decoded.isOk()): + utp_received_packets.inc() + await processPacket[A](r, decoded.get(), sender) else: - let err = dec.error() - warn "failed to decode packet from address", address = sender, msg = err + utp_failed_packets.inc() + let err = decoded.error() + warn "Failed to decode packet from address", address = sender, msg = err -proc generateNewUniqueSocket[A](r: UtpRouter[A], address: A): Option[UtpSocket[A]] = - ## Tries to generate unique socket, gives up after maxSocketGenerationTries tries +proc generateNewUniqueSocket[A]( + r: UtpRouter[A], address: A):Option[UtpSocket[A]] = + ## Try to generate unique socket, give up after maxSocketGenerationTries tries var tryCount = 0 while tryCount < maxSocketGenerationTries: let rcvId = randUint16(r.rng[]) - let socket = newOutgoingSocket[A](address, r.sendCb, r.socketConfig, rcvId, r.rng[]) + let socket = newOutgoingSocket[A]( + address, r.sendCb, r.socketConfig, rcvId, r.rng[]) if r.registerIfAbsent(socket): return some(socket) @@ -214,52 +278,79 @@ proc generateNewUniqueSocket[A](r: UtpRouter[A], address: A): Option[UtpSocket[A return none[UtpSocket[A]]() -proc connect[A](s: UtpSocket[A]): Future[ConnectionResult[A]] {.async.}= - info "Initiating connection", - to = s.socketKey - +proc innerConnect[A](s: UtpSocket[A]): Future[ConnectionResult[A]] {.async.} = let startFut = s.startOutgoingSocket() - startFut.cancelCallback = proc(udata: pointer) {.gcsafe.} = - # if for some reason future will be cancelled, destory socket to clear it from - # active socket list - s.destroy() - try: await startFut - info "Outgoing connection successful", - to = s.socketKey + utp_success_outgoing.inc() + debug "Outgoing connection successful", dst = s.socketKey return ok(s) except ConnectionError: - info "Outgoing connection timed-out", - to = s.socketKey + utp_failed_outgoing.inc() + debug "Outgoing connection timed-out", dst = s.socketKey s.destroy() return err(OutgoingConnectionError(kind: ConnectionTimedOut)) + except CancelledError as exc: + s.destroy() + debug "Connection cancelled", dst = s.socketKey + raise exc + +proc connect[A](s: UtpSocket[A]): Future[ConnectionResult[A]] = + debug "Initiating connection", dst = s.socketKey + + # Create inner future, to make sure we are installing cancelCallback + # on whole connection future, and not only part of it + let connectionFuture = s.innerConnect() + + connectionFuture.cancelCallback = proc(udata: pointer) {.gcsafe.} = + debug "Connection cancel callback fired", + socketKey = s.socketKey + # if for some reason the future is cancelled, destroy socket to clear it + # from the active socket list + s.destroy() + + return connectionFuture + +proc socketAlreadyExists[A](): ConnectionResult[A] = + return err(OutgoingConnectionError(kind: SocketAlreadyExists)) + +proc socketAlreadyExistsFut[A](): Future[ConnectionResult[A]] = + let fut = newFuture[ConnectionResult[A]]() + fut.complete(socketAlreadyExists[A]()) + return fut # Connect to provided address -# Reference implementation: https://github.com/bittorrent/libutp/blob/master/utp_internal.cpp#L2732 -proc connectTo*[A](r: UtpRouter[A], address: A): Future[ConnectionResult[A]] {.async.} = +# Reference implementation: +# https://github.com/bittorrent/libutp/blob/master/utp_internal.cpp#L2732 +proc connectTo*[A]( + r: UtpRouter[A], address: A): Future[ConnectionResult[A]] = let maybeSocket = r.generateNewUniqueSocket(address) if (maybeSocket.isNone()): - return err(OutgoingConnectionError(kind: SocketAlreadyExists)) + return socketAlreadyExistsFut[A]() else: let socket = maybeSocket.unsafeGet() - return await socket.connect() + let connFut = socket.connect() + return connFut # Connect to provided address with provided connection id, if socket with this id # and address already exsits return error -proc connectTo*[A](r: UtpRouter[A], address: A, connectionId: uint16): Future[ConnectionResult[A]] {.async.} = - let socket = newOutgoingSocket[A](address, r.sendCb, r.socketConfig, connectionId, r.rng[]) +proc connectTo*[A]( + r: UtpRouter[A], address: A, connectionId: uint16): + Future[ConnectionResult[A]] = + let socket = newOutgoingSocket[A]( + address, r.sendCb, r.socketConfig, connectionId, r.rng[]) if (r.registerIfAbsent(socket)): - return await socket.connect() + let connFut = socket.connect() + return connFut else: - return err(OutgoingConnectionError(kind: SocketAlreadyExists)) + return socketAlreadyExistsFut[A]() proc shutdown*[A](r: UtpRouter[A]) = # stop processing any new packets and close all sockets in background without - # notifing remote peers + # notifying remote peers r.closed = true for s in r.allSockets(): s.destroy() @@ -267,12 +358,12 @@ proc shutdown*[A](r: UtpRouter[A]) = proc shutdownWait*[A](r: UtpRouter[A]) {.async.} = var activeSockets: seq[UtpSocket[A]] = @[] # stop processing any new packets and close all sockets without - # notifing remote peers + # notifying remote peers r.closed = true - # we need to make copy as calling socket.destroyWait() removes socket from the table - # and iterator throws error. Antother option would be to wait until number of opensockets - # go to 0 + # Need to make a copy as calling socket.destroyWait() removes the socket from + # the table and iterator throws error. Another option would be to wait until + # the number of open sockets drops to 0 for s in r.allSockets(): activeSockets.add(s) diff --git a/vendor/nim-eth/eth/utp/utp_socket.nim b/vendor/nim-eth/eth/utp/utp_socket.nim index 10acbd5d7..5202a815d 100644 --- a/vendor/nim-eth/eth/utp/utp_socket.nim +++ b/vendor/nim-eth/eth/utp/utp_socket.nim @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Status Research & Development GmbH +# Copyright (c) 2021-2022 Status Research & Development GmbH # Licensed and distributed under either of # * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). # * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). @@ -8,7 +8,7 @@ import std/[sugar, deques], - chronos, chronicles, bearssl, + chronos, chronicles, stew/[results, bitops2], ./growable_buffer, ./packets, @@ -80,6 +80,18 @@ type # Size of reorder buffer calculated as fraction of optRcvBuffer maxSizeOfReorderBuffer: uint32 + # Maximal number of payload bytes per data packet. Total packet size will be equal to + # payloadSize + 20 (size of header of data packet) + # TODO for now we enable only static configuration of packet sizes. In the future + # it would be nice to add option which enables automatic packet size discovery + # based on traffic + payloadSize*: uint32 + + # Maximal number of open uTP connections. When hit, no more incoming connections + # will be allowed, but it will still be possible to open new outgoing uTP + # connections + maxNumberOfOpenConnections*: int + WriteErrorType* = enum SocketNotWriteable, FinSent @@ -196,7 +208,7 @@ type # current size of rcv buffer offset: int - + # readers waiting for data pendingReads: Deque[ReadReq] @@ -297,11 +309,16 @@ type ConnectionResult*[A] = Result[UtpSocket[A], OutgoingConnectionError] const - # Maximal number of payload bytes per packet. Total packet size will be equal to - # mtuSize + sizeof(header) = 600 bytes - # TODO for now it is just some random value. Ultimatly this value should be dynamically - # adjusted based on traffic. - mtuSize = 580 + # Default maximum size of the data packet payload. With such configuration + # data packets will have 508 bytes (488 + 20 header). + # 508 bytes of udp payload can translate into 576 bytes udp packet i.e + # 508bytes paylaod + 60bytes (max ip header) + 8bytes (udp header) = 576bytes. + # 576bytes is defined as minimum reassembly buffer size i.e + # the minimum datagram size that we are guaranteed any implementation must support. + # from RFC791: All hosts must be prepared + # to accept datagrams of up to 576 octets (whether they arrive whole + # or in fragments). + defaultPayloadSize = 488 # How often each socket check its different on going timers checkTimeoutsLoopInterval = milliseconds(500) @@ -334,22 +351,10 @@ const allowedAckWindow*: uint16 = 3 # Timeout after which the send window will be reset to its minimal value after it dropped - # lower than our current packet size. i.e when we received a packet + # lower than our current packet size. i.e when we received a packet # from remote peer with `wndSize` set to number <= current packet size defaultResetWindowTimeout = seconds(15) - # If remote peer window drops to zero, then after some time we will reset it - # to this value even if we do not receive any more messages from remote peers. - # Reset period is configured in `SocketConfig` - minimalRemoteWindow: uint32 = 1500 - - # Initial max window size. Reference implementation uses value which enables one packet - # to be transfered. - # We use value two times higher as we do not yet have proper mtu estimation, and - # our impl should work over udp and discovery v5 (where proper estmation may be harder - # as packets already have discvoveryv5 envelope) - startMaxWindow* = 2 * mtuSize - reorderBufferMaxSize = 1024 duplicateAcksBeforeResend = 3 @@ -357,7 +362,7 @@ const # minimal time before subseqent window decays maxWindowDecay = milliseconds(100) - # Maximal size of reorder buffer as fraction of optRcvBuffer size following + # Maximal size of reorder buffer as fraction of optRcvBuffer size following # semantics apply bases on rcvBuffer set to 1000 bytes: # if there are already 1000 bytes in rcv buffer no more bytes will be accepted to reorder buffer # if there are already 500 bytes in reoreder buffer, no more bytes will be accepted @@ -366,6 +371,10 @@ const # happens maxReorderBufferSize = 0.5 + # Default number of of open utp connections + # libutp uses 3000 + # libtorrent uses ~16000 + defaultMaxOpenConnections = 8000 proc init*[A](T: type UtpSocketKey, remoteAddress: A, rcvId: uint16): T = UtpSocketKey[A](remoteAddress: remoteAddress, rcvId: rcvId) @@ -392,8 +401,13 @@ proc init*( optRcvBuffer: uint32 = defaultOptRcvBuffer, incomingSocketReceiveTimeout: Option[Duration] = some(defaultRcvRetransmitTimeout), remoteWindowResetTimeout: Duration = defaultResetWindowTimeout, - optSndBuffer: uint32 = defaultOptRcvBuffer + optSndBuffer: uint32 = defaultOptRcvBuffer, + payloadSize: uint32 = defaultPayloadSize, + maxNumberOfOpenConnections: int = defaultMaxOpenConnections ): T = + # make sure there is always some payload in data packets, and that packets are not to large. + # with 1480 packet boundary, data packets will have 1500 bytes which seems reasonable + doAssert(payloadSize > 0 and payloadSize <= 1480, "payloadSize should always be positive number <= 1480") # TODO make sure optRcvBuffer is nicely divisible by maxReorderBufferSize let reorderBufferSize = uint32(maxReorderBufferSize * float64(optRcvBuffer)) SocketConfig( @@ -403,11 +417,13 @@ proc init*( optSndBuffer: optSndBuffer, incomingSocketReceiveTimeout: incomingSocketReceiveTimeout, remoteWindowResetTimeout: remoteWindowResetTimeout, - maxSizeOfReorderBuffer: reorderBufferSize + maxSizeOfReorderBuffer: reorderBufferSize, + payloadSize: payloadSize, + maxNumberOfOpenConnections: maxNumberOfOpenConnections ) # number of bytes which will fit in current send window -proc freeWindowBytes(socket: UtpSocket): uint32 = +proc freeWindowBytes(socket: UtpSocket): uint32 = let maxSend = min(socket.maxRemoteWindow, socket.maxWindow) if (maxSend <= socket.currentWindow): return 0 @@ -435,7 +451,7 @@ proc sendData(socket: UtpSocket, data: seq[byte]) = if f.failed: warn "UTP send failed", msg = f.readError.msg -proc sendPacket(socket: UtpSocket, seqNr: uint16) = +proc sendPacket(socket: UtpSocket, seqNr: uint16) = proc setSend(p: var OutgoingPacket): seq[byte] = let timestampInfo = getMonoTimestamp() @@ -450,9 +466,9 @@ proc sendPacket(socket: UtpSocket, seqNr: uint16) = modifyTimeStampAndAckNr(p.packetBytes, timestampInfo.timestamp, socket.ackNr) return p.packetBytes - + socket.sendData(setSend(socket.outBuffer[seqNr])) - + proc resetSendTimeout(socket: UtpSocket) = socket.retransmitTimeout = socket.rto socket.rtoTimeout = getMonoTimestamp().moment + socket.retransmitTimeout @@ -515,15 +531,17 @@ proc checkTimeouts(socket: UtpSocket) = socket.flushPackets() if socket.isOpened(): - let currentPacketSize = uint32(socket.getPacketSize()) + let currentPacketSize = socket.getPacketSize() if (socket.zeroWindowTimer.isSome() and currentTime > socket.zeroWindowTimer.unsafeGet()): if socket.maxRemoteWindow <= currentPacketSize: + # Reset remote window, to minimal value which will fit at least two packet + let minimalRemoteWindow = 2 * socket.socketConfig.payloadSize socket.maxRemoteWindow = minimalRemoteWindow + debug "Reset remote window to minimal value", + minRemote = minimalRemoteWindow socket.zeroWindowTimer = none[Moment]() - debug "Reset remote window to minimal value", - minRemote = minimalRemoteWindow - + if (currentTime > socket.rtoTimeout): debug "CheckTimeouts rto timeout", socketKey = socket.socketKey, @@ -545,7 +563,7 @@ proc checkTimeouts(socket: UtpSocket) = if socket.shouldDisconnectFromFailedRemote(): debug "Remote host failed", state = socket.state, - retransmitCount = socket.retransmitCount + retransmitCount = socket.retransmitCount if socket.state == SynSent and (not socket.connectionFuture.finished()): socket.connectionFuture.fail(newException(ConnectionError, "Connection to peer timed out")) @@ -571,7 +589,7 @@ proc checkTimeouts(socket: UtpSocket) = oldMaxWindow = oldMaxWindow, newMaxWindow = newMaxWindow - socket.maxWindow = newMaxWindow + socket.maxWindow = newMaxWindow elif (socket.maxWindow < currentPacketSize): # due to high delay window has shrunk below packet size # which means that we cannot send more data @@ -595,7 +613,7 @@ proc checkTimeouts(socket: UtpSocket) = if (socket.curWindowPackets > 0 and socket.outBuffer[oldestPacketSeqNr].transmissions > 0): inc socket.retransmitCount socket.fastTimeout = true - + debug "Resending oldest packet", pkSeqNr = oldestPacketSeqNr, retransmitCount = socket.retransmitCount, @@ -604,7 +622,7 @@ proc checkTimeouts(socket: UtpSocket) = # Oldest packet should always be present, so it is safe to call force # resend socket.sendPacket(oldestPacketSeqNr) - + # TODO add sending keep alives when necessary proc checkTimeoutsLoop(s: UtpSocket) {.async.} = @@ -612,19 +630,22 @@ proc checkTimeoutsLoop(s: UtpSocket) {.async.} = try: while true: await sleepAsync(checkTimeoutsLoopInterval) - await s.eventQueue.put(SocketEvent(kind: CheckTimeouts)) - except CancelledError: + s.eventQueue.putNoWait(SocketEvent(kind: CheckTimeouts)) + except CancelledError as exc: + # check timeouts loop is last running future managed by socket, if its + # cancelled we can fire closeEvent + s.closeEvent.fire() trace "checkTimeoutsLoop canceled" + raise exc proc startTimeoutLoop(s: UtpSocket) = s.checkTimeoutsLoop = checkTimeoutsLoop(s) -proc getPacketSize*(socket: UtpSocket): int = - # TODO currently returning constant, ultimatly it should be bases on mtu estimates - mtuSize +proc getPacketSize*(socket: UtpSocket): uint32 = + socket.socketConfig.payloadSize proc handleDataWrite(socket: UtpSocket, data: seq[byte]): int = - let pSize = socket.getPacketSize() + let pSize = int(socket.getPacketSize()) let endIndex = data.high() var i = 0 var bytesWritten = 0 @@ -682,15 +703,22 @@ proc isConnected*(socket: UtpSocket): bool = proc isClosed*(socket: UtpSocket): bool = socket.state == Destroy and socket.closeEvent.isSet() +proc isClosedAndCleanedUpAllResources*(socket: UtpSocket): bool = + ## Test Api to check that all resources are properly cleaned up + socket.isClosed() and socket.eventLoop.cancelled() and socket.checkTimeoutsLoop.cancelled() + proc destroy*(s: UtpSocket) = - info "Destroying socket", - to = s.socketKey + debug "Destroying socket", to = s.socketKey ## Moves socket to destroy state and clean all reasources. ## Remote is not notified in any way about socket end of life s.state = Destroy s.eventLoop.cancel() - s.checkTimeoutsLoop.cancel() - s.closeEvent.fire() + # This procedure initiate cleanup process which goes like: + # Cancel EventLoop -> Cancel timeoutsLoop -> Fire closeEvent + # This is necessary due to how evenLoop look like i.e it has only one await + # point on `eventQueue.get` which trigger cancellation excepion only when + # someone will try run `eventQueue.put`. Without `eventQueue.put` , eventLoop + # future shows as cancelled, but handler for CancelledError is not run proc destroyWait*(s: UtpSocket) {.async.} = ## Moves socket to destroy state and clean all reasources and wait for all registered @@ -879,7 +907,7 @@ proc tryDecayWindow(socket: UtpSocket, now: Moment) = if (now - socket.lastWindowDecay >= maxWindowDecay): socket.lastWindowDecay = now let newMaxWindow = max(uint32(0.5 * float64(socket.maxWindow)), uint32(minWindowSize)) - + debug "Decaying maxWindow", oldWindow = socket.maxWindow, newWindow = newMaxWindow @@ -887,7 +915,7 @@ proc tryDecayWindow(socket: UtpSocket, now: Moment) = socket.maxWindow = newMaxWindow socket.slowStart = false socket.slowStartTreshold = newMaxWindow - + # ack packets (removes them from out going buffer) based on selective ack extension header proc selectiveAckPackets(socket: UtpSocket, receivedPackedAckNr: uint16, ext: SelectiveAckExtension, currentTime: Moment): void = # we add 2, as the first bit in the mask therefore represents ackNr + 2 becouse @@ -913,7 +941,7 @@ proc selectiveAckPackets(socket: UtpSocket, receivedPackedAckNr: uint16, ext: S if (socket.seqNr - v - 1) >= socket.curWindowPackets - 1: dec bits continue - + let bitSet: bool = getBit(ext.acks, bits) if bitSet: @@ -933,7 +961,7 @@ proc selectiveAckPackets(socket: UtpSocket, receivedPackedAckNr: uint16, ext: S discard socket.ackPacket(v, currentTime) dec bits continue - + if counter >= duplicateAcksBeforeResend and (v - socket.fastResendSeqNr) <= reorderBufferMaxSize: debug "No ack for packet", pkAckNr = v, @@ -965,7 +993,7 @@ proc selectiveAckPackets(socket: UtpSocket, receivedPackedAckNr: uint16, ext: S # packet is no longer in send buffer ignore whole further processing dec i continue - + registerLoss = true # it is safe to call as we already checked that packet is in send buffer @@ -1026,7 +1054,7 @@ proc generateAckPacket*(socket: UtpSocket): Packet = bitmask ) -proc sendAck(socket: UtpSocket) = +proc sendAck(socket: UtpSocket) = ## Creates and sends ack, based on current socket state. Acks are different from ## other packets as we do not track them in outgoing buffet @@ -1039,6 +1067,25 @@ proc sendAck(socket: UtpSocket) = socket.sendData(encodePacket(ackPacket)) + +proc tryfinalizeConnection(socket: UtpSocket, p: Packet) = + # To avoid amplification attacks, server socket is in SynRecv state until + # it receices first data transfer + # https://www.usenix.org/system/files/conference/woot15/woot15-paper-adamsky.pdf + # Socket is in SynRecv state only when recv timeout is configured + if (socket.state == SynRecv and p.header.pType == ST_DATA): + socket.state = Connected + + if (socket.state == SynSent and p.header.pType == ST_STATE): + socket.state = Connected + socket.ackNr = p.header.seqNr - 1 + + debug "Received Syn-Ack finalizing connection", + socketAckNr = socket.ackNr + + if (not socket.connectionFuture.finished()): + socket.connectionFuture.complete() + # TODO at socket level we should handle only FIN/DATA/ACK packets. Refactor to make # it enforcable by type system proc processPacketInternal(socket: UtpSocket, p: Packet) = @@ -1102,8 +1149,8 @@ proc processPacketInternal(socket: UtpSocket, p: Packet) = # the fast-resend on duplicate-ack logic for bi-directional connections # (except in the case of a selective ACK). This is in line with BSD4.4 TCP # implementation. - if socket.curWindowPackets > 0 and - pkAckNr == socket.seqNr - socket.curWindowPackets - 1 and + if socket.curWindowPackets > 0 and + pkAckNr == socket.seqNr - socket.curWindowPackets - 1 and p.header.pType == ST_STATE: inc socket.duplicateAck @@ -1127,7 +1174,7 @@ proc processPacketInternal(socket: UtpSocket, p: Packet) = # if `pastExpected` is really big number (for example: uint16.high) then most # probably we are receiving packet which we already received # example: we already received packet with `seqNr = 10` so our `socket.ackNr = 10` - # if we receive this packet once again then `pastExpected = 10 - 10 - 1` which + # if we receive this packet once again then `pastExpected = 10 - 10 - 1` which # equals (due to wrapping) 65535 # this means that remote most probably did not receive our ack, so we need to resend # it. We are doing it for last `reorderBufferMaxSize` packets @@ -1144,7 +1191,7 @@ proc processPacketInternal(socket: UtpSocket, p: Packet) = debug "Bytes acked by classic ack", bytesAcked = ackedBytes - + if (p.eack.isSome()): let selectiveAckedBytes = socket.calculateSelectiveAckBytes(pkAckNr, p.eack.unsafeGet()) debug "Bytes acked by selective ack", @@ -1190,7 +1237,7 @@ proc processPacketInternal(socket: UtpSocket, p: Packet) = let diff = uint32((socket.ourHistogram.getValue() - minRtt).microseconds()) socket.ourHistogram.shift(diff) - let currentPacketSize = uint32(socket.getPacketSize()) + let currentPacketSize = socket.getPacketSize() let (newMaxWindow, newSlowStartTreshold, newSlowStart) = applyCongestionControl( socket.maxWindow, @@ -1227,6 +1274,8 @@ proc processPacketInternal(socket: UtpSocket, p: Packet) = resetZeroWindowTime = socket.zeroWindowTimer, currentPacketSize = currentPacketSize + socket.tryfinalizeConnection(p) + # socket.curWindowPackets == acks means that this packet acked all remaining packets # including the sent fin packets if (socket.finSent and socket.curWindowPackets == acks): @@ -1272,187 +1321,172 @@ proc processPacketInternal(socket: UtpSocket, p: Packet) = pkSeqNr = oldestOutstandingPktSeqNr inc socket.fastResendSeqNr - + # Is is safe to call force resend as we already checked shouldReSendPacket # condition socket.sendPacket(oldestOutstandingPktSeqNr) - + if (p.eack.isSome()): socket.selectiveAckPackets(pkAckNr, p.eack.unsafeGet(), timestampInfo.moment) - case p.header.pType - of ST_DATA, ST_FIN: - # To avoid amplification attacks, server socket is in SynRecv state until - # it receices first data transfer - # https://www.usenix.org/system/files/conference/woot15/woot15-paper-adamsky.pdf - # Socket is in SynRecv state only when recv timeout is configured - if (socket.state == SynRecv and p.header.pType == ST_DATA): - socket.state = Connected + if p.header.pType == ST_DATA or p.header.pType == ST_FIN: + if socket.state != Connected: + debug "Unexpected packet", + socketState = socket.state, + packetType = p.header.pType - if (p.header.pType == ST_FIN and (not socket.gotFin)): - debug "Received FIN packet", - eofPktNr = pkSeqNr, - curAckNr = socket.ackNr + # we have received user generated packet (DATA or FIN), in not connected + # state. Stop processing it. + return - socket.gotFin = true - socket.eofPktNr = pkSeqNr + if (p.header.pType == ST_FIN and (not socket.gotFin)): + debug "Received FIN packet", + eofPktNr = pkSeqNr, + curAckNr = socket.ackNr - # we got in order packet - if (pastExpected == 0 and (not socket.reachedFin)): - debug "Received in order packet" - let payloadLength = len(p.payload) - if (payloadLength > 0 and (not socket.readShutdown)): - # we need to sum both rcv buffer and reorder buffer - if (uint32(socket.offset) + socket.inBufferBytes + uint32(payloadLength) > socket.socketConfig.optRcvBuffer): - # even though packet is in order and passes all the checks, it would - # overflow our receive buffer, it means that we are receiving data - # faster than we are reading it. Do not ack this packet, and drop received - # data - debug "Recevied packet would overflow receive buffer dropping it", - pkSeqNr = p.header.seqNr, - bytesReceived = payloadLength, - rcvbufferSize = socket.offset, - reorderBufferSize = socket.inBufferBytes - return - - debug "Received data packet", - bytesReceived = payloadLength - # we are getting in order data packet, we can flush data directly to the incoming buffer - # await upload(addr socket.buffer, unsafeAddr p.payload[0], p.payload.len()) - moveMem(addr socket.rcvBuffer[socket.offset], unsafeAddr p.payload[0], payloadLength) - socket.offset = socket.offset + payloadLength - - # Bytes have been passed to upper layer, we can increase number of last - # acked packet - inc socket.ackNr - - # check if the following packets are in reorder buffer - - debug "Looking for packets in re-order buffer", - reorderCount = socket.reorderCount - - while true: - # We are doing this in reoreder loop, to handle the case when we already received - # fin but there were some gaps before eof - # we have reached remote eof, and should not receive more packets from remote - if ((not socket.reachedFin) and socket.gotFin and socket.eofPktNr == socket.ackNr): - debug "Reached socket EOF" - # In case of reaching eof, it is up to user of library what to to with - # it. With the current implementation, the most apropriate way would be to - # destory it (as with our implementation we know that remote is destroying its acked fin) - # as any other send will either generate timeout, or socket will be forcefully - # closed by reset - socket.reachedFin = true - # this is not necessarily true, but as we have already reached eof we can - # ignore following packets - socket.reorderCount = 0 - - if socket.reorderCount == 0: - break - - let nextPacketNum = socket.ackNr + 1 - - let maybePacket = socket.inBuffer.get(nextPacketNum) - - if maybePacket.isNone(): - break - - let packet = maybePacket.unsafeGet() - let reorderPacketPayloadLength = len(packet.payload) - - if (reorderPacketPayloadLength > 0 and (not socket.readShutdown)): - debug "Got packet from reorder buffer", - packetBytes = len(packet.payload), - packetSeqNr = packet.header.seqNr, - packetAckNr = packet.header.ackNr, - socketSeqNr = socket.seqNr, - socektAckNr = socket.ackNr, - rcvbufferSize = socket.offset, - reorderBufferSize = socket.inBufferBytes - - # Rcv buffer and reorder buffer are sized that it is always possible to - # move data from reorder buffer to rcv buffer without overflow - moveMem(addr socket.rcvBuffer[socket.offset], unsafeAddr packet.payload[0], reorderPacketPayloadLength) - socket.offset = socket.offset + reorderPacketPayloadLength - - debug "Deleting packet", - seqNr = nextPacketNum - - socket.inBuffer.delete(nextPacketNum) - inc socket.ackNr - dec socket.reorderCount - socket.inBufferBytes = socket.inBufferBytes - uint32(reorderPacketPayloadLength) - - debug "Socket state after processing in order packet", - socketKey = socket.socketKey, - socketAckNr = socket.ackNr, - reorderCount = socket.reorderCount, - windowPackets = socket.curWindowPackets - - # TODO for now we just schedule concurrent task with ack sending. It may - # need improvement, as with this approach there is no direct control over - # how many concurrent tasks there are and how to cancel them when socket - # is closed - socket.sendAck() - - # we got packet out of order - else: - debug "Got out of order packet" - - if (socket.gotFin and pkSeqNr > socket.eofPktNr): - debug "Got packet past eof", - pkSeqNr = pkSeqNr, - eofPktNr = socket.eofPktNr + socket.gotFin = true + socket.eofPktNr = pkSeqNr + # we got in order packet + if (pastExpected == 0 and (not socket.reachedFin)): + debug "Received in order packet" + let payloadLength = len(p.payload) + if (payloadLength > 0 and (not socket.readShutdown)): + # we need to sum both rcv buffer and reorder buffer + if (uint32(socket.offset) + socket.inBufferBytes + uint32(payloadLength) > socket.socketConfig.optRcvBuffer): + # even though packet is in order and passes all the checks, it would + # overflow our receive buffer, it means that we are receiving data + # faster than we are reading it. Do not ack this packet, and drop received + # data + debug "Recevied packet would overflow receive buffer dropping it", + pkSeqNr = p.header.seqNr, + bytesReceived = payloadLength, + rcvbufferSize = socket.offset, + reorderBufferSize = socket.inBufferBytes return - # growing buffer before checking the packet is already there to avoid - # looking at older packet due to indices wrap aroud - socket.inBuffer.ensureSize(pkSeqNr + 1, pastExpected + 1) + debug "Received data packet", + bytesReceived = payloadLength + # we are getting in order data packet, we can flush data directly to the incoming buffer + # await upload(addr socket.buffer, unsafeAddr p.payload[0], p.payload.len()) + moveMem(addr socket.rcvBuffer[socket.offset], unsafeAddr p.payload[0], payloadLength) + socket.offset = socket.offset + payloadLength - if (socket.inBuffer.get(pkSeqNr).isSome()): - debug "Packet with seqNr already received", - seqNr = pkSeqNr - else: - let payloadLength = uint32(len(p.payload)) - if (socket.inBufferBytes + payloadLength <= socket.socketConfig.maxSizeOfReorderBuffer and - socket.inBufferBytes + uint32(socket.offset) + payloadLength <= socket.socketConfig.optRcvBuffer): - - debug "store packet in reorder buffer", - packetBytes = payloadLength, - packetSeqNr = p.header.seqNr, - packetAckNr = p.header.ackNr, - socketSeqNr = socket.seqNr, - socektAckNr = socket.ackNr, - rcvbufferSize = socket.offset, - reorderBufferSize = socket.inBufferBytes + # Bytes have been passed to upper layer, we can increase number of last + # acked packet + inc socket.ackNr - socket.inBuffer.put(pkSeqNr, p) - inc socket.reorderCount - socket.inBufferBytes = socket.inBufferBytes + payloadLength - debug "added out of order packet to reorder buffer", - reorderCount = socket.reorderCount - # we send ack packet, as we reoreder count is > 0, so the eack bitmask will be - # generated - socket.sendAck() + # check if the following packets are in reorder buffer - of ST_STATE: - if (socket.state == SynSent and (not socket.connectionFuture.finished())): - socket.state = Connected - # TODO reference implementation sets ackNr (p.header.seqNr - 1), although - # spec mention that it should be equal p.header.seqNr. For now follow the - # reference impl to be compatible with it. Later investigate trin compatibility. - socket.ackNr = p.header.seqNr - 1 - # In case of SynSent complate the future as last thing to make sure user of libray will - # receive socket in correct state - socket.connectionFuture.complete() + debug "Looking for packets in re-order buffer", + reorderCount = socket.reorderCount - of ST_RESET: - debug "Received ST_RESET on known socket, ignoring" - of ST_SYN: - debug "Received ST_SYN on known socket, ignoring" + while true: + # We are doing this in reoreder loop, to handle the case when we already received + # fin but there were some gaps before eof + # we have reached remote eof, and should not receive more packets from remote + if ((not socket.reachedFin) and socket.gotFin and socket.eofPktNr == socket.ackNr): + debug "Reached socket EOF" + # In case of reaching eof, it is up to user of library what to to with + # it. With the current implementation, the most apropriate way would be to + # destory it (as with our implementation we know that remote is destroying its acked fin) + # as any other send will either generate timeout, or socket will be forcefully + # closed by reset + socket.reachedFin = true + # this is not necessarily true, but as we have already reached eof we can + # ignore following packets + socket.reorderCount = 0 -proc processPacket*(socket: UtpSocket, p: Packet): Future[void] = + if socket.reorderCount == 0: + break + + let nextPacketNum = socket.ackNr + 1 + + let maybePacket = socket.inBuffer.get(nextPacketNum) + + if maybePacket.isNone(): + break + + let packet = maybePacket.unsafeGet() + let reorderPacketPayloadLength = len(packet.payload) + + if (reorderPacketPayloadLength > 0 and (not socket.readShutdown)): + debug "Got packet from reorder buffer", + packetBytes = len(packet.payload), + packetSeqNr = packet.header.seqNr, + packetAckNr = packet.header.ackNr, + socketSeqNr = socket.seqNr, + socektAckNr = socket.ackNr, + rcvbufferSize = socket.offset, + reorderBufferSize = socket.inBufferBytes + + # Rcv buffer and reorder buffer are sized that it is always possible to + # move data from reorder buffer to rcv buffer without overflow + moveMem(addr socket.rcvBuffer[socket.offset], unsafeAddr packet.payload[0], reorderPacketPayloadLength) + socket.offset = socket.offset + reorderPacketPayloadLength + + debug "Deleting packet", + seqNr = nextPacketNum + + socket.inBuffer.delete(nextPacketNum) + inc socket.ackNr + dec socket.reorderCount + socket.inBufferBytes = socket.inBufferBytes - uint32(reorderPacketPayloadLength) + + debug "Socket state after processing in order packet", + socketKey = socket.socketKey, + socketAckNr = socket.ackNr, + reorderCount = socket.reorderCount, + windowPackets = socket.curWindowPackets + + # TODO for now we just schedule concurrent task with ack sending. It may + # need improvement, as with this approach there is no direct control over + # how many concurrent tasks there are and how to cancel them when socket + # is closed + socket.sendAck() + + # we got packet out of order + else: + debug "Got out of order packet" + + if (socket.gotFin and pkSeqNr > socket.eofPktNr): + debug "Got packet past eof", + pkSeqNr = pkSeqNr, + eofPktNr = socket.eofPktNr + + return + + # growing buffer before checking the packet is already there to avoid + # looking at older packet due to indices wrap aroud + socket.inBuffer.ensureSize(pkSeqNr + 1, pastExpected + 1) + + if (socket.inBuffer.get(pkSeqNr).isSome()): + debug "Packet with seqNr already received", + seqNr = pkSeqNr + else: + let payloadLength = uint32(len(p.payload)) + if (socket.inBufferBytes + payloadLength <= socket.socketConfig.maxSizeOfReorderBuffer and + socket.inBufferBytes + uint32(socket.offset) + payloadLength <= socket.socketConfig.optRcvBuffer): + + debug "store packet in reorder buffer", + packetBytes = payloadLength, + packetSeqNr = p.header.seqNr, + packetAckNr = p.header.ackNr, + socketSeqNr = socket.seqNr, + socektAckNr = socket.ackNr, + rcvbufferSize = socket.offset, + reorderBufferSize = socket.inBufferBytes + + socket.inBuffer.put(pkSeqNr, p) + inc socket.reorderCount + socket.inBufferBytes = socket.inBufferBytes + payloadLength + debug "added out of order packet to reorder buffer", + reorderCount = socket.reorderCount + # we send ack packet, as we reoreder count is > 0, so the eack bitmask will be + # generated + socket.sendAck() + +proc processPacket*(socket: UtpSocket, p: Packet): Future[void] = socket.eventQueue.put(SocketEvent(kind: NewPacket, packet: p)) template shiftBuffer(t, c: untyped) = @@ -1472,7 +1506,7 @@ proc onRead(socket: UtpSocket, readReq: var ReadReq): ReadResult = if readReq.reader.finished(): return ReadCancelled - + if socket.atEof(): # buffer is already empty and we reached remote fin, just finish read with whatever # was already read @@ -1524,7 +1558,7 @@ proc eventLoop(socket: UtpSocket) {.async.} = case ev.kind of NewPacket: socket.processPacketInternal(ev.packet) - + # we processed a packet and rcv buffer size is larger than 0, # check if we can finish some pending readers while socket.pendingReads.len() > 0: @@ -1550,7 +1584,7 @@ proc eventLoop(socket: UtpSocket) {.async.} = # close should be last packet send break of Data: - # check if writing was not cancelled in the mean time. This approach + # check if writing was not cancelled in the mean time. This approach # can create partial writes as part of the data could be written with # with WriteReq if (not wr.writer.finished()): @@ -1601,11 +1635,10 @@ proc eventLoop(socket: UtpSocket) {.async.} = of ReadNotFinished: socket.pendingReads.addLast(readReq) else: - # in any other case we do not need to do any thing + # in any other case we do not need to do any thing discard - socket.checkTimeouts() - except CancelledError: + except CancelledError as exc: for w in socket.pendingWrites.items(): if w.kind == Data and (not w.writer.finished()): let res = Result[int, WriteError].err(WriteError(kind: SocketNotWriteable, currentState: socket.state)) @@ -1618,7 +1651,10 @@ proc eventLoop(socket: UtpSocket) {.async.} = r.reader.complete(r.bytesAvailable) socket.pendingWrites.clear() socket.pendingReads.clear() + # main eventLoop has been cancelled, try to cancel check timeouts loop + socket.checkTimeoutsLoop.cancel() trace "main socket event loop cancelled" + raise exc proc startEventLoop(s: UtpSocket) = s.eventLoop = eventLoop(s) @@ -1640,8 +1676,7 @@ proc close*(socket: UtpSocket) = socket.readShutdown = true if (not socket.sendFinRequested): try: - info "Sending FIN", - to = socket.socketKey + debug "Sending FIN", dst = socket.socketKey # with this approach, all pending writes will be executed before sending fin packet # we could also and method which places close request as first one to process # but it would complicate the write loop @@ -1666,9 +1701,7 @@ proc closeWait*(socket: UtpSocket) {.async.} = await socket.closeEvent.wait() proc write*(socket: UtpSocket, data: seq[byte]): Future[WriteResult] = - info "Write data", - to = socket.socketKey, - length = len(data) + debug "Write data", dst = socket.socketKey, length = len(data) let retFuture = newFuture[WriteResult]("UtpSocket.write") @@ -1805,6 +1838,13 @@ proc new[A]( initialTimeout: Duration ): T = let currentTime = getMonoTimestamp().moment + + # Initial max window size. Reference implementation uses value which enables one packet + # to be transfered. + # We use value two times higher as we do not yet have proper mtu estimation, and + # our impl should work over udp and discovery v5 (where proper estmation may be harder + # as packets already have discoveryv5 envelope) + let initMaxWindow = 2 * cfg.payloadSize T( remoteAddress: to, state: state, @@ -1820,7 +1860,7 @@ proc new[A]( currentWindow: 0, # start with 1mb assumption, field will be updated with first received packet maxRemoteWindow: 1024 * 1024, - maxWindow: startMaxWindow, + maxWindow: initMaxWindow, inBuffer: GrowableCircularBuffer[Packet].init(), retransmitTimeout: initialTimeout, rtoTimeout: currentTime + initialTimeout, @@ -1852,7 +1892,7 @@ proc newOutgoingSocket*[A]( snd: SendCallback[A], cfg: SocketConfig, rcvConnectionId: uint16, - rng: var BrHmacDrbgContext + rng: var HmacDrbgContext ): UtpSocket[A] = let sndConnectionId = rcvConnectionId + 1 let initialSeqNr = randUint16(rng) @@ -1877,7 +1917,7 @@ proc newIncomingSocket*[A]( cfg: SocketConfig, connectionId: uint16, ackNr: uint16, - rng: var BrHmacDrbgContext + rng: var HmacDrbgContext ): UtpSocket[A] = let initialSeqNr = randUint16(rng) @@ -1906,16 +1946,19 @@ proc newIncomingSocket*[A]( initialTimeout ) +proc getSocketConfig*(socket: UtpSocket): SocketConfig = + socket.socketConfig + proc startIncomingSocket*(socket: UtpSocket) = # Make sure ack was flushed before moving forward - socket.sendAck() + socket.sendAck() socket.startEventLoop() socket.startTimeoutLoop() proc startOutgoingSocket*(socket: UtpSocket): Future[void] = doAssert(socket.state == SynSent) let packet = synPacket(socket.seqNr, socket.connectionIdRcv, socket.getRcvWindowSize()) - debug "Sending SYN packet", + debug "Sending SYN packet", seqNr = packet.header.seqNr, connectionId = packet.header.connectionId # set number of transmissions to 1 as syn packet will be send just after diff --git a/vendor/nim-eth/nim.cfg b/vendor/nim-eth/nim.cfg new file mode 100644 index 000000000..371f6d79d --- /dev/null +++ b/vendor/nim-eth/nim.cfg @@ -0,0 +1,5 @@ +# Avoid some rare stack corruption while using exceptions with a SEH-enabled +# toolchain: https://github.com/status-im/nimbus-eth2/issues/3121 +@if windows and not vcc: + --define:nimRawSetjmp +@end diff --git a/vendor/nim-eth/tests/config.nims b/vendor/nim-eth/tests/config.nims deleted file mode 100644 index f67c4ac32..000000000 --- a/vendor/nim-eth/tests/config.nims +++ /dev/null @@ -1,4 +0,0 @@ ---threads:on -# rocksdb_backend newChainDB fails compiling without nimOldCaseObjects as -# rocksdb init does this type of assignment ---define:nimOldCaseObjects diff --git a/vendor/nim-eth/tests/db/all_tests.nim b/vendor/nim-eth/tests/db/all_tests.nim index afb6f62bc..552aea143 100644 --- a/vendor/nim-eth/tests/db/all_tests.nim +++ b/vendor/nim-eth/tests/db/all_tests.nim @@ -1,4 +1,3 @@ import - ./test_kvstore_rocksdb, ./test_kvstore_sqlite3, ./test_kvstore diff --git a/vendor/nim-eth/tests/db/test_kvstore_rocksdb.nim b/vendor/nim-eth/tests/db/test_kvstore_rocksdb.nim deleted file mode 100644 index 2e099a9a2..000000000 --- a/vendor/nim-eth/tests/db/test_kvstore_rocksdb.nim +++ /dev/null @@ -1,18 +0,0 @@ -{.used.} - -import - std/os, - unittest2, - chronicles, - ../../eth/db/[kvstore, kvstore_rocksdb], - ./test_kvstore - -suite "RocksStoreRef": - test "KvStore interface": - let tmp = getTempDir() / "nimbus-test-db" - removeDir(tmp) - - let db = RocksStoreRef.init(tmp, "test")[] - defer: db.close() - - testKvStore(kvStore db, false) diff --git a/vendor/nim-eth/tests/db/test_kvstore_sqlite3.nim b/vendor/nim-eth/tests/db/test_kvstore_sqlite3.nim index a69121af4..693b180fa 100644 --- a/vendor/nim-eth/tests/db/test_kvstore_sqlite3.nim +++ b/vendor/nim-eth/tests/db/test_kvstore_sqlite3.nim @@ -1,8 +1,9 @@ {.used.} import - std/[os, options], + std/[os, options, sequtils], testutils/unittests, + stew/endians2, ../../eth/db/[kvstore, kvstore_sqlite3], ./test_kvstore @@ -232,4 +233,52 @@ procSuite "SqStoreRef": rowRes.expect("working db") check abc == row found = true - check found \ No newline at end of file + check found + + proc customSumFun( + a: openArray[byte], + b: openArray[byte]): Result[seq[byte], cstring] {.noSideEffect, gcsafe, cdecl, raises: [Defect].} = + let num1 = uint32.fromBytesBE(a) + let num2 = uint32.fromBytesBE(b) + let sum = num1 + num2 + let asBytes = sum.toBytesBE().toSeq() + return ok(asBytes) + + test "Register custom scalar function": + let db = SqStoreRef.init("", "test", inMemory = true)[] + + let registerResult = db.registerCustomScalarFunction("sum32", customSumFun) + + check: + registerResult.isOk() + + defer: db.close() + + let kv = db.openKvStore().get() + defer: kv.close() + + var sums: seq[seq[byte]] = @[] + + # Use custom function, which interprest blobs as uint32 numbers and sums + # them together + let sumKeyVal = db.prepareStmt( + "SELECT sum32(key, value) FROM kvstore;", + NoParams, seq[byte]).get + + let testUint = uint32(38) + + let putRes = kv.put(testUint.toBytesBE(), testUint.toBytesBE()) + + check: + putRes.isOk() + + discard sumKeyVal.exec do (res: seq[byte]): + sums.add(res) + + check: + len(sums) == 1 + + let sum = uint32.fromBytesBE(sums[0]) + + check: + sum == testUint + testUint diff --git a/vendor/nim-eth/tests/fuzzing/discovery/fuzz.nim b/vendor/nim-eth/tests/fuzzing/discovery/fuzz.nim index 8d816ed08..a3f4993d5 100644 --- a/vendor/nim-eth/tests/fuzzing/discovery/fuzz.nim +++ b/vendor/nim-eth/tests/fuzzing/discovery/fuzz.nim @@ -1,4 +1,5 @@ import + std/net, testutils/fuzzing, chronicles, nimcrypto/keccak, ../../../eth/p2p/[discovery, enode], ../../../eth/[keys, rlp], ../../p2p/p2p_test_helper @@ -18,7 +19,8 @@ init: var targetNodeKey = PrivateKey.fromHex("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617")[] targetNodeAddr = localAddress(DefaultListeningPort) - targetNode = newDiscoveryProtocol(targetNodeKey, targetNodeAddr, @[]) + targetNode = newDiscoveryProtocol( + targetNodeKey, targetNodeAddr, @[], Port(DefaultListeningPort)) # Create the transport as else replies on the messages send will fail. targetNode.open() diff --git a/vendor/nim-eth/tests/fuzzing/discoveryv5/fuzz_decode_message.nim b/vendor/nim-eth/tests/fuzzing/discoveryv5/fuzz_decode_message.nim index 4d8121fed..ca67bb9ad 100644 --- a/vendor/nim-eth/tests/fuzzing/discoveryv5/fuzz_decode_message.nim +++ b/vendor/nim-eth/tests/fuzzing/discoveryv5/fuzz_decode_message.nim @@ -13,11 +13,11 @@ test: of unused: break of ping: encoded = encodeMessage(message.ping, message.reqId) of pong: encoded = encodeMessage(message.pong, message.reqId) - of findnode: encoded = encodeMessage(message.findNode, message.reqId) + of findNode: encoded = encodeMessage(message.findNode, message.reqId) of nodes: encoded = encodeMessage(message.nodes, message.reqId) - of talkreq: encoded = encodeMessage(message.talkreq, message.reqId) - of talkresp: encoded = encodeMessage(message.talkresp, message.reqId) - of regtopic, ticket, regconfirmation, topicquery: + of talkReq: encoded = encodeMessage(message.talkReq, message.reqId) + of talkResp: encoded = encodeMessage(message.talkResp, message.reqId) + of regTopic, ticket, regConfirmation, topicQuery: break # This will hit assert because of issue: diff --git a/vendor/nim-eth/tests/fuzzing/discoveryv5/fuzz_decode_packet.nim b/vendor/nim-eth/tests/fuzzing/discoveryv5/fuzz_decode_packet.nim index c320f4cab..1583bf4dd 100644 --- a/vendor/nim-eth/tests/fuzzing/discoveryv5/fuzz_decode_packet.nim +++ b/vendor/nim-eth/tests/fuzzing/discoveryv5/fuzz_decode_packet.nim @@ -28,9 +28,9 @@ test: # It is not the best idea to generate extra data and encrypt data but we do # it like this as the decodeHeader proc does decrypt + decode + decrypt. # There is no separate decrypt step that can be skipped because of this. - var iv: array[ivSize, byte] - brHmacDrbgGenerate(rng[], iv) - let maskedHeader = encryptHeader(nodeB.id, iv, payload) + let + iv = rng[].generate(array[ivSize, byte]) + maskedHeader = encryptHeader(nodeB.id, iv, payload) let decoded = decodePacket(codecB, nodeA.address.get(), @iv & maskedHeader) if decoded.isErr(): diff --git a/vendor/nim-eth/tests/fuzzing/rlpx/thunk.nim b/vendor/nim-eth/tests/fuzzing/rlpx/thunk.nim index c050acdda..508cb6464 100644 --- a/vendor/nim-eth/tests/fuzzing/rlpx/thunk.nim +++ b/vendor/nim-eth/tests/fuzzing/rlpx/thunk.nim @@ -1,7 +1,7 @@ import - testutils/fuzzing, chronos, + testutils/fuzzing, chronos, ../../../eth/p2p, ../../../eth/p2p/rlpx, ../../../eth/p2p/private/p2p_types, - ../../../eth/p2p/rlpx_protocols/[whisper_protocol, eth_protocol], + ../../../eth/p2p/rlpx_protocols/eth_protocol, ../../p2p/p2p_test_helper var @@ -14,8 +14,8 @@ let rng = newRng() # to mock more to get rid of anything sockets, async, etc. # However, it can and has provided reasonably quick results anyhow. init: - node1 = setupTestNode(rng, eth, Whisper) - node2 = setupTestNode(rng, eth, Whisper) + node1 = setupTestNode(rng, eth) + node2 = setupTestNode(rng, eth) node2.startListening() peer = waitFor node1.rlpxConnect(newNode(node2.toENode())) diff --git a/vendor/nim-eth/tests/keys/test_keys.nim b/vendor/nim-eth/tests/keys/test_keys.nim index 600170de5..df46bb4df 100644 --- a/vendor/nim-eth/tests/keys/test_keys.nim +++ b/vendor/nim-eth/tests/keys/test_keys.nim @@ -11,7 +11,7 @@ import unittest2, - nimcrypto/hash, nimcrypto/keccak, nimcrypto/utils, bearssl, stew/byteutils, + nimcrypto/hash, nimcrypto/keccak, nimcrypto/utils, stew/byteutils, ../../eth/keys from strutils import toLowerAscii @@ -218,8 +218,7 @@ suite "ECC/ECDSA/ECDHE tests suite": test "ECDSA/100 signatures": # signature test for i in 1..100: - var m: array[32, byte] - brHmacDrbgGenerate(rng[], m) + let m = rng[].generate(array[32, byte]) var s = PrivateKey.random(rng[]) var key = s.toPublicKey() let sig = sign(s, SkMessage(m)) diff --git a/vendor/nim-eth/tests/nim.cfg b/vendor/nim-eth/tests/nim.cfg new file mode 100644 index 000000000..3162e22cd --- /dev/null +++ b/vendor/nim-eth/tests/nim.cfg @@ -0,0 +1,10 @@ +--threads:on +# rocksdb_backend newChainDB fails compiling without nimOldCaseObjects as +# rocksdb init does this type of assignment +--define:nimOldCaseObjects + +# Avoid some rare stack corruption while using exceptions with a SEH-enabled +# toolchain: https://github.com/status-im/nimbus-eth2/issues/3121 +@if windows and not vcc: + --define:nimRawSetjmp +@end diff --git a/vendor/nim-eth/tests/p2p/all_tests.nim b/vendor/nim-eth/tests/p2p/all_tests.nim index f73574eda..f80189d68 100644 --- a/vendor/nim-eth/tests/p2p/all_tests.nim +++ b/vendor/nim-eth/tests/p2p/all_tests.nim @@ -6,9 +6,5 @@ import ./test_ecies, ./test_enode, ./test_rlpx_thunk, - ./test_shh, - ./test_shh_config, - ./test_shh_connect, ./test_protocol_handlers, ./les/test_flow_control - \ No newline at end of file diff --git a/vendor/nim-eth/tests/p2p/bzz_basic_client.nim b/vendor/nim-eth/tests/p2p/bzz_basic_client.nim deleted file mode 100644 index 757ca74d2..000000000 --- a/vendor/nim-eth/tests/p2p/bzz_basic_client.nim +++ /dev/null @@ -1,20 +0,0 @@ -import - std/tables, - chronos, - ../../eth/p2p, ../../eth/p2p/peer_pool, - ../../eth/p2p/rlpx_protocols/bzz_protocol, - ./p2p_test_helper - -# Basic bzz test to test handshake with ethersphere/swarm node -# Fixed enode string for now - -var node = setupTestNode(Bzz, Hive) - -let nodeId = "enode://10420addaa648ffcf09c4ba9df7ce876f276f77aae015bc9346487780c9c04862dc47cec17c86be10d4fb7d93f2cae3f8e702f94cb6dea5807bfedad218a53df@127.0.0.1:30399" -let enode = ENode.fromString(nodeId)[] -waitFor node.peerPool.connectToNode(newNode(enode)) - -doAssert node.peerPool.connectedNodes.len() == 1 - -while true: - poll() diff --git a/vendor/nim-eth/tests/p2p/discv5_test_helper.nim b/vendor/nim-eth/tests/p2p/discv5_test_helper.nim index 397bed5c1..3034a250e 100644 --- a/vendor/nim-eth/tests/p2p/discv5_test_helper.nim +++ b/vendor/nim-eth/tests/p2p/discv5_test_helper.nim @@ -1,5 +1,5 @@ import - stew/shims/net, bearssl, chronos, + stew/shims/net, chronos, ../../eth/keys, ../../eth/p2p/discoveryv5/[enr, node, routing_table], ../../eth/p2p/discoveryv5/protocol as discv5_protocol @@ -10,7 +10,7 @@ proc localAddress*(port: int): Address = Address(ip: ValidIpAddress.init("127.0.0.1"), port: Port(port)) proc initDiscoveryNode*( - rng: ref BrHmacDrbgContext, + rng: ref HmacDrbgContext, privKey: PrivateKey, address: Address, bootstrapRecords: openArray[Record] = [], @@ -47,14 +47,14 @@ proc generateNode*(privKey: PrivateKey, port: int = 20302, some(port), some(port), localEnrFields).expect("Properly intialized private key") result = newNode(enr).expect("Properly initialized node") -proc generateNRandomNodes*(rng: ref BrHmacDrbgContext, n: int): seq[Node] = +proc generateNRandomNodes*(rng: var HmacDrbgContext, n: int): seq[Node] = var res = newSeq[Node]() for i in 1..n: - let node = generateNode(PrivateKey.random(rng[])) + let node = generateNode(PrivateKey.random(rng)) res.add(node) res -proc nodeAndPrivKeyAtDistance*(n: Node, rng: var BrHmacDrbgContext, d: uint32, +proc nodeAndPrivKeyAtDistance*(n: Node, rng: var HmacDrbgContext, d: uint32, ip: ValidIpAddress = ValidIpAddress.init("127.0.0.1")): (Node, PrivateKey) = while true: let pk = PrivateKey.random(rng) @@ -62,19 +62,19 @@ proc nodeAndPrivKeyAtDistance*(n: Node, rng: var BrHmacDrbgContext, d: uint32, if logDistance(n.id, node.id) == d: return (node, pk) -proc nodeAtDistance*(n: Node, rng: var BrHmacDrbgContext, d: uint32, +proc nodeAtDistance*(n: Node, rng: var HmacDrbgContext, d: uint32, ip: ValidIpAddress = ValidIpAddress.init("127.0.0.1")): Node = let (node, _) = n.nodeAndPrivKeyAtDistance(rng, d, ip) node proc nodesAtDistance*( - n: Node, rng: var BrHmacDrbgContext, d: uint32, amount: int, + n: Node, rng: var HmacDrbgContext, d: uint32, amount: int, ip: ValidIpAddress = ValidIpAddress.init("127.0.0.1")): seq[Node] = for i in 0.. 1280 -> should fail + let talkresp = await discv5_protocol.talkReq(node1, node2.localNode, + talkProtocol, repeat(byte 6, 1173)) + + check: + talkresp.isErr() + + await node1.closeWait() + await node2.closeWait() + + asyncTest "Max packet size: Response": + let + node1 = initDiscoveryNode( + rng, PrivateKey.random(rng[]), localAddress(20302)) + node2 = initDiscoveryNode( + rng, PrivateKey.random(rng[]), localAddress(20303)) + talkProtocol = "echo".toBytes() + + proc handler( + protocol: TalkProtocol, request: seq[byte], + fromId: NodeId, fromUdpAddress: Address): + seq[byte] {.gcsafe, raises: [Defect].} = + # Return the request + same protocol id + 2 bytes, to make it 1 byte + # bigger than the request + request & "echo12".toBytes() + + let echoProtocol = TalkProtocol(protocolHandler: handler) + + check node2.registerTalkProtocol(talkProtocol, echoProtocol).isOk() + # Do a ping first so a session is created, that makes the next message to + # be an ordinary message and more easy to reverse calculate packet sizes for + # than for a handshake message. + check (await node1.ping(node2.localNode)).isOk() + + block: # 1171 -> response will be 1 byte bigger thus this should pass + let talkresp = await discv5_protocol.talkReq(node1, node2.localNode, + talkProtocol, repeat(byte 6, 1171)) + + check: + talkresp.isOk() + + block: # 1172 -> response will be 1 byte bigger thus this should fail + let talkresp = await discv5_protocol.talkReq(node1, node2.localNode, + talkProtocol, repeat(byte 6, 1172)) + + check: + talkresp.isErr() + + await node1.closeWait() + await node2.closeWait() diff --git a/vendor/nim-eth/tests/p2p/test_discoveryv5_encoding.nim b/vendor/nim-eth/tests/p2p/test_discoveryv5_encoding.nim index 4ab089e02..8991a4549 100644 --- a/vendor/nim-eth/tests/p2p/test_discoveryv5_encoding.nim +++ b/vendor/nim-eth/tests/p2p/test_discoveryv5_encoding.nim @@ -456,18 +456,15 @@ suite "Discovery v5.1 Additional Encode/Decode": check decryptGCM(encryptionKey, nonce, invalidCipher, ad).isNone() test "Encrypt / Decrypt header": - var nonce: AESGCMNonce - brHmacDrbgGenerate(rng[], nonce) let + nonce = rng[].generate(AESGCMNonce) privKey = PrivateKey.random(rng[]) nodeId = privKey.toPublicKey().toNodeId() authdata = newSeq[byte](32) staticHeader = encodeStaticHeader(Flag.OrdinaryMessage, nonce, authdata.len()) header = staticHeader & authdata - - var iv: array[128 div 8, byte] - brHmacDrbgGenerate(rng[], iv) + iv = rng[].generate(array[128 div 8, byte]) let encrypted = encryptHeader(nodeId, iv, header) @@ -511,8 +508,7 @@ suite "Discovery v5.1 Additional Encode/Decode": decoded[].requestNonce == nonce test "Encode / Decode Whoareyou Packet": - var requestNonce: AESGCMNonce - brHmacDrbgGenerate(rng[], requestNonce) + let requestNonce = rng[].generate(AESGCMNonce) let recordSeq = 0'u64 let data = encodeWhoareyouPacket(rng[], codecA, nodeB.id, @@ -532,9 +528,8 @@ suite "Discovery v5.1 Additional Encode/Decode": decoded[].whoareyou.recordSeq == recordSeq test "Encode / Decode Handshake Message Packet": - var requestNonce: AESGCMNonce - brHmacDrbgGenerate(rng[], requestNonce) let + requestNonce = rng[].generate(AESGCMNonce) recordSeq = 1'u64 m = PingMessage(enrSeq: 0) reqId = RequestId.init(rng[]) @@ -563,9 +558,8 @@ suite "Discovery v5.1 Additional Encode/Decode": decoded.get().node.isNone() test "Encode / Decode Handshake Message Packet with ENR": - var requestNonce: AESGCMNonce - brHmacDrbgGenerate(rng[], requestNonce) let + requestNonce = rng[].generate(AESGCMNonce) recordSeq = 0'u64 m = PingMessage(enrSeq: 0) reqId = RequestId.init(rng[]) diff --git a/vendor/nim-eth/tests/p2p/test_enode.nim b/vendor/nim-eth/tests/p2p/test_enode.nim index ba30f695a..7e9b7a9df 100644 --- a/vendor/nim-eth/tests/p2p/test_enode.nim +++ b/vendor/nim-eth/tests/p2p/test_enode.nim @@ -104,8 +104,4 @@ suite "ENode": check runBNTest(RopstenBootnodes) check runBNTest(RinkebyBootnodes) check runBNTest(GoerliBootnodes) - check runBNTest(DiscoveryV5Bootnodes) check runBNTest(KovanBootnodes) - check runBNTest(StatusBootNodes) - check runBNTest(StatusBootNodesStaging) - check runBNTest(StatusBootNodesTest) diff --git a/vendor/nim-eth/tests/p2p/test_enr.nim b/vendor/nim-eth/tests/p2p/test_enr.nim index a80167d7b..0306e8408 100644 --- a/vendor/nim-eth/tests/p2p/test_enr.nim +++ b/vendor/nim-eth/tests/p2p/test_enr.nim @@ -1,9 +1,15 @@ +# Copyright (c) 2019-2022 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + {.used.} import std/[options, sequtils], unittest2, - nimcrypto/utils, stew/shims/net, + stew/shims/net, ../../eth/p2p/discoveryv5/enr, ../../eth/[keys, rlp] let rng = newRng() diff --git a/vendor/nim-eth/tests/p2p/test_rlpx_thunk.json b/vendor/nim-eth/tests/p2p/test_rlpx_thunk.json index f0eb32356..5c90ad607 100644 --- a/vendor/nim-eth/tests/p2p/test_rlpx_thunk.json +++ b/vendor/nim-eth/tests/p2p/test_rlpx_thunk.json @@ -7,7 +7,7 @@ "Message id that is not supported": { "payload": "08", "error": "UnsupportedMessageError", - "description": "This is a message id not used by devp2p, eth or whisper" + "description": "This is a message id not used by devp2p or eth" }, "Message id that is bigger than int32": { "payload": "888888888888888888", @@ -49,10 +49,25 @@ "error": "MalformedRlpError", "description": "listElem to error on invalid size encoding" }, - "Listing elements when not a list": { - "payload": "010a", + "Listing single element list when having more entries": { + "payload": "01c20420", "error": "RlpTypeMismatch", - "description": "listElem to assert on not a list" + "description": "listElem to assert on not a single entry list" + }, + "Listing single element list when having empty list": { + "payload": "01c0", + "error": "RlpTypeMismatch", + "description": "listElem to assert on not a single entry list" + }, + "Listing single element list with entry off enum range": { + "payload": "01c116", + "error": "RlpTypeMismatch", + "description": "Disconnect reason code out of bounds 0..16 (got: 22)" + }, + "Listing single element off enum range": { + "payload": "0116", + "error": "RlpTypeMismatch", + "description": "Disconnect reason code out of bounds 0..16 (got: 22)" }, "devp2p hello packet version 22 + additional list elements for EIP-8": { "payload": "00f87137916b6e6574682f76302e39312f706c616e39cdc5836574683dc6846d6f726b1682270fb840fda1cff674c90c9a197539fe3dfb53086ace64f83ed7c6eabec741f7f381cc803e52ab2cd55d5569bce4347107a310dfd5f88a010cd2ffd1005ca406f1842877c883666f6f836261720304" diff --git a/vendor/nim-eth/tests/p2p/test_rlpx_thunk.nim b/vendor/nim-eth/tests/p2p/test_rlpx_thunk.nim index 01f5bc787..4747e67c4 100644 --- a/vendor/nim-eth/tests/p2p/test_rlpx_thunk.nim +++ b/vendor/nim-eth/tests/p2p/test_rlpx_thunk.nim @@ -4,14 +4,14 @@ import std/[json, os], unittest2, chronos, stew/byteutils, - ../../eth/p2p, ../../eth/p2p/rlpx_protocols/[whisper_protocol, eth_protocol], + ../../eth/p2p, ../../eth/p2p/rlpx_protocols/eth_protocol, ./p2p_test_helper let rng = newRng() var - node1 = setupTestNode(rng, eth, Whisper) - node2 = setupTestNode(rng, eth, Whisper) + node1 = setupTestNode(rng, eth) + node2 = setupTestNode(rng, eth) node2.startListening() var peer = waitFor node1.rlpxConnect(newNode(node2.toENode())) diff --git a/vendor/nim-eth/tests/p2p/test_routing_table.nim b/vendor/nim-eth/tests/p2p/test_routing_table.nim index da35e74d8..64cac967a 100644 --- a/vendor/nim-eth/tests/p2p/test_routing_table.nim +++ b/vendor/nim-eth/tests/p2p/test_routing_table.nim @@ -2,7 +2,6 @@ import unittest2, - bearssl, ../../eth/keys, ../../eth/p2p/discoveryv5/[routing_table, node, enr], ./discv5_test_helper @@ -121,10 +120,10 @@ suite "Routing Table Tests": table.replaceNode(table.nodeToRevalidate()) block: # Should return the last node of the replacement cache successfully. - let result = table.getNode(lastNode.id) + let res = table.getNode(lastNode.id) check: - result.isSome() - result.get() == lastNode + res.isSome() + res.get() == lastNode block: # This node should be removed check (table.getNode(bucketNodes[bucketNodes.high].id)).isNone() @@ -187,10 +186,10 @@ suite "Routing Table Tests": for n in 0.. x.foo == text) @@ -124,3 +136,39 @@ suite "Utp ring buffer": buff.get(15) == none[int]() buff.get(16) == none[int]() buff.get(17) == some(17) + + test "Ensuring proper wrap around when adding elements to buffer": + var buff = GrowableCircularBuffer[int].init(size = 2) + + buff.ensureSize(65535, 0) + buff.put(65535, 65535) + buff.ensureSize(0, 1) + buff.put(0, 0) + + # index 2 will not fit in buffer of size 2 so it will need to be expanded to 4 + buff.ensureSize(1, 2) + buff.put(1, 1) + + check: + buff.len() == 4 + + buff.ensureSize(2, 3) + buff.put(2, 2) + # index 4 will not fit in buffer size 4 so it will need to expanded + buff.ensureSize(3, 4) + buff.put(3, 3) + + # all elements should be available thorugh old indexes + check: + buff.get(65535) == some(65535) + buff.get(0) == some(0) + buff.get(1) == some(1) + buff.get(2) == some(2) + buff.get(3) == some(3) + buff.len() == 8 + + var elemsCounter = 0 + for elem in buff.items: + inc elemsCounter + check: + elemsCounter == 8 diff --git a/vendor/nim-eth/tests/utp/test_discv5_protocol.nim b/vendor/nim-eth/tests/utp/test_discv5_protocol.nim index 3c238e31a..d35cb5192 100644 --- a/vendor/nim-eth/tests/utp/test_discv5_protocol.nim +++ b/vendor/nim-eth/tests/utp/test_discv5_protocol.nim @@ -8,20 +8,16 @@ import std/options, - chronos, bearssl, + chronos, stew/shims/net, stew/byteutils, testutils/unittests, ../../eth/p2p/discoveryv5/[enr, node, routing_table], ../../eth/p2p/discoveryv5/protocol as discv5_protocol, ../../eth/utp/utp_discv5_protocol, ../../eth/keys, + ../../eth/utp/utp_router as rt, ../p2p/discv5_test_helper -proc generateByteArray(rng: var BrHmacDrbgContext, length: int): seq[byte] = - var bytes = newSeq[byte](length) - brHmacDrbgGenerate(rng, bytes) - return bytes - procSuite "Utp protocol over discovery v5 tests": let rng = newRng() let utpProtId = "test-utp".toBytes() @@ -70,6 +66,41 @@ procSuite "Utp protocol over discovery v5 tests": await node1.closeWait() await node2.closeWait() + proc cbUserData(server: UtpRouter[NodeAddress], client: UtpSocket[NodeAddress]): Future[void] = + let queue = rt.getUserData[NodeAddress, AsyncQueue[UtpSocket[NodeAddress]]](server) + queue.addLast(client) + + asyncTest "Provide user data pointer and use it in callback": + let + queue = newAsyncQueue[UtpSocket[NodeAddress]]() + node1 = initDiscoveryNode( + rng, PrivateKey.random(rng[]), localAddress(20302)) + node2 = initDiscoveryNode( + rng, PrivateKey.random(rng[]), localAddress(20303)) + + # constructor which uses connection callback and user data pointer as ref + utp1 = UtpDiscv5Protocol.new(node1, utpProtId, cbUserData, queue) + utp2 = UtpDiscv5Protocol.new(node2, utpProtId, cbUserData, queue) + + # nodes must have session between each other + check: + (await node1.ping(node2.localNode)).isOk() + + let clientSocketResult = await utp1.connectTo(NodeAddress.init(node2.localNode).unsafeGet()) + let clientSocket = clientSocketResult.get() + let serverSocket = await queue.get() + + check: + clientSocket.isConnected() + # in this test we do not configure the socket to be connected just after + # accepting incoming connection + not serverSocket.isConnected() + + await clientSocket.destroyWait() + await serverSocket.destroyWait() + await node1.closeWait() + await node2.closeWait() + asyncTest "Success write data over packet size to remote host": let queue = newAsyncQueue[UtpSocket[NodeAddress]]() @@ -91,7 +122,7 @@ procSuite "Utp protocol over discovery v5 tests": let serverSocket = await queue.get() - let bytesToTransfer = generateByteArray(rng[], numOfBytes) + let bytesToTransfer = rng[].generateBytes(numOfBytes) let written = await clientSocket.write(bytesToTransfer) let received = await serverSocket.read(numOfBytes) @@ -127,6 +158,7 @@ procSuite "Utp protocol over discovery v5 tests": node2, utpProtId, registerIncomingSocketCallback(queue), + nil, allowOneIdCallback(allowedId), SocketConfig.init()) diff --git a/vendor/nim-eth/tests/utp/test_protocol.nim b/vendor/nim-eth/tests/utp/test_protocol.nim index d39207fce..d7dd1b8a2 100644 --- a/vendor/nim-eth/tests/utp/test_protocol.nim +++ b/vendor/nim-eth/tests/utp/test_protocol.nim @@ -8,10 +8,10 @@ import sequtils, - chronos, bearssl, + chronos, testutils/unittests, ./test_utils, - ../../eth/utp/utp_router, + ../../eth/utp/utp_router as rt, ../../eth/utp/utp_protocol, ../../eth/keys @@ -147,10 +147,43 @@ procSuite "Utp protocol over udp tests": await utpProt1.shutdownWait() await utpProt2.shutdownWait() + + proc cbUserData(server: UtpRouter[TransportAddress], client: UtpSocket[TransportAddress]): Future[void] = + let q = rt.getUserData[TransportAddress, AsyncQueue[UtpSocket[TransportAddress]]](server) + q.addLast(client) + + asyncTest "Provide user data pointer and use it in callback": + let incomingConnections = newAsyncQueue[UtpSocket[TransportAddress]]() + let address = initTAddress("127.0.0.1", 9079) + let utpProt1 = UtpProtocol.new(cbUserData, address, incomingConnections) + + let address1 = initTAddress("127.0.0.1", 9080) + let utpProt2 = UtpProtocol.new(cbUserData, address1, incomingConnections) + + let connResult = await utpProt1.connectTo(address1) + + check: + connResult.isOk() + + let clientSocket = connResult.get() + # this future will be completed when we called accepted connection callback + let serverSocket = await incomingConnections.get() + + check: + clientSocket.isConnected() + # after successful connection outgoing buffer should be empty as syn packet + # should be correctly acked + clientSocket.numPacketsInOutGoingBuffer() == 0 + + not serverSocket.isConnected() + + await utpProt1.shutdownWait() + await utpProt2.shutdownWait() + asyncTest "Fail to connect to offline remote host": let server1Called = newAsyncEvent() let address = initTAddress("127.0.0.1", 9079) - let utpProt1 = UtpProtocol.new(setAcceptedCallback(server1Called), address , SocketConfig.init(milliseconds(200))) + let utpProt1 = UtpProtocol.new(setAcceptedCallback(server1Called), address , nil, SocketConfig.init(milliseconds(200))) let address1 = initTAddress("127.0.0.1", 9080) @@ -174,7 +207,7 @@ procSuite "Utp protocol over udp tests": asyncTest "Success connect to remote host which initialy was offline": let server1Called = newAsyncEvent() let address = initTAddress("127.0.0.1", 9079) - let utpProt1 = UtpProtocol.new(setAcceptedCallback(server1Called), address, SocketConfig.init(milliseconds(500))) + let utpProt1 = UtpProtocol.new(setAcceptedCallback(server1Called), address, nil, SocketConfig.init(milliseconds(500))) let address1 = initTAddress("127.0.0.1", 9080) @@ -210,7 +243,7 @@ procSuite "Utp protocol over udp tests": # Server socket is not in connected state, until first data transfer (not s.serverSocket.isConnected()) - let bytesToTransfer = generateByteArray(rng[], 100) + let bytesToTransfer = rng[].generateBytes(100) let bytesReceivedFromClient = await transferData(s.clientSocket, s.serverSocket, bytesToTransfer) @@ -237,7 +270,7 @@ procSuite "Utp protocol over udp tests": (not s.serverSocket.isConnected()) # 5000 bytes is over maximal packet size - let bytesToTransfer = generateByteArray(rng[], 5000) + let bytesToTransfer = rng[].generateBytes(5000) let bytesReceivedFromClient = await transferData(s.clientSocket, s.serverSocket, bytesToTransfer) let bytesReceivedFromServer = await transferData(s.serverSocket, s.clientSocket, bytesToTransfer) @@ -266,14 +299,14 @@ procSuite "Utp protocol over udp tests": # 5000 bytes is over maximal packet size - let bytesToTransfer = generateByteArray(rng[], 5000) + let bytesToTransfer = rng[].generateBytes(5000) let written = await s.clientSocket.write(bytesToTransfer) check: written.get() == len(bytesToTransfer) - let bytesToTransfer1 = generateByteArray(rng[], 5000) + let bytesToTransfer1 = rng[].generateBytes(5000) let written1 = await s.clientSocket.write(bytesToTransfer1) @@ -301,8 +334,8 @@ procSuite "Utp protocol over udp tests": s.clientSocket2.numPacketsInOutGoingBuffer() == 0 let numBytesToTransfer = 5000 - let client1Data = generateByteArray(rng[], numBytesToTransfer) - let client2Data = generateByteArray(rng[], numBytesToTransfer) + let client1Data = rng[].generateBytes(numBytesToTransfer) + let client2Data = rng[].generateBytes(numBytesToTransfer) discard s.clientSocket1.write(client1Data) discard s.clientSocket2.write(client2Data) @@ -327,7 +360,7 @@ procSuite "Utp protocol over udp tests": # Server socket is not in connected state, until first data transfer (not s.serverSocket.isConnected()) - let bytesToTransfer = generateByteArray(rng[], 100) + let bytesToTransfer = rng[].generateBytes(100) let bytesReceivedFromClient = await transferData(s.clientSocket, s.serverSocket, bytesToTransfer) @@ -362,9 +395,9 @@ procSuite "Utp protocol over udp tests": # Server socket is not in connected state, until first data transfer (not s.serverSocket.isConnected()) - let bytesToTransfer1 = generateByteArray(rng[], 1000) - let bytesToTransfer2 = generateByteArray(rng[], 1000) - let bytesToTransfer3 = generateByteArray(rng[], 1000) + let bytesToTransfer1 = rng[].generateBytes(1000) + let bytesToTransfer2 = rng[].generateBytes(1000) + let bytesToTransfer3 = rng[].generateBytes(1000) let w1 = await s.clientSocket.write(bytesToTransfer1) let w2 = await s.clientSocket.write(bytesToTransfer2) @@ -387,17 +420,18 @@ procSuite "Utp protocol over udp tests": var server1Called = newAsyncEvent() let address1 = initTAddress("127.0.0.1", 9079) let utpProt1 = - UtpProtocol.new(setAcceptedCallback(server1Called), address1, SocketConfig.init(lowSynTimeout)) + UtpProtocol.new(setAcceptedCallback(server1Called), address1, nil, SocketConfig.init(lowSynTimeout)) let address2 = initTAddress("127.0.0.1", 9080) let utpProt2 = - UtpProtocol.new(registerIncomingSocketCallback(serverSockets), address2, SocketConfig.init(lowSynTimeout)) + UtpProtocol.new(registerIncomingSocketCallback(serverSockets), address2, nil, SocketConfig.init(lowSynTimeout)) let address3 = initTAddress("127.0.0.1", 9081) let utpProt3 = UtpProtocol.new( registerIncomingSocketCallback(serverSockets), address3, + nil, SocketConfig.init(), allowOneIdCallback(allowedId) ) @@ -424,7 +458,7 @@ procSuite "Utp protocol over udp tests": asyncTest "Success data transfer of a lot of data should increase available window on sender side": let s = await initClientServerScenario() - + let startMaxWindow = 2 * s.clientSocket.getSocketConfig().payloadSize check: s.clientSocket.isConnected() # initially window has value equal to some pre configured constant @@ -436,7 +470,7 @@ procSuite "Utp protocol over udp tests": (not s.serverSocket.isConnected()) # big transfer of 50kb - let bytesToTransfer = generateByteArray(rng[], 50000) + let bytesToTransfer = rng[].generateBytes(50000) let bytesReceivedFromClient = await transferData(s.clientSocket, s.serverSocket, bytesToTransfer) @@ -455,6 +489,7 @@ procSuite "Utp protocol over udp tests": asyncTest "Not used socket should decay its max send window": let s = await initClientServerScenario() + let startMaxWindow = 2 * s.clientSocket.getSocketConfig().payloadSize check: s.clientSocket.isConnected() @@ -467,7 +502,7 @@ procSuite "Utp protocol over udp tests": (not s.serverSocket.isConnected()) # big transfer of 50kb - let bytesToTransfer = generateByteArray(rng[], 50000) + let bytesToTransfer = rng[].generateBytes(50000) let bytesReceivedFromClient = await transferData(s.clientSocket, s.serverSocket, bytesToTransfer) diff --git a/vendor/nim-eth/tests/utp/test_protocol_integration.nim b/vendor/nim-eth/tests/utp/test_protocol_integration.nim index 63fad08b4..b03fbdbff 100644 --- a/vendor/nim-eth/tests/utp/test_protocol_integration.nim +++ b/vendor/nim-eth/tests/utp/test_protocol_integration.nim @@ -7,17 +7,15 @@ {.used.} import - std/[sequtils, tables, options, sugar], - chronos, bearssl, + std/[tables, options], + chronos, testutils/unittests, - ./test_utils, ../../eth/utp/utp_router, ../../eth/utp/utp_protocol, ../../eth/keys, ../../eth/p2p/discoveryv5/random2 - -proc connectTillSuccess(p: UtpProtocol, to: TransportAddress, maxTries: int = 20): Future[UtpSocket[TransportAddress]] {.async.} = +proc connectTillSuccess(p: UtpProtocol, to: TransportAddress, maxTries: int = 20): Future[UtpSocket[TransportAddress]] {.async.} = var i = 0 while true: let res = await p.connectTo(to) @@ -31,7 +29,7 @@ proc connectTillSuccess(p: UtpProtocol, to: TransportAddress, maxTries: int = 20 proc buildAcceptConnection( t: ref Table[UtpSocketKey[TransportAddress], UtpSocket[TransportAddress]] - ): AcceptConnectionCallback[TransportAddress] = + ): AcceptConnectionCallback[TransportAddress] = return ( proc (server: UtpRouter[TransportAddress], client: UtpSocket[TransportAddress]): Future[void] = let fut = newFuture[void]() @@ -42,7 +40,7 @@ proc buildAcceptConnection( ) proc getServerSocket( - t: ref Table[UtpSocketKey[TransportAddress], UtpSocket[TransportAddress]], + t: ref Table[UtpSocketKey[TransportAddress], UtpSocket[TransportAddress]], clientAddress: TransportAddress, clientConnectionId: uint16): Option[UtpSocket[TransportAddress]] = let serverSocketKey = UtpSocketKey[TransportAddress](remoteAddress: clientAddress, rcvId: clientConnectionId + 1) @@ -68,27 +66,27 @@ procSuite "Utp protocol over udp tests with loss and delays": ) ) - proc testScenario(maxDelay: int, dropRate: int, cfg: SocketConfig = SocketConfig.init()): + proc testScenario(maxDelay: int, dropRate: int, cfg: SocketConfig = SocketConfig.init()): Future[( - UtpProtocol, - UtpSocket[TransportAddress], - UtpProtocol, + UtpProtocol, + UtpSocket[TransportAddress], + UtpProtocol, UtpSocket[TransportAddress]) ] {.async.} = var connections1 = newTable[UtpSocketKey[TransportAddress], UtpSocket[TransportAddress]]() let address1 = initTAddress("127.0.0.1", 9080) - let utpProt1 = + let utpProt1 = UtpProtocol.new( - buildAcceptConnection(connections1), + buildAcceptConnection(connections1), address1, socketConfig = cfg, - sendCallbackBuilder = sendBuilder(maxDelay, dropRate), + sendCallbackBuilder = sendBuilder(maxDelay, dropRate), rng = rng) var connections2 = newTable[UtpSocketKey[TransportAddress], UtpSocket[TransportAddress]]() let address2 = initTAddress("127.0.0.1", 9081) - let utpProt2 = + let utpProt2 = UtpProtocol.new( buildAcceptConnection(connections2), address2, @@ -112,20 +110,19 @@ procSuite "Utp protocol over udp tests with loss and delays": cfg: SocketConfig proc init( - T: type TestCase, - maxDelay: int, - dropRate: int, + T: type TestCase, + maxDelay: int, + dropRate: int, bytesToTransfer: int, cfg: SocketConfig = SocketConfig.init(), bytesPerRead: int = 0): TestCase = TestCase(maxDelay: maxDelay, dropRate: dropRate, bytesToTransfer: bytesToTransfer, cfg: cfg, bytesPerRead: bytesPerRead) let testCases = @[ - TestCase.init(45, 10, 40000), - TestCase.init(25, 15, 40000), + TestCase.init(15, 3, 40000), # super small recv buffer which will be constantly on the brink of being full - TestCase.init(15, 5, 40000, SocketConfig.init(optRcvBuffer = uint32(6000), remoteWindowResetTimeout = seconds(5))), - TestCase.init(15, 10, 40000, SocketConfig.init(optRcvBuffer = uint32(6000), remoteWindowResetTimeout = seconds(5))) + TestCase.init(10, 3, 40000, SocketConfig.init(optRcvBuffer = uint32(10000), remoteWindowResetTimeout = seconds(5))), + TestCase.init(10, 6, 40000, SocketConfig.init(optRcvBuffer = uint32(10000), remoteWindowResetTimeout = seconds(5))) ] asyncTest "Write and Read large data in different network conditions": @@ -135,10 +132,10 @@ procSuite "Utp protocol over udp tests with loss and delays": clientProtocol, clientSocket, serverProtocol, - serverSocket) = await testScenario(testCase.maxDelay, testCase.dropRate, testcase.cfg) + serverSocket) = await testScenario(testCase.maxDelay, testCase.dropRate, testCase.cfg) let smallBytes = 10 - let smallBytesToTransfer = generateByteArray(rng[], smallBytes) + let smallBytesToTransfer = rng[].generateBytes(smallBytes) # first transfer and read to make server socket connecteced let write1 = await clientSocket.write(smallBytesToTransfer) let read1 = await serverSocket.read(smallBytes) @@ -148,16 +145,15 @@ procSuite "Utp protocol over udp tests with loss and delays": read1 == smallBytesToTransfer let numBytes = testCase.bytesToTransfer - let bytesToTransfer = generateByteArray(rng[], numBytes) + let bytesToTransfer = rng[].generateBytes(numBytes) discard clientSocket.write(bytesToTransfer) discard serverSocket.write(bytesToTransfer) - + let serverReadFut = serverSocket.read(numBytes) let clientReadFut = clientSocket.read(numBytes) - yield serverReadFut - yield clientReadFut + await allFutures(serverReadFut, clientReadFut) let clientRead = clientReadFut.read() let serverRead = serverReadFut.read() @@ -165,15 +161,15 @@ procSuite "Utp protocol over udp tests with loss and delays": check: clientRead == bytesToTransfer serverRead == bytesToTransfer - + await clientProtocol.shutdownWait() await serverProtocol.shutdownWait() let testCases1 = @[ # small buffers so it will fill up between reads - TestCase.init(15, 5, 40000, SocketConfig.init(optRcvBuffer = uint32(6000), remoteWindowResetTimeout = seconds(5)), 10000), - TestCase.init(15, 10, 40000, SocketConfig.init(optRcvBuffer = uint32(6000), remoteWindowResetTimeout = seconds(5)), 10000), - TestCase.init(15, 15, 40000, SocketConfig.init(optRcvBuffer = uint32(6000), remoteWindowResetTimeout = seconds(5)), 10000) + TestCase.init(5, 3, 40000, SocketConfig.init(optRcvBuffer = uint32(10000), remoteWindowResetTimeout = seconds(5)), 10000), + TestCase.init(10, 6, 40000, SocketConfig.init(optRcvBuffer = uint32(10000), remoteWindowResetTimeout = seconds(5)), 10000), + TestCase.init(15, 6, 40000, SocketConfig.init(optRcvBuffer = uint32(10000), remoteWindowResetTimeout = seconds(5)), 10000) ] proc readWithMultipleReads(s: UtpSocket[TransportAddress], numOfReads: int, bytesPerRead: int): Future[seq[byte]] {.async.}= @@ -184,7 +180,7 @@ procSuite "Utp protocol over udp tests with loss and delays": res.add(bytes) inc i return res - + asyncTest "Write and Read large data in different network conditions split over several reads": for testCase in testCases1: @@ -192,10 +188,10 @@ procSuite "Utp protocol over udp tests with loss and delays": clientProtocol, clientSocket, serverProtocol, - serverSocket) = await testScenario(testCase.maxDelay, testCase.dropRate, testcase.cfg) + serverSocket) = await testScenario(testCase.maxDelay, testCase.dropRate, testCase.cfg) let smallBytes = 10 - let smallBytesToTransfer = generateByteArray(rng[], smallBytes) + let smallBytesToTransfer = rng[].generateBytes(smallBytes) # first transfer and read to make server socket connecteced let write1 = await clientSocket.write(smallBytesToTransfer) let read1 = await serverSocket.read(smallBytes) @@ -204,18 +200,16 @@ procSuite "Utp protocol over udp tests with loss and delays": read1 == smallBytesToTransfer let numBytes = testCase.bytesToTransfer - let bytesToTransfer = generateByteArray(rng[], numBytes) + let bytesToTransfer = rng[].generateBytes(numBytes) discard clientSocket.write(bytesToTransfer) discard serverSocket.write(bytesToTransfer) - + let numOfReads = int(testCase.bytesToTransfer / testCase.bytesPerRead) let serverReadFut = serverSocket.readWithMultipleReads(numOfReads, testCase.bytesPerRead) let clientReadFut = clientSocket.readWithMultipleReads(numOfReads, testCase.bytesPerRead) - yield serverReadFut - - yield clientReadFut + await allFutures(serverReadFut, clientReadFut) let clientRead = clientReadFut.read() let serverRead = serverReadFut.read() @@ -228,10 +222,9 @@ procSuite "Utp protocol over udp tests with loss and delays": await serverProtocol.shutdownWait() let testCase2 = @[ - TestCase.init(45, 0, 40000), - TestCase.init(45, 0, 80000), - TestCase.init(25, 15, 40000), - TestCase.init(15, 5, 40000, SocketConfig.init(optRcvBuffer = uint32(10000), remoteWindowResetTimeout = seconds(5))) + TestCase.init(10, 0, 80000), + TestCase.init(10, 3, 40000), + TestCase.init(15, 6, 40000, SocketConfig.init(optRcvBuffer = uint32(10000), remoteWindowResetTimeout = seconds(5))) ] asyncTest "Write large data and read till EOF": @@ -240,11 +233,11 @@ procSuite "Utp protocol over udp tests with loss and delays": clientProtocol, clientSocket, serverProtocol, - serverSocket) = await testScenario(testCase.maxDelay, testCase.dropRate, testcase.cfg) + serverSocket) = await testScenario(testCase.maxDelay, testCase.dropRate, testCase.cfg) let numBytes = testCase.bytesToTransfer - let bytesToTransfer = generateByteArray(rng[], numBytes) + let bytesToTransfer = rng[].generateBytes(numBytes) discard await clientSocket.write(bytesToTransfer) clientSocket.close() diff --git a/vendor/nim-eth/tests/utp/test_utils.nim b/vendor/nim-eth/tests/utp/test_utils.nim index 556b55859..962a31a08 100644 --- a/vendor/nim-eth/tests/utp/test_utils.nim +++ b/vendor/nim-eth/tests/utp/test_utils.nim @@ -9,11 +9,6 @@ type AssertionCallback = proc(): bool {.gcsafe, raises: [Defect].} let testBufferSize = 1024'u32 let defaultRcvOutgoingId = 314'u16 -proc generateByteArray*(rng: var BrHmacDrbgContext, length: int): seq[byte] = - var bytes = newSeq[byte](length) - brHmacDrbgGenerate(rng, bytes) - return bytes - proc waitUntil*(f: AssertionCallback): Future[void] {.async.} = while true: let res = f() @@ -65,7 +60,7 @@ template connectOutGoingSocketWithIncoming*( let incomingSocket = newIncomingSocket[TransportAddress]( testAddress, - initTestSnd(incomingQueue), + initTestSnd(incomingQueue), cfg, initialPacket.header.connectionId, initialPacket.header.seqNr, @@ -77,9 +72,9 @@ template connectOutGoingSocketWithIncoming*( let responseAck = await incomingQueue.get() await outgoingSocket.processPacket(responseAck) - + await waitUntil(proc (): bool = outgoingSocket.isConnected()) - + check: outgoingSocket.isConnected() @@ -91,7 +86,7 @@ proc generateDataPackets*( initialSeqNr: uint16, connectionId: uint16, ackNr: uint16, - rng: var BrHmacDrbgContext): seq[Packet] = + rng: var HmacDrbgContext): seq[Packet] = let packetSize = 100 var packets = newSeq[Packet]() var i = 0'u16 @@ -101,7 +96,7 @@ proc generateDataPackets*( connectionId, ackNr, testBufferSize, - generateByteArray(rng, packetSize), + rng.generateBytes(packetSize), 0 ) packets.add(packet) diff --git a/vendor/nim-eth/tests/utp/test_utp_router.nim b/vendor/nim-eth/tests/utp/test_utp_router.nim index 75b6816e3..6cea6ec16 100644 --- a/vendor/nim-eth/tests/utp/test_utp_router.nim +++ b/vendor/nim-eth/tests/utp/test_utp_router.nim @@ -8,7 +8,7 @@ import std/[hashes, options], - chronos, bearssl, chronicles, + chronos, chronicles, testutils/unittests, ./test_utils, ../../eth/utp/utp_router, @@ -87,7 +87,7 @@ procSuite "Utp router unit tests": asyncTest "Router should create new incoming socket when receiving not known syn packet": let q = newAsyncQueue[UtpSocket[int]]() - let router = UtpRouter[int].new(registerIncomingSocketCallback(q), SocketConfig.init(), rng) + let router = UtpRouter[int].new(registerIncomingSocketCallback(q), nil, nil, SocketConfig.init(), rng) router.sendCb = testSend let encodedSyn = encodePacket(synPacket(10, 10, 10)) @@ -96,6 +96,25 @@ procSuite "Utp router unit tests": check: router.len() == 1 + asyncTest "Router should not create new incoming connections when hitting connections limit": + let q = newAsyncQueue[UtpSocket[int]]() + let connectionsLimit = 2 + let customConfig = SocketConfig.init(maxNumberOfOpenConnections = connectionsLimit) + let router = UtpRouter[int].new(registerIncomingSocketCallback(q), customConfig, rng) + router.sendCb = testSend + + var synPackets: seq[seq[byte]] + + for i in 1..connectionsLimit+5: + let encodedSyn = encodePacket(synPacket(10, uint16(i), 10)) + synPackets.add(encodedSyn) + + for p in synPackets: + await router.processIncomingBytes(p, testSender) + + check: + router.len() == connectionsLimit + asyncTest "Incoming connection should be closed when not receving data for period of time when configured": let q = newAsyncQueue[UtpSocket[int]]() let router = @@ -193,7 +212,6 @@ procSuite "Utp router unit tests": check: socket.isConnected() - asyncTest "Router should create new incoming socket when receiving same syn packet from diffrent sender": let q = newAsyncQueue[UtpSocket[int]]() let router = UtpRouter[int].new(registerIncomingSocketCallback(q), SocketConfig.init(), rng) @@ -312,6 +330,8 @@ procSuite "Utp router unit tests": let connectResult = await connectFuture + await waitUntil(proc (): bool = router.len() == 0) + check: connectResult.isErr() connectResult.error().kind == ConnectionTimedOut @@ -333,6 +353,8 @@ procSuite "Utp router unit tests": await connectFuture.cancelAndWait() + await waitUntil(proc (): bool = router.len() == 0) + check: router.len() == 0 @@ -352,7 +374,7 @@ procSuite "Utp router unit tests": check: connectResult.isErr() - # even though send is failing we will just finish with timeout, + # even though send is failing we will just finish with timeout, connectResult.error().kind == ConnectionTimedOut router.len() == 0 diff --git a/vendor/nim-eth/tests/utp/test_utp_socket.nim b/vendor/nim-eth/tests/utp/test_utp_socket.nim index fbae5f86a..739f1089b 100644 --- a/vendor/nim-eth/tests/utp/test_utp_socket.nim +++ b/vendor/nim-eth/tests/utp/test_utp_socket.nim @@ -1,4 +1,4 @@ -# Copyright (c) 2020-2021 Status Research & Development GmbH +# Copyright (c) 2020-2022 Status Research & Development GmbH # Licensed and distributed under either of # * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). # * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). @@ -8,7 +8,7 @@ import std/[algorithm, random, sequtils, options], - chronos, bearssl, chronicles, + chronos, testutils/unittests, ./test_utils, ../../eth/utp/utp_router, @@ -186,7 +186,7 @@ procSuite "Utp socket unit test": await outgoingSocket.processPacket(p) var sentAcks: seq[Packet] = @[] - + for i in 0'u16..', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}'} + SPACEO + HOTAB @@ -48,6 +48,8 @@ const LSEP = SEPARATORS - BSLASH - DQUOTE - EQUALS - SEMCOL - SPACEO - HOTAB LSEP2 = LSEP - COMMA - FSLASH + LSEP3 = LSEP - FSLASH + CTL2 = CTL - HOTAB # Legend: # [0x81, 0x8D] - markers @@ -153,6 +155,28 @@ const 0xCD, 0x83, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0x0D, 0x0D, # sD: semicolon and spaces ] + # * CTL2 LTOK LSEP3 / \ ; " = SPACE + contentTypeSM = [ + 0xE00, 0xE00, 0x801, 0xE00, 0xE00, 0xE00, 0xE00, 0xE00, 0xE00, 0xE00, # s00: start of media-type + 0xE01, 0xE01, 0x001, 0xE01, 0x802, 0xE01, 0xE01, 0xE01, 0xE01, 0xE01, # s01: media-type and forward slash + 0xE02, 0xE02, 0x803, 0xE02, 0xE02, 0xE02, 0xE02, 0xE02, 0xE02, 0xE02, # s02: forward slash + 0xE03, 0xE03, 0x003, 0xE03, 0xE03, 0xE03, 0x805, 0xE03, 0xE03, 0x804, # s03: media-subtype + 0xE04, 0xE04, 0xE04, 0xE04, 0xE04, 0xE04, 0x005, 0xE04, 0xE04, 0x004, # s04: spaces + 0xE05, 0xE05, 0x806, 0xE05, 0xE05, 0xE05, 0xE05, 0xE05, 0xE05, 0x005, # s05: semicolon and spaces + 0xE06, 0xE06, 0x006, 0xE06, 0xE06, 0xE06, 0xE06, 0xE06, 0x807, 0xE06, # s06: param-name + 0xE07, 0xE07, 0x808, 0xE07, 0xE07, 0xE07, 0x811, 0x80B, 0xE07, 0xE07, # s07: = + 0xE08, 0xE08, 0x008, 0xE08, 0xE08, 0xE08, 0x80A, 0xE08, 0xE08, 0x809, # s08: parm-value-token + 0xE09, 0xE09, 0x806, 0xE09, 0xE09, 0xE09, 0x805, 0xE09, 0xE09, 0x009, # s09: spaces after parm-value-token + 0xE0A, 0xE0A, 0x806, 0xE0A, 0xE0A, 0xE0A, 0xE0A, 0xE0A, 0xE0A, 0x00A, # s0a: semicolon and spaces + 0x80C, 0xE0B, 0x80C, 0x80C, 0x80C, 0x80D, 0x80C, 0x80F, 0x80C, 0x80C, # s0b: starting double quote + 0x00C, 0xE0C, 0x00C, 0x00C, 0x00C, 0x80D, 0x00C, 0x80F, 0x00C, 0x00C, # s0c: parm-value-quote + 0x80E, 0xE0D, 0x80E, 0x80E, 0x80E, 0x80E, 0x80E, 0x80E, 0x80E, 0x80E, # s0d: escaped character + 0x00C, 0xE0E, 0x00C, 0x00C, 0x00C, 0x80D, 0x00C, 0x80F, 0x00C, 0x00C, # s0e: parm-value-quote + 0xE0F, 0xE0F, 0xE0F, 0xE0F, 0xE0F, 0xE0F, 0x810, 0xE0F, 0xE0F, 0x00F, # s0f: spaces after parm-value-quote + 0xE10, 0xE10, 0x806, 0xE10, 0xE10, 0xE10, 0xE10, 0xE10, 0xE10, 0x010, # s10: semicolon and spaces + 0xE11, 0xE11, 0x806, 0xE11, 0xE11, 0xE11, 0xE11, 0xE11, 0xE11, 0x011 # s11: empty value, semicolon and spaces + ] + # * LTOKN LSEP2 / \ , ; " = SPACE acceptSM = [ 0xE00, 0x801, 0xE00, 0xE00, 0xE00, 0x000, 0xE00, 0xE00, 0xE00, 0xE00, # s00: start of media-type @@ -295,6 +319,7 @@ type length*: int ## HTTP headers length ContentDispositionHeader* = object + ## `Content-Disposition` header data: seq[byte] state*: int status*: HttpStatus @@ -324,10 +349,19 @@ type AcceptInfo* = object data*: seq[AcceptMediaItem] + ContentTypeData* = object + ## `Content-Type` header data + state*: int + status*: HttpStatus + mediaType*: MediaType + params*: seq[tuple[name: string, value: string]] + HttpReqRespHeader* = HttpRequestHeader | HttpResponseHeader | HttpHeadersList BChar* = byte | char +proc toString[T: BChar](data: openArray[T], start, stop: int): string + template processHeaders(sm: untyped, state: var int, ch: char): int = let code = case ch @@ -411,6 +445,33 @@ template processAcceptHeader(sm: untyped, state: var int, ch: char): int = state = newstate and 0xFF newstate +template processContentType(sm: untyped, state: var int, ch: char): int = + let code = + case ch + of CTL2: + 1 + of LTOKEN: + 2 + of LSEP3: + 3 + of FSLASH: + 4 + of BSLASH: + 5 + of SEMCOL: + 6 + of DQUOTE: + 7 + of EQUALS: + 8 + of SPACEO: + 9 + else: + 0 + let newstate = sm[(state shl 3) + (state shl 1) + code] + state = newstate and 0xFF + newstate + proc processMethod[T: BChar](data: openArray[T], s, e: int): HttpMethod = let length = e - s + 1 case char(data[s]) @@ -593,7 +654,7 @@ proc parseRequest*[T: BChar](data: openArray[T], res -proc parseRequest*[T: BChar](data: seq[T]): HttpRequestHeader = +proc parseRequest*[T: BChar](data: sink seq[T]): HttpRequestHeader = ## Parse sequence of characters or bytes as HTTP request header. ## ## Note: to prevent unnecessary allocations source array ``data`` will be @@ -604,7 +665,10 @@ proc parseRequest*[T: BChar](data: seq[T]): HttpRequestHeader = ## ## Returns `HttpRequestHeader` instance. var res = parseRequest(data, false) - shallowCopy(res.data, cast[seq[byte]](data)) + when declared(shallowCopy): + shallowCopy(res.data, cast[seq[byte]](data)) + else: + res.data = cast[seq[byte]](data) res proc parseHeaders*[T: BChar](data: openArray[T], @@ -676,7 +740,7 @@ proc parseHeaders*[T: BChar](data: openArray[T], inc(index) res -proc parseHeaders*[T: BChar](data: seq[T]): HttpHeadersList = +proc parseHeaders*[T: BChar](data: sink seq[T]): HttpHeadersList = ## Parse sequence of characters or bytes as HTTP headers list. ## ## Note: to prevent unnecessary allocations source array ``data`` will be @@ -687,7 +751,10 @@ proc parseHeaders*[T: BChar](data: seq[T]): HttpHeadersList = ## ## Returns `HttpHeadersList` instance. var res = parseHeaders(data, false) - shallowCopy(res.data, cast[seq[byte]](data)) + when declared(shallowCopy): + shallowCopy(res.data, cast[seq[byte]](data)) + else: + res.data = cast[seq[byte]](data) res proc parseResponse*[T: BChar](data: openArray[T], @@ -794,7 +861,7 @@ proc parseResponse*[T: BChar](data: openArray[T], inc(index) res -proc parseResponse*[T: BChar](data: seq[T]): HttpResponseHeader = +proc parseResponse*[T: BChar](data: sink seq[T]): HttpResponseHeader = ## Parse sequence of characters or bytes as HTTP response header. ## ## Note: to prevent unnecessary allocations source array ``data`` will be @@ -805,7 +872,10 @@ proc parseResponse*[T: BChar](data: seq[T]): HttpResponseHeader = ## ## Returns `HttpResponseHeader` instance. var res = parseResponse(data, false) - shallowCopy(res.data, cast[seq[byte]](data)) + when declared(shallowCopy): + shallowCopy(res.data, cast[seq[byte]](data)) + else: + res.data = cast[seq[byte]](data) res proc parseDisposition*[T: BChar](data: openArray[T], @@ -813,7 +883,7 @@ proc parseDisposition*[T: BChar](data: openArray[T], ## Parse sequence of characters or bytes of HTTP ``Content-Disposition`` ## header according to RFC6266. ## - ## TODO: Support extended `*` values. + ## TODO: Support extended `*` values. ## ## If `makeCopy` flag is ``true``, procedure will create a copy of ``data`` ## in result. @@ -923,7 +993,7 @@ proc parseDisposition*[T: BChar](data: openArray[T], else: ContentDispositionHeader(status: HttpStatus.Failure) -proc parseDisposition*[T: BChar](data: seq[T]): ContentDispositionHeader = +proc parseDisposition*[T: BChar](data: sink seq[T]): ContentDispositionHeader = ## Parse sequence of characters or bytes of HTTP ``Content-Disposition`` ## header according to RFC6266. ## @@ -935,9 +1005,119 @@ proc parseDisposition*[T: BChar](data: seq[T]): ContentDispositionHeader = ## ## Returns `ContentDispositionHeader` instance. var res = parseDisposition(data, false) - shallowCopy(res.data, cast[seq[byte]](data)) + when declared(shallowCopy): + shallowCopy(res.data, cast[seq[byte]](data)) + else: + res.data = cast[seq[byte]](data) res +proc parseContentType*[T: BChar](data: openArray[T]): ContentTypeData = + ## Parse sequence of characters or bytes of HTTP ``Content-Type`` + ## header according to RFC7231 (section 3.1.1.5). + ## + ## Returns `ContentTypeData` instance. + var + index = 0 + state = 0 + start = -1 + finish = 0 + name = "" + value = "" + + var res = ContentTypeData(status: HttpStatus.Failure) + + if len(data) == 0: + return res + + while index < len(data): + let ps = contentTypeSM.processContentType(state, char(data[index])) + res.state = ps + case ps + of 0x801: + # media-type start + start = index + of 0x802: + # media-type finish + if start == -1: + break + finish = index - 1 + res.mediaType.media = data.toString(start, finish) + start = -1 + of 0x803: + # sub-media-type start + start = index + of 0x804, 0x805: + # sub-media-type finish + if start == -1: + break + finish = index - 1 + res.mediaType.subtype = data.toString(start, finish) + start = -1 + of 0x806: + # parameter name start + start = index + of 0x807: + # parameter name finish + if start == -1: + break + finish = index - 1 + name = data.toString(start, finish) + start = -1 + of 0x808: + start = index + of 0x809, 0x80A: + if start == -1: + break + finish = index - 1 + value = data.toString(start, finish) + res.params.add((name: name, value: value)) + start = -1 + of 0x80C: + value.reset() + value.add(data[index]) + of 0x00C, 0x80E: + value.add(data[index]) + of 0x80F: + res.params.add((name: name, value: value)) + of 0x811: + res.params.add((name: name, value: "")) + of 0x80B, 0x80D, 0x810: + discard + of 0x000..0x00B, 0x00D..0x011: + discard + of 0xE00..0xE10: + break + else: + break + inc(index) + + res.status = + case res.state + of 0x003, 0x803: + if start == -1: + HttpStatus.Failure + else: + res.mediaType.subtype = data.toString(start, index - 1) + HttpStatus.Success + of 0x807: + res.params.add((name: name, value: "")) + HttpStatus.Success + of 0x808, 0x008: + if start == -1: + HttpStatus.Failure + else: + res.params.add((name: name, value: data.toString(start, index - 1))) + HttpStatus.Success + of 0x80F: + HttpStatus.Success + else: + HttpStatus.Failure + + if res.status == HttpStatus.Success: + res + else: + ContentTypeData(status: HttpStatus.Failure) + proc parseAcceptHeader*[T: BChar](data: openArray[T], makeCopy: bool): AcceptHeader = var @@ -1069,12 +1249,12 @@ proc parseAcceptHeader*[T: BChar](data: openArray[T], AcceptHeader(status: HttpStatus.Failure) template success*(reqresp: HttpReqRespHeader | ContentDispositionHeader | - AcceptHeader): bool = + AcceptHeader | ContentTypeData): bool = ## Returns ``true`` is ``reqresp`` was successfully parsed. reqresp.status == HttpStatus.Success template failed*(reqresp: HttpReqRespHeader | ContentDispositionHeader | - AcceptHeader): bool = + AcceptHeader | ContentTypeData): bool = ## Returns ``true`` if ``reqresp`` parsing was failed. reqresp.status == HttpStatus.Failure @@ -1099,7 +1279,7 @@ proc contains*(reqresp: HttpReqRespHeader, header: string): bool = return true return false -proc toString(data: openArray[byte], start, stop: int): string = +proc toString[T: BChar](data: openArray[T], start, stop: int): string = ## Slice a raw data blob into a string ## This is an inclusive slice ## The output string is null-terminated for raw C-compat @@ -1230,6 +1410,30 @@ proc cmp*(x, y: MediaType): int = proc `==`*(x, y: MediaType): bool = cmp(x, y) == 0 +proc isValid*(x: MediaType): bool = + ## Returns ``true`` if MediaType ``x`` is not empty and do not have illegal + ## characters. + if (len(x.media) == 0) or (len(x.subtype) == 0): + false + else: + for ch in x.media: + if ch notin LTOKEN: + return false + for ch in x.subtype: + if ch notin LTOKEN: + return false + true + +proc isWildCard*(x: MediaType): bool = + ## Returns ``true`` if media type ``x`` is not empty and do not have wildcard + ## values in ``media`` or ``subtype``. + ## + ## Values like `*/*` or `application/*` are wildcard types. + if (len(x.media) == 0) or (len(x.subtype) == 0): + false + else: + (x.media == "*") or (x.subtype == "*") + proc `$`*(s: AcceptMediaItem): string = ## Returns string representation of AcceptMediaItem object. if len(s.params) > 0: @@ -1430,6 +1634,52 @@ proc getAcceptInfo*(value: string): Result[AcceptInfo, cstring] = else: err("Invalid Accept header format") +proc getContentType*(value: string): Result[ContentTypeData, cstring] = + let header = parseContentType(value) + if header.success(): + ok(header) + else: + err("Invalid Content-Type header format") + +proc `==`*(a: ContentTypeData, b: MediaType): bool = + if a.status != HttpStatus.Success: + false + else: + a.mediaType == b + +proc `==`*(a: MediaType, b: ContentTypeData): bool = + `==`(b, a) + +proc `==`*(a, b: ContentTypeData): bool = + if (a.status != HttpStatus.Success) or (b.status != HttpStatus.Success): + return false + if a.mediaType != b.mediaType: + return false + if len(a.params) != len(b.params): + return false + if len(a.params) > 0: + proc cmpTuple(a, b: tuple[name: string, value: string]): int = + let res = cmpIgnoreCase(a.name, b.name) + if res != 0: + return res + cmpIgnoreCase(a.value, b.value) + let aparams = a.params.sorted(cmpTuple, SortOrder.Ascending) + let bparams = b.params.sorted(cmpTuple, SortOrder.Ascending) + for index, item in aparams.pairs(): + if cmpTuple(item, bparams[index]) != 0: + return false + true + +proc `$`*(a: ContentTypeData): string = + if a.status != HttpStatus.Success: + "" + else: + let params = a.params.mapIt(it.name & "=\"" & it.value & "\"").join("; ") + if len(params) > 0: + $a.mediaType & "; " & params + else: + $a.mediaType + proc uri*(request: HttpRequestHeader): string = ## Returns HTTP request URI as string from ``request``. if request.success(): diff --git a/vendor/nim-http-utils/tests/mimetypes.txt b/vendor/nim-http-utils/tests/mimetypes.txt new file mode 100644 index 000000000..3d926a9a0 --- /dev/null +++ b/vendor/nim-http-utils/tests/mimetypes.txt @@ -0,0 +1,1983 @@ +application/1d-interleaved-parityfec +application/3gpdash-qoe-report+xml +application/3gppHal+json +application/3gppHalForms+json +application/3gpp-ims+xml +application/A2L +application/ace+cbor +application/ace+json +application/activemessage +application/activity+json +application/aif+cbor +application/aif+json +application/alto-cdni+json +application/alto-cdnifilter+json +application/alto-costmap+json +application/alto-costmapfilter+json +application/alto-directory+json +application/alto-endpointprop+json +application/alto-endpointpropparams+json +application/alto-endpointcost+json +application/alto-endpointcostparams+json +application/alto-error+json +application/alto-networkmapfilter+json +application/alto-networkmap+json +application/alto-propmap+json +application/alto-propmapparams+json +application/alto-updatestreamcontrol+json +application/alto-updatestreamparams+json +application/AML +application/andrew-inset +application/applefile +application/at+jwt +application/ATF +application/ATFX +application/atom+xml +application/atomcat+xml +application/atomdeleted+xml +application/atomicmail +application/atomsvc+xml +application/atsc-dwd+xml +application/atsc-dynamic-event-message +application/atsc-held+xml +application/atsc-rdt+json +application/atsc-rsat+xml +application/ATXML +application/auth-policy+xml +application/automationml-aml+xml +application/automationml-amlx+zip +application/bacnet-xdd+zip +application/batch-SMTP +application/beep+xml +application/calendar+json +application/calendar+xml +application/call-completion +application/CALS-1840 +application/captive+json +application/cbor +application/cbor-seq +application/cccex +application/ccmp+xml +application/ccxml+xml +application/cda+xml +application/CDFX+XML +application/cdmi-capability +application/cdmi-container +application/cdmi-domain +application/cdmi-object +application/cdmi-queue +application/cdni +application/CEA +application/cea-2018+xml +application/cellml+xml +application/cfw +application/city+json +application/clr +application/clue_info+xml +application/clue+xml +application/cms +application/cnrp+xml +application/coap-group+json +application/coap-payload +application/commonground +application/concise-problem-details+cbor +application/conference-info+xml +application/cpl+xml +application/cose +application/cose-key +application/cose-key-set +application/csrattrs +application/csta+xml +application/CSTAdata+xml +application/csvm+json +application/cwl +application/cwl+json +application/cwt +application/cybercash +application/dash+xml +application/dash-patch+xml +application/dashdelta +application/davmount+xml +application/dca-rft +application/DCD +application/dec-dx +application/dialog-info+xml +application/dicom +application/dicom+json +application/dicom+xml +application/DII +application/DIT +application/dns +application/dns+json +application/dns-message +application/dots+cbor +application/dskpp+xml +application/dssc+der +application/dssc+xml +application/dvcs +application/ecmascript +application/EDI-consent +application/EDIFACT +application/EDI-X12 +application/efi +application/elm+json +application/elm+xml +application/EmergencyCallData.cap+xml +application/EmergencyCallData.Comment+xml +application/EmergencyCallData.Control+xml +application/EmergencyCallData.DeviceInfo+xml +application/EmergencyCallData.eCall.MSD +application/EmergencyCallData.ProviderInfo+xml +application/EmergencyCallData.ServiceInfo+xml +application/EmergencyCallData.SubscriberInfo+xml +application/EmergencyCallData.VEDS+xml +application/emma+xml +application/emotionml+xml +application/encaprtp +application/epp+xml +application/epub+zip +application/eshop +application/example +application/exi +application/expect-ct-report+json +application/express +application/fastinfoset +application/fastsoap +application/fdf +application/fdt+xml +application/fhir+json +application/fhir+xml +application/fits +application/flexfec +application/font-sfnt +application/font-tdpfr +application/font-woff +application/framework-attributes+xml +application/geo+json +application/geo+json-seq +application/geopackage+sqlite3 +application/geoxacml+xml +application/gltf-buffer +application/gml+xml +application/gzip +application/H224 +application/held+xml +application/hl7v2+xml +application/http +application/hyperstudio +application/ibe-key-request+xml +application/ibe-pkg-reply+xml +application/ibe-pp-data +application/iges +application/im-iscomposing+xml +application/index +application/index.cmd +application/index.obj +application/index.response +application/index.vnd +application/inkml+xml +application/IOTP +application/ipfix +application/ipp +application/ISUP +application/its+xml +application/javascript +application/jf2feed+json +application/jose +application/jose+json +application/jrd+json +application/jscalendar+json +application/json +application/json-patch+json +application/json-seq +application/jwk+json +application/jwk-set+json +application/jwt +application/kpml-request+xml +application/kpml-response+xml +application/ld+json +application/lgr+xml +application/link-format +application/linkset +application/linkset+json +application/load-control+xml +application/lost+xml +application/lostsync+xml +application/lpf+zip +application/LXF +application/mac-binhex40 +application/macwriteii +application/mads+xml +application/manifest+json +application/marc +application/marcxml+xml +application/mathematica +application/mathml+xml +application/mathml-content+xml +application/mathml-presentation+xml +application/mbms-associated-procedure-description+xml +application/mbms-deregister+xml +application/mbms-envelope+xml +application/mbms-msk-response+xml +application/mbms-msk+xml +application/mbms-protection-description+xml +application/mbms-reception-report+xml +application/mbms-register-response+xml +application/mbms-register+xml +application/mbms-schedule+xml +application/mbms-user-service-description+xml +application/mbox +application/media_control+xml +application/media-policy-dataset+xml +application/mediaservercontrol+xml +application/merge-patch+json +application/metalink4+xml +application/mets+xml +application/MF4 +application/mikey +application/mipc +application/missing-blocks+cbor-seq +application/mmt-aei+xml +application/mmt-usd+xml +application/mods+xml +application/moss-keys +application/moss-signature +application/mosskey-data +application/mosskey-request +application/mp21 +application/mp4 +application/mpeg4-generic +application/mpeg4-iod +application/mpeg4-iod-xmt +application/mrb-consumer+xml +application/mrb-publish+xml +application/msc-ivr+xml +application/msc-mixer+xml +application/msword +application/mud+json +application/multipart-core +application/mxf +application/n-quads +application/n-triples +application/nasdata +application/news-checkgroups +application/news-groupinfo +application/news-transmission +application/nlsml+xml +application/node +application/nss +application/oauth-authz-req+jwt +application/oblivious-dns-message +application/ocsp-request +application/ocsp-response +application/octet-stream +application/ODA +application/odm+xml +application/ODX +application/oebps-package+xml +application/ogg +application/opc-nodeset+xml +application/oscore +application/oxps +application/p21 +application/p21+zip +application/p2p-overlay+xml +application/parityfec +application/passport +application/patch-ops-error+xml +application/pdf +application/PDX +application/pem-certificate-chain +application/pgp-encrypted +application/pgp-keys +application/pgp-signature +application/pidf-diff+xml +application/pidf+xml +application/pkcs10 +application/pkcs7-mime +application/pkcs7-signature +application/pkcs8 +application/pkcs8-encrypted +application/pkcs12 +application/pkix-attr-cert +application/pkix-cert +application/pkix-crl +application/pkix-pkipath +application/pkixcmp +application/pls+xml +application/poc-settings+xml +application/postscript +application/ppsp-tracker+json +application/problem+json +application/problem+xml +application/provenance+xml +application/prs.alvestrand.titrax-sheet +application/prs.cww +application/prs.cyn +application/prs.hpub+zip +application/prs.nprend +application/prs.plucker +application/prs.rdf-xml-crypt +application/prs.xsf+xml +application/pskc+xml +application/pvd+json +application/rdf+xml +application/route-apd+xml +application/route-s-tsid+xml +application/route-usd+xml +application/QSIG +application/raptorfec +application/rdap+json +application/reginfo+xml +application/relax-ng-compact-syntax +application/remote-printing +application/reputon+json +application/resource-lists-diff+xml +application/resource-lists+xml +application/rfc+xml +application/riscos +application/rlmi+xml +application/rls-services+xml +application/rpki-ghostbusters +application/rpki-manifest +application/rpki-publication +application/rpki-roa +application/rpki-updown +application/rtf +application/rtploopback +application/rtx +application/samlassertion+xml +application/samlmetadata+xml +application/sarif-external-properties+json +application/sarif+json +application/sbe +application/sbml+xml +application/scaip+xml +application/scim+json +application/scvp-cv-request +application/scvp-cv-response +application/scvp-vp-request +application/scvp-vp-response +application/sdp +application/secevent+jwt +application/senml-etch+cbor +application/senml-etch+json +application/senml-exi +application/senml+cbor +application/senml+json +application/senml+xml +application/sensml-exi +application/sensml+cbor +application/sensml+json +application/sensml+xml +application/sep-exi +application/sep+xml +application/session-info +application/set-payment +application/set-payment-initiation +application/set-registration +application/set-registration-initiation +application/SGML +application/sgml-open-catalog +application/shf+xml +application/sieve +application/simple-filter+xml +application/simple-message-summary +application/simpleSymbolContainer +application/sipc +application/slate +application/smil +application/smil+xml +application/smpte336m +application/soap+fastinfoset +application/soap+xml +application/sparql-query +application/spdx+json +application/sparql-results+xml +application/spirits-event+xml +application/sql +application/srgs +application/srgs+xml +application/sru+xml +application/ssml+xml +application/stix+json +application/swid+xml +application/tamp-apex-update +application/tamp-apex-update-confirm +application/tamp-community-update +application/tamp-community-update-confirm +application/tamp-error +application/tamp-sequence-adjust +application/tamp-sequence-adjust-confirm +application/tamp-status-query +application/tamp-status-response +application/tamp-update +application/tamp-update-confirm +application/taxii+json +application/td+json +application/tei+xml +application/TETRA_ISI +application/thraud+xml +application/timestamp-query +application/timestamp-reply +application/timestamped-data +application/tlsrpt+gzip +application/tlsrpt+json +application/tnauthlist +application/token-introspection+jwt +application/trickle-ice-sdpfrag +application/trig +application/ttml+xml +application/tve-trigger +application/tzif +application/tzif-leap +application/ulpfec +application/urc-grpsheet+xml +application/urc-ressheet+xml +application/urc-targetdesc+xml +application/urc-uisocketdesc+xml +application/vcard+json +application/vcard+xml +application/vemmi +application/vnd.1000minds.decision-model+xml +application/vnd.3gpp.5gnas +application/vnd.3gpp.access-transfer-events+xml +application/vnd.3gpp.bsf+xml +application/vnd.3gpp.GMOP+xml +application/vnd.3gpp.gtpc +application/vnd.3gpp.interworking-data +application/vnd.3gpp.lpp +application/vnd.3gpp.mc-signalling-ear +application/vnd.3gpp.mcdata-affiliation-command+xml +application/vnd.3gpp.mcdata-info+xml +application/vnd.3gpp.mcdata-msgstore-ctrl-request+xml +application/vnd.3gpp.mcdata-payload +application/vnd.3gpp.mcdata-regroup+xml +application/vnd.3gpp.mcdata-service-config+xml +application/vnd.3gpp.mcdata-signalling +application/vnd.3gpp.mcdata-ue-config+xml +application/vnd.3gpp.mcdata-user-profile+xml +application/vnd.3gpp.mcptt-affiliation-command+xml +application/vnd.3gpp.mcptt-floor-request+xml +application/vnd.3gpp.mcptt-info+xml +application/vnd.3gpp.mcptt-location-info+xml +application/vnd.3gpp.mcptt-mbms-usage-info+xml +application/vnd.3gpp.mcptt-service-config+xml +application/vnd.3gpp.mcptt-signed+xml +application/vnd.3gpp.mcptt-ue-config+xml +application/vnd.3gpp.mcptt-ue-init-config+xml +application/vnd.3gpp.mcptt-user-profile+xml +application/vnd.3gpp.mcvideo-affiliation-command+xml +application/vnd.3gpp.mcvideo-affiliation-info+xml +application/vnd.3gpp.mcvideo-info+xml +application/vnd.3gpp.mcvideo-location-info+xml +application/vnd.3gpp.mcvideo-mbms-usage-info+xml +application/vnd.3gpp.mcvideo-service-config+xml +application/vnd.3gpp.mcvideo-transmission-request+xml +application/vnd.3gpp.mcvideo-ue-config+xml +application/vnd.3gpp.mcvideo-user-profile+xml +application/vnd.3gpp.mid-call+xml +application/vnd.3gpp.ngap +application/vnd.3gpp.pfcp +application/vnd.3gpp.pic-bw-large +application/vnd.3gpp.pic-bw-small +application/vnd.3gpp.pic-bw-var +application/vnd.3gpp-prose-pc3ch+xml +application/vnd.3gpp-prose+xml +application/vnd.3gpp.s1ap +application/vnd.3gpp.sms +application/vnd.3gpp.sms+xml +application/vnd.3gpp.srvcc-ext+xml +application/vnd.3gpp.SRVCC-info+xml +application/vnd.3gpp.state-and-event-info+xml +application/vnd.3gpp.ussd+xml +application/vnd.3gpp-v2x-local-service-information +application/vnd.3gpp2.bcmcsinfo+xml +application/vnd.3gpp2.sms +application/vnd.3gpp2.tcap +application/vnd.3lightssoftware.imagescal +application/vnd.3M.Post-it-Notes +application/vnd.accpac.simply.aso +application/vnd.accpac.simply.imp +application/vnd.acucobol +application/vnd.acucorp +application/vnd.adobe.flash.movie +application/vnd.adobe.formscentral.fcdt +application/vnd.adobe.fxp +application/vnd.adobe.partial-upload +application/vnd.adobe.xdp+xml +application/vnd.aether.imp +application/vnd.afpc.afplinedata +application/vnd.afpc.afplinedata-pagedef +application/vnd.afpc.cmoca-cmresource +application/vnd.afpc.foca-charset +application/vnd.afpc.foca-codedfont +application/vnd.afpc.foca-codepage +application/vnd.afpc.modca +application/vnd.afpc.modca-cmtable +application/vnd.afpc.modca-formdef +application/vnd.afpc.modca-mediummap +application/vnd.afpc.modca-objectcontainer +application/vnd.afpc.modca-overlay +application/vnd.afpc.modca-pagesegment +application/vnd.age +application/vnd.ah-barcode +application/vnd.ahead.space +application/vnd.airzip.filesecure.azf +application/vnd.airzip.filesecure.azs +application/vnd.amadeus+json +application/vnd.amazon.mobi8-ebook +application/vnd.americandynamics.acc +application/vnd.amiga.ami +application/vnd.amundsen.maze+xml +application/vnd.android.ota +application/vnd.anki +application/vnd.anser-web-certificate-issue-initiation +application/vnd.antix.game-component +application/vnd.apache.arrow.file +application/vnd.apache.arrow.stream +application/vnd.apache.thrift.binary +application/vnd.apache.thrift.compact +application/vnd.apache.thrift.json +application/vnd.api+json +application/vnd.aplextor.warrp+json +application/vnd.apothekende.reservation+json +application/vnd.apple.installer+xml +application/vnd.apple.keynote +application/vnd.apple.mpegurl +application/vnd.apple.numbers +application/vnd.apple.pages +application/vnd.arastra.swi +application/vnd.aristanetworks.swi +application/vnd.artisan+json +application/vnd.artsquare +application/vnd.astraea-software.iota +application/vnd.audiograph +application/vnd.autopackage +application/vnd.avalon+json +application/vnd.avistar+xml +application/vnd.balsamiq.bmml+xml +application/vnd.banana-accounting +application/vnd.bbf.usp.error +application/vnd.bbf.usp.msg +application/vnd.bbf.usp.msg+json +application/vnd.balsamiq.bmpr +application/vnd.bekitzur-stech+json +application/vnd.belightsoft.lhzd+zip +application/vnd.belightsoft.lhzl+zip +application/vnd.bint.med-content +application/vnd.biopax.rdf+xml +application/vnd.blink-idb-value-wrapper +application/vnd.blueice.multipass +application/vnd.bluetooth.ep.oob +application/vnd.bluetooth.le.oob +application/vnd.bmi +application/vnd.bpf +application/vnd.bpf3 +application/vnd.businessobjects +application/vnd.byu.uapi+json +application/vnd.cab-jscript +application/vnd.canon-cpdl +application/vnd.canon-lips +application/vnd.capasystems-pg+json +application/vnd.cendio.thinlinc.clientconf +application/vnd.century-systems.tcp_stream +application/vnd.chemdraw+xml +application/vnd.chess-pgn +application/vnd.chipnuts.karaoke-mmd +application/vnd.ciedi +application/vnd.cinderella +application/vnd.cirpack.isdn-ext +application/vnd.citationstyles.style+xml +application/vnd.claymore +application/vnd.cloanto.rp9 +application/vnd.clonk.c4group +application/vnd.cluetrust.cartomobile-config +application/vnd.cluetrust.cartomobile-config-pkg +application/vnd.coffeescript +application/vnd.collabio.xodocuments.document +application/vnd.collabio.xodocuments.document-template +application/vnd.collabio.xodocuments.presentation +application/vnd.collabio.xodocuments.presentation-template +application/vnd.collabio.xodocuments.spreadsheet +application/vnd.collabio.xodocuments.spreadsheet-template +application/vnd.collection.doc+json +application/vnd.collection+json +application/vnd.collection.next+json +application/vnd.comicbook-rar +application/vnd.comicbook+zip +application/vnd.commerce-battelle +application/vnd.commonspace +application/vnd.coreos.ignition+json +application/vnd.cosmocaller +application/vnd.contact.cmsg +application/vnd.crick.clicker +application/vnd.crick.clicker.keyboard +application/vnd.crick.clicker.palette +application/vnd.crick.clicker.template +application/vnd.crick.clicker.wordbank +application/vnd.criticaltools.wbs+xml +application/vnd.cryptii.pipe+json +application/vnd.crypto-shade-file +application/vnd.cryptomator.encrypted +application/vnd.cryptomator.vault +application/vnd.ctc-posml +application/vnd.ctct.ws+xml +application/vnd.cups-pdf +application/vnd.cups-postscript +application/vnd.cups-ppd +application/vnd.cups-raster +application/vnd.cups-raw +application/vnd.curl +application/vnd.cyan.dean.root+xml +application/vnd.cybank +application/vnd.cyclonedx+json +application/vnd.cyclonedx+xml +application/vnd.d2l.coursepackage1p0+zip +application/vnd.d3m-dataset +application/vnd.d3m-problem +application/vnd.dart +application/vnd.data-vision.rdz +application/vnd.datalog +application/vnd.datapackage+json +application/vnd.dataresource+json +application/vnd.dbf +application/vnd.debian.binary-package +application/vnd.dece.data +application/vnd.dece.ttml+xml +application/vnd.dece.unspecified +application/vnd.dece.zip +application/vnd.denovo.fcselayout-link +application/vnd.desmume.movie +application/vnd.dir-bi.plate-dl-nosuffix +application/vnd.dm.delegation+xml +application/vnd.dna +application/vnd.document+json +application/vnd.dolby.mobile.1 +application/vnd.dolby.mobile.2 +application/vnd.doremir.scorecloud-binary-document +application/vnd.dpgraph +application/vnd.dreamfactory +application/vnd.drive+json +application/vnd.dtg.local +application/vnd.dtg.local.flash +application/vnd.dtg.local.html +application/vnd.dvb.ait +application/vnd.dvb.dvbisl+xml +application/vnd.dvb.dvbj +application/vnd.dvb.esgcontainer +application/vnd.dvb.ipdcdftnotifaccess +application/vnd.dvb.ipdcesgaccess +application/vnd.dvb.ipdcesgaccess2 +application/vnd.dvb.ipdcesgpdd +application/vnd.dvb.ipdcroaming +application/vnd.dvb.iptv.alfec-base +application/vnd.dvb.iptv.alfec-enhancement +application/vnd.dvb.notif-aggregate-root+xml +application/vnd.dvb.notif-container+xml +application/vnd.dvb.notif-generic+xml +application/vnd.dvb.notif-ia-msglist+xml +application/vnd.dvb.notif-ia-registration-request+xml +application/vnd.dvb.notif-ia-registration-response+xml +application/vnd.dvb.notif-init+xml +application/vnd.dvb.pfr +application/vnd.dvb.service +application/vnd.dxr +application/vnd.dynageo +application/vnd.dzr +application/vnd.easykaraoke.cdgdownload +application/vnd.ecip.rlp +application/vnd.ecdis-update +application/vnd.eclipse.ditto+json +application/vnd.ecowin.chart +application/vnd.ecowin.filerequest +application/vnd.ecowin.fileupdate +application/vnd.ecowin.series +application/vnd.ecowin.seriesrequest +application/vnd.ecowin.seriesupdate +application/vnd.efi.img +application/vnd.efi.iso +application/vnd.emclient.accessrequest+xml +application/vnd.enliven +application/vnd.enphase.envoy +application/vnd.eprints.data+xml +application/vnd.epson.esf +application/vnd.epson.msf +application/vnd.epson.quickanime +application/vnd.epson.salt +application/vnd.epson.ssf +application/vnd.ericsson.quickcall +application/vnd.espass-espass+zip +application/vnd.eszigno3+xml +application/vnd.etsi.aoc+xml +application/vnd.etsi.asic-s+zip +application/vnd.etsi.asic-e+zip +application/vnd.etsi.cug+xml +application/vnd.etsi.iptvcommand+xml +application/vnd.etsi.iptvdiscovery+xml +application/vnd.etsi.iptvprofile+xml +application/vnd.etsi.iptvsad-bc+xml +application/vnd.etsi.iptvsad-cod+xml +application/vnd.etsi.iptvsad-npvr+xml +application/vnd.etsi.iptvservice+xml +application/vnd.etsi.iptvsync+xml +application/vnd.etsi.iptvueprofile+xml +application/vnd.etsi.mcid+xml +application/vnd.etsi.mheg5 +application/vnd.etsi.overload-control-policy-dataset+xml +application/vnd.etsi.pstn+xml +application/vnd.etsi.sci+xml +application/vnd.etsi.simservs+xml +application/vnd.etsi.timestamp-token +application/vnd.etsi.tsl+xml +application/vnd.etsi.tsl.der +application/vnd.eu.kasparian.car+json +application/vnd.eudora.data +application/vnd.evolv.ecig.profile +application/vnd.evolv.ecig.settings +application/vnd.evolv.ecig.theme +application/vnd.exstream-empower+zip +application/vnd.exstream-package +application/vnd.ezpix-album +application/vnd.ezpix-package +application/vnd.f-secure.mobile +application/vnd.fastcopy-disk-image +application/vnd.familysearch.gedcom+zip +application/vnd.fdsn.mseed +application/vnd.fdsn.seed +application/vnd.ffsns +application/vnd.ficlab.flb+zip +application/vnd.filmit.zfc +application/vnd.fints +application/vnd.firemonkeys.cloudcell +application/vnd.FloGraphIt +application/vnd.fluxtime.clip +application/vnd.font-fontforge-sfd +application/vnd.framemaker +application/vnd.frogans.fnc +application/vnd.frogans.ltf +application/vnd.fsc.weblaunch +application/vnd.fujifilm.fb.docuworks +application/vnd.fujifilm.fb.docuworks.binder +application/vnd.fujifilm.fb.docuworks.container +application/vnd.fujifilm.fb.jfi+xml +application/vnd.fujitsu.oasys +application/vnd.fujitsu.oasys2 +application/vnd.fujitsu.oasys3 +application/vnd.fujitsu.oasysgp +application/vnd.fujitsu.oasysprs +application/vnd.fujixerox.ART4 +application/vnd.fujixerox.ART-EX +application/vnd.fujixerox.ddd +application/vnd.fujixerox.docuworks +application/vnd.fujixerox.docuworks.binder +application/vnd.fujixerox.docuworks.container +application/vnd.fujixerox.HBPL +application/vnd.fut-misnet +application/vnd.futoin+cbor +application/vnd.futoin+json +application/vnd.fuzzysheet +application/vnd.genomatix.tuxedo +application/vnd.genozip +application/vnd.gentics.grd+json +application/vnd.geo+json +application/vnd.geocube+xml +application/vnd.geogebra.file +application/vnd.geogebra.slides +application/vnd.geogebra.tool +application/vnd.geometry-explorer +application/vnd.geonext +application/vnd.geoplan +application/vnd.geospace +application/vnd.gerber +application/vnd.globalplatform.card-content-mgt +application/vnd.globalplatform.card-content-mgt-response +application/vnd.gmx +application/vnd.gnu.taler.exchange+json +application/vnd.gnu.taler.merchant+json +application/vnd.google-earth.kml+xml +application/vnd.google-earth.kmz +application/vnd.gov.sk.e-form+xml +application/vnd.gov.sk.e-form+zip +application/vnd.gov.sk.xmldatacontainer+xml +application/vnd.grafeq +application/vnd.gridmp +application/vnd.groove-account +application/vnd.groove-help +application/vnd.groove-identity-message +application/vnd.groove-injector +application/vnd.groove-tool-message +application/vnd.groove-tool-template +application/vnd.groove-vcard +application/vnd.hal+json +application/vnd.hal+xml +application/vnd.HandHeld-Entertainment+xml +application/vnd.hbci +application/vnd.hc+json +application/vnd.hcl-bireports +application/vnd.hdt +application/vnd.heroku+json +application/vnd.hhe.lesson-player +application/vnd.hp-HPGL +application/vnd.hp-hpid +application/vnd.hp-hps +application/vnd.hp-jlyt +application/vnd.hp-PCL +application/vnd.hp-PCLXL +application/vnd.httphone +application/vnd.hydrostatix.sof-data +application/vnd.hyper-item+json +application/vnd.hyper+json +application/vnd.hyperdrive+json +application/vnd.hzn-3d-crossword +application/vnd.ibm.afplinedata +application/vnd.ibm.electronic-media +application/vnd.ibm.MiniPay +application/vnd.ibm.modcap +application/vnd.ibm.rights-management +application/vnd.ibm.secure-container +application/vnd.iccprofile +application/vnd.ieee.1905 +application/vnd.igloader +application/vnd.imagemeter.folder+zip +application/vnd.imagemeter.image+zip +application/vnd.immervision-ivp +application/vnd.immervision-ivu +application/vnd.ims.imsccv1p1 +application/vnd.ims.imsccv1p2 +application/vnd.ims.imsccv1p3 +application/vnd.ims.lis.v2.result+json +application/vnd.ims.lti.v2.toolconsumerprofile+json +application/vnd.ims.lti.v2.toolproxy.id+json +application/vnd.ims.lti.v2.toolproxy+json +application/vnd.ims.lti.v2.toolsettings+json +application/vnd.ims.lti.v2.toolsettings.simple+json +application/vnd.informedcontrol.rms+xml +application/vnd.infotech.project +application/vnd.infotech.project+xml +application/vnd.informix-visionary +application/vnd.innopath.wamp.notification +application/vnd.insors.igm +application/vnd.intercon.formnet +application/vnd.intergeo +application/vnd.intertrust.digibox +application/vnd.intertrust.nncp +application/vnd.intu.qbo +application/vnd.intu.qfx +application/vnd.ipld.car +application/vnd.ipld.raw +application/vnd.iptc.g2.catalogitem+xml +application/vnd.iptc.g2.conceptitem+xml +application/vnd.iptc.g2.knowledgeitem+xml +application/vnd.iptc.g2.newsitem+xml +application/vnd.iptc.g2.newsmessage+xml +application/vnd.iptc.g2.packageitem+xml +application/vnd.iptc.g2.planningitem+xml +application/vnd.ipunplugged.rcprofile +application/vnd.irepository.package+xml +application/vnd.is-xpr +application/vnd.isac.fcs +application/vnd.jam +application/vnd.iso11783-10+zip +application/vnd.japannet-directory-service +application/vnd.japannet-jpnstore-wakeup +application/vnd.japannet-payment-wakeup +application/vnd.japannet-registration +application/vnd.japannet-registration-wakeup +application/vnd.japannet-setstore-wakeup +application/vnd.japannet-verification +application/vnd.japannet-verification-wakeup +application/vnd.jcp.javame.midlet-rms +application/vnd.jisp +application/vnd.joost.joda-archive +application/vnd.jsk.isdn-ngn +application/vnd.kahootz +application/vnd.kde.karbon +application/vnd.kde.kchart +application/vnd.kde.kformula +application/vnd.kde.kivio +application/vnd.kde.kontour +application/vnd.kde.kpresenter +application/vnd.kde.kspread +application/vnd.kde.kword +application/vnd.kenameaapp +application/vnd.kidspiration +application/vnd.Kinar +application/vnd.koan +application/vnd.kodak-descriptor +application/vnd.las +application/vnd.las.las+json +application/vnd.las.las+xml +application/vnd.laszip +application/vnd.leap+json +application/vnd.liberty-request+xml +application/vnd.llamagraphics.life-balance.desktop +application/vnd.llamagraphics.life-balance.exchange+xml +application/vnd.logipipe.circuit+zip +application/vnd.loom +application/vnd.lotus-1-2-3 +application/vnd.lotus-approach +application/vnd.lotus-freelance +application/vnd.lotus-notes +application/vnd.lotus-organizer +application/vnd.lotus-screencam +application/vnd.lotus-wordpro +application/vnd.macports.portpkg +application/vnd.mapbox-vector-tile +application/vnd.marlin.drm.actiontoken+xml +application/vnd.marlin.drm.conftoken+xml +application/vnd.marlin.drm.license+xml +application/vnd.marlin.drm.mdcf +application/vnd.mason+json +application/vnd.maxar.archive.3tz+zip +application/vnd.maxmind.maxmind-db +application/vnd.mcd +application/vnd.medcalcdata +application/vnd.mediastation.cdkey +application/vnd.meridian-slingshot +application/vnd.MFER +application/vnd.mfmp +application/vnd.micro+json +application/vnd.micrografx.flo +application/vnd.micrografx.igx +application/vnd.microsoft.portable-executable +application/vnd.microsoft.windows.thumbnail-cache +application/vnd.miele+json +application/vnd.mif +application/vnd.minisoft-hp3000-save +application/vnd.mitsubishi.misty-guard.trustweb +application/vnd.Mobius.DAF +application/vnd.Mobius.DIS +application/vnd.Mobius.MBK +application/vnd.Mobius.MQY +application/vnd.Mobius.MSL +application/vnd.Mobius.PLC +application/vnd.Mobius.TXF +application/vnd.mophun.application +application/vnd.mophun.certificate +application/vnd.motorola.flexsuite +application/vnd.motorola.flexsuite.adsi +application/vnd.motorola.flexsuite.fis +application/vnd.motorola.flexsuite.gotap +application/vnd.motorola.flexsuite.kmr +application/vnd.motorola.flexsuite.ttc +application/vnd.motorola.flexsuite.wem +application/vnd.motorola.iprm +application/vnd.mozilla.xul+xml +application/vnd.ms-artgalry +application/vnd.ms-asf +application/vnd.ms-cab-compressed +application/vnd.ms-3mfdocument +application/vnd.ms-excel +application/vnd.ms-excel.addin.macroEnabled.12 +application/vnd.ms-excel.sheet.binary.macroEnabled.12 +application/vnd.ms-excel.sheet.macroEnabled.12 +application/vnd.ms-excel.template.macroEnabled.12 +application/vnd.ms-fontobject +application/vnd.ms-htmlhelp +application/vnd.ms-ims +application/vnd.ms-lrm +application/vnd.ms-office.activeX+xml +application/vnd.ms-officetheme +application/vnd.ms-playready.initiator+xml +application/vnd.ms-powerpoint +application/vnd.ms-powerpoint.addin.macroEnabled.12 +application/vnd.ms-powerpoint.presentation.macroEnabled.12 +application/vnd.ms-powerpoint.slide.macroEnabled.12 +application/vnd.ms-powerpoint.slideshow.macroEnabled.12 +application/vnd.ms-powerpoint.template.macroEnabled.12 +application/vnd.ms-PrintDeviceCapabilities+xml +application/vnd.ms-PrintSchemaTicket+xml +application/vnd.ms-project +application/vnd.ms-tnef +application/vnd.ms-windows.devicepairing +application/vnd.ms-windows.nwprinting.oob +application/vnd.ms-windows.printerpairing +application/vnd.ms-windows.wsd.oob +application/vnd.ms-wmdrm.lic-chlg-req +application/vnd.ms-wmdrm.lic-resp +application/vnd.ms-wmdrm.meter-chlg-req +application/vnd.ms-wmdrm.meter-resp +application/vnd.ms-word.document.macroEnabled.12 +application/vnd.ms-word.template.macroEnabled.12 +application/vnd.ms-works +application/vnd.ms-wpl +application/vnd.ms-xpsdocument +application/vnd.msa-disk-image +application/vnd.mseq +application/vnd.msign +application/vnd.multiad.creator +application/vnd.multiad.creator.cif +application/vnd.musician +application/vnd.music-niff +application/vnd.muvee.style +application/vnd.mynfc +application/vnd.nacamar.ybrid+json +application/vnd.ncd.control +application/vnd.ncd.reference +application/vnd.nearst.inv+json +application/vnd.nebumind.line +application/vnd.nervana +application/vnd.netfpx +application/vnd.neurolanguage.nlu +application/vnd.nimn +application/vnd.nintendo.snes.rom +application/vnd.nintendo.nitro.rom +application/vnd.nitf +application/vnd.noblenet-directory +application/vnd.noblenet-sealer +application/vnd.noblenet-web +application/vnd.nokia.catalogs +application/vnd.nokia.conml+wbxml +application/vnd.nokia.conml+xml +application/vnd.nokia.iptv.config+xml +application/vnd.nokia.iSDS-radio-presets +application/vnd.nokia.landmark+wbxml +application/vnd.nokia.landmark+xml +application/vnd.nokia.landmarkcollection+xml +application/vnd.nokia.ncd +application/vnd.nokia.n-gage.ac+xml +application/vnd.nokia.n-gage.data +application/vnd.nokia.n-gage.symbian.install +application/vnd.nokia.pcd+wbxml +application/vnd.nokia.pcd+xml +application/vnd.nokia.radio-preset +application/vnd.nokia.radio-presets +application/vnd.novadigm.EDM +application/vnd.novadigm.EDX +application/vnd.novadigm.EXT +application/vnd.ntt-local.content-share +application/vnd.ntt-local.file-transfer +application/vnd.ntt-local.ogw_remote-access +application/vnd.ntt-local.sip-ta_remote +application/vnd.ntt-local.sip-ta_tcp_stream +application/vnd.oasis.opendocument.base +application/vnd.oasis.opendocument.chart +application/vnd.oasis.opendocument.chart-template +application/vnd.oasis.opendocument.database +application/vnd.oasis.opendocument.formula +application/vnd.oasis.opendocument.formula-template +application/vnd.oasis.opendocument.graphics +application/vnd.oasis.opendocument.graphics-template +application/vnd.oasis.opendocument.image +application/vnd.oasis.opendocument.image-template +application/vnd.oasis.opendocument.presentation +application/vnd.oasis.opendocument.presentation-template +application/vnd.oasis.opendocument.spreadsheet +application/vnd.oasis.opendocument.spreadsheet-template +application/vnd.oasis.opendocument.text +application/vnd.oasis.opendocument.text-master +application/vnd.oasis.opendocument.text-template +application/vnd.oasis.opendocument.text-web +application/vnd.obn +application/vnd.ocf+cbor +application/vnd.oci.image.manifest.v1+json +application/vnd.oftn.l10n+json +application/vnd.oipf.contentaccessdownload+xml +application/vnd.oipf.contentaccessstreaming+xml +application/vnd.oipf.cspg-hexbinary +application/vnd.oipf.dae.svg+xml +application/vnd.oipf.dae.xhtml+xml +application/vnd.oipf.mippvcontrolmessage+xml +application/vnd.oipf.pae.gem +application/vnd.oipf.spdiscovery+xml +application/vnd.oipf.spdlist+xml +application/vnd.oipf.ueprofile+xml +application/vnd.oipf.userprofile+xml +application/vnd.olpc-sugar +application/vnd.oma.bcast.associated-procedure-parameter+xml +application/vnd.oma.bcast.drm-trigger+xml +application/vnd.oma.bcast.imd+xml +application/vnd.oma.bcast.ltkm +application/vnd.oma.bcast.notification+xml +application/vnd.oma.bcast.provisioningtrigger +application/vnd.oma.bcast.sgboot +application/vnd.oma.bcast.sgdd+xml +application/vnd.oma.bcast.sgdu +application/vnd.oma.bcast.simple-symbol-container +application/vnd.oma.bcast.smartcard-trigger+xml +application/vnd.oma.bcast.sprov+xml +application/vnd.oma.bcast.stkm +application/vnd.oma.cab-address-book+xml +application/vnd.oma.cab-feature-handler+xml +application/vnd.oma.cab-pcc+xml +application/vnd.oma.cab-subs-invite+xml +application/vnd.oma.cab-user-prefs+xml +application/vnd.oma.dcd +application/vnd.oma.dcdc +application/vnd.oma.dd2+xml +application/vnd.oma.drm.risd+xml +application/vnd.oma.group-usage-list+xml +application/vnd.oma.lwm2m+cbor +application/vnd.oma.lwm2m+json +application/vnd.oma.lwm2m+tlv +application/vnd.oma.pal+xml +application/vnd.oma.poc.detailed-progress-report+xml +application/vnd.oma.poc.final-report+xml +application/vnd.oma.poc.groups+xml +application/vnd.oma.poc.invocation-descriptor+xml +application/vnd.oma.poc.optimized-progress-report+xml +application/vnd.oma.push +application/vnd.oma.scidm.messages+xml +application/vnd.oma.xcap-directory+xml +application/vnd.omads-email+xml +application/vnd.omads-file+xml +application/vnd.omads-folder+xml +application/vnd.omaloc-supl-init +application/vnd.oma-scws-config +application/vnd.oma-scws-http-request +application/vnd.oma-scws-http-response +application/vnd.onepager +application/vnd.onepagertamp +application/vnd.onepagertamx +application/vnd.onepagertat +application/vnd.onepagertatp +application/vnd.onepagertatx +application/vnd.onvif.metadata +application/vnd.openblox.game-binary +application/vnd.openblox.game+xml +application/vnd.openeye.oeb +application/vnd.openstreetmap.data+xml +application/vnd.opentimestamps.ots +application/vnd.openxmlformats-officedocument.custom-properties+xml +application/vnd.openxmlformats-officedocument.customXmlProperties+xml +application/vnd.openxmlformats-officedocument.drawing+xml +application/vnd.openxmlformats-officedocument.drawingml.chart+xml +application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml +application/vnd.openxmlformats-officedocument.drawingml.diagramColors+xml +application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml +application/vnd.openxmlformats-officedocument.drawingml.diagramLayout+xml +application/vnd.openxmlformats-officedocument.drawingml.diagramStyle+xml +application/vnd.openxmlformats-officedocument.extended-properties+xml +application/vnd.openxmlformats-officedocument.presentationml.commentAuthors+xml +application/vnd.openxmlformats-officedocument.presentationml.comments+xml +application/vnd.openxmlformats-officedocument.presentationml.handoutMaster+xml +application/vnd.openxmlformats-officedocument.presentationml.notesMaster+xml +application/vnd.openxmlformats-officedocument.presentationml.notesSlide+xml +application/vnd.openxmlformats-officedocument.presentationml.presentation +application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml +application/vnd.openxmlformats-officedocument.presentationml.presProps+xml +application/vnd.openxmlformats-officedocument.presentationml.slide +application/vnd.openxmlformats-officedocument.presentationml.slide+xml +application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml +application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml +application/vnd.openxmlformats-officedocument.presentationml.slideshow +application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml +application/vnd.openxmlformats-officedocument.presentationml.slideUpdateInfo+xml +application/vnd.openxmlformats-officedocument.presentationml.tableStyles+xml +application/vnd.openxmlformats-officedocument.presentationml.tags+xml +application/vnd.openxmlformats-officedocument.presentationml.template +application/vnd.openxmlformats-officedocument.presentationml.template.main+xml +application/vnd.openxmlformats-officedocument.presentationml.viewProps+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.queryTable+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.revisionHeaders+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.revisionLog+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.tableSingleCells+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.template +application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.userNames+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.volatileDependencies+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml +application/vnd.openxmlformats-officedocument.theme+xml +application/vnd.openxmlformats-officedocument.themeOverride+xml +application/vnd.openxmlformats-officedocument.vmlDrawing +application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.document +application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.template +application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml +application/vnd.openxmlformats-package.core-properties+xml +application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml +application/vnd.openxmlformats-package.relationships+xml +application/vnd.oracle.resource+json +application/vnd.orange.indata +application/vnd.osa.netdeploy +application/vnd.osgeo.mapguide.package +application/vnd.osgi.bundle +application/vnd.osgi.dp +application/vnd.osgi.subsystem +application/vnd.otps.ct-kip+xml +application/vnd.oxli.countgraph +application/vnd.pagerduty+json +application/vnd.palm +application/vnd.panoply +application/vnd.paos.xml +application/vnd.patentdive +application/vnd.patientecommsdoc +application/vnd.pawaafile +application/vnd.pcos +application/vnd.pg.format +application/vnd.pg.osasli +application/vnd.piaccess.application-licence +application/vnd.picsel +application/vnd.pmi.widget +application/vnd.poc.group-advertisement+xml +application/vnd.pocketlearn +application/vnd.powerbuilder6 +application/vnd.powerbuilder6-s +application/vnd.powerbuilder7 +application/vnd.powerbuilder75 +application/vnd.powerbuilder75-s +application/vnd.powerbuilder7-s +application/vnd.preminet +application/vnd.previewsystems.box +application/vnd.proteus.magazine +application/vnd.psfs +application/vnd.publishare-delta-tree +application/vnd.pvi.ptid1 +application/vnd.pwg-multiplexed +application/vnd.pwg-xhtml-print+xml +application/vnd.qualcomm.brew-app-res +application/vnd.quarantainenet +application/vnd.Quark.QuarkXPress +application/vnd.quobject-quoxdocument +application/vnd.radisys.moml+xml +application/vnd.radisys.msml-audit-conf+xml +application/vnd.radisys.msml-audit-conn+xml +application/vnd.radisys.msml-audit-dialog+xml +application/vnd.radisys.msml-audit-stream+xml +application/vnd.radisys.msml-audit+xml +application/vnd.radisys.msml-conf+xml +application/vnd.radisys.msml-dialog-base+xml +application/vnd.radisys.msml-dialog-fax-detect+xml +application/vnd.radisys.msml-dialog-fax-sendrecv+xml +application/vnd.radisys.msml-dialog-group+xml +application/vnd.radisys.msml-dialog-speech+xml +application/vnd.radisys.msml-dialog-transform+xml +application/vnd.radisys.msml-dialog+xml +application/vnd.radisys.msml+xml +application/vnd.rainstor.data +application/vnd.rapid +application/vnd.rar +application/vnd.realvnc.bed +application/vnd.recordare.musicxml +application/vnd.recordare.musicxml+xml +application/vnd.RenLearn.rlprint +application/vnd.resilient.logic +application/vnd.restful+json +application/vnd.rig.cryptonote +application/vnd.route66.link66+xml +application/vnd.rs-274x +application/vnd.ruckus.download +application/vnd.s3sms +application/vnd.sailingtracker.track +application/vnd.sar +application/vnd.sbm.cid +application/vnd.sbm.mid2 +application/vnd.scribus +application/vnd.sealed.3df +application/vnd.sealed.csf +application/vnd.sealed.doc +application/vnd.sealed.eml +application/vnd.sealed.mht +application/vnd.sealed.net +application/vnd.sealed.ppt +application/vnd.sealed.tiff +application/vnd.sealed.xls +application/vnd.sealedmedia.softseal.html +application/vnd.sealedmedia.softseal.pdf +application/vnd.seemail +application/vnd.seis+json +application/vnd.sema +application/vnd.semd +application/vnd.semf +application/vnd.shade-save-file +application/vnd.shana.informed.formdata +application/vnd.shana.informed.formtemplate +application/vnd.shana.informed.interchange +application/vnd.shana.informed.package +application/vnd.shootproof+json +application/vnd.shopkick+json +application/vnd.shp +application/vnd.shx +application/vnd.sigrok.session +application/vnd.SimTech-MindMapper +application/vnd.siren+json +application/vnd.smaf +application/vnd.smart.notebook +application/vnd.smart.teacher +application/vnd.snesdev-page-table +application/vnd.software602.filler.form+xml +application/vnd.software602.filler.form-xml-zip +application/vnd.solent.sdkm+xml +application/vnd.spotfire.dxp +application/vnd.spotfire.sfs +application/vnd.sqlite3 +application/vnd.sss-cod +application/vnd.sss-dtf +application/vnd.sss-ntf +application/vnd.stepmania.package +application/vnd.stepmania.stepchart +application/vnd.street-stream +application/vnd.sun.wadl+xml +application/vnd.sus-calendar +application/vnd.svd +application/vnd.swiftview-ics +application/vnd.sycle+xml +application/vnd.syft+json +application/vnd.syncml.dm.notification +application/vnd.syncml.dmddf+xml +application/vnd.syncml.dmtnds+wbxml +application/vnd.syncml.dmtnds+xml +application/vnd.syncml.dmddf+wbxml +application/vnd.syncml.dm+wbxml +application/vnd.syncml.dm+xml +application/vnd.syncml.ds.notification +application/vnd.syncml+xml +application/vnd.tableschema+json +application/vnd.tao.intent-module-archive +application/vnd.tcpdump.pcap +application/vnd.think-cell.ppttc+json +application/vnd.tml +application/vnd.tmd.mediaflex.api+xml +application/vnd.tmobile-livetv +application/vnd.tri.onesource +application/vnd.trid.tpt +application/vnd.triscape.mxs +application/vnd.trueapp +application/vnd.truedoc +application/vnd.ubisoft.webplayer +application/vnd.ufdl +application/vnd.uiq.theme +application/vnd.umajin +application/vnd.unity +application/vnd.uoml+xml +application/vnd.uplanet.alert +application/vnd.uplanet.alert-wbxml +application/vnd.uplanet.bearer-choice +application/vnd.uplanet.bearer-choice-wbxml +application/vnd.uplanet.cacheop +application/vnd.uplanet.cacheop-wbxml +application/vnd.uplanet.channel +application/vnd.uplanet.channel-wbxml +application/vnd.uplanet.list +application/vnd.uplanet.listcmd +application/vnd.uplanet.listcmd-wbxml +application/vnd.uplanet.list-wbxml +application/vnd.uri-map +application/vnd.uplanet.signal +application/vnd.valve.source.material +application/vnd.vcx +application/vnd.vd-study +application/vnd.vectorworks +application/vnd.vel+json +application/vnd.verimatrix.vcas +application/vnd.veritone.aion+json +application/vnd.veryant.thin +application/vnd.ves.encrypted +application/vnd.vidsoft.vidconference +application/vnd.visio +application/vnd.visionary +application/vnd.vividence.scriptfile +application/vnd.vsf +application/vnd.wap.sic +application/vnd.wap.slc +application/vnd.wap.wbxml +application/vnd.wap.wmlc +application/vnd.wap.wmlscriptc +application/vnd.webturbo +application/vnd.wfa.dpp +application/vnd.wfa.p2p +application/vnd.wfa.wsc +application/vnd.windows.devicepairing +application/vnd.wmc +application/vnd.wmf.bootstrap +application/vnd.wolfram.mathematica +application/vnd.wolfram.mathematica.package +application/vnd.wolfram.player +application/vnd.wordperfect +application/vnd.wqd +application/vnd.wrq-hp3000-labelled +application/vnd.wt.stf +application/vnd.wv.csp+xml +application/vnd.wv.csp+wbxml +application/vnd.wv.ssp+xml +application/vnd.xacml+json +application/vnd.xara +application/vnd.xfdl +application/vnd.xfdl.webform +application/vnd.xmi+xml +application/vnd.xmpie.cpkg +application/vnd.xmpie.dpkg +application/vnd.xmpie.plan +application/vnd.xmpie.ppkg +application/vnd.xmpie.xlim +application/vnd.yamaha.hv-dic +application/vnd.yamaha.hv-script +application/vnd.yamaha.hv-voice +application/vnd.yamaha.openscoreformat.osfpvg+xml +application/vnd.yamaha.openscoreformat +application/vnd.yamaha.remote-setup +application/vnd.yamaha.smaf-audio +application/vnd.yamaha.smaf-phrase +application/vnd.yamaha.through-ngn +application/vnd.yamaha.tunnel-udpencap +application/vnd.yaoweme +application/vnd.yellowriver-custom-menu +application/vnd.youtube.yt +application/vnd.zul +application/vnd.zzazz.deck+xml +application/voicexml+xml +application/voucher-cms+json +application/vq-rtcpxr +application/wasm +application/watcherinfo+xml +application/webpush-options+json +application/whoispp-query +application/whoispp-response +application/widget +application/wita +application/wordperfect5.1 +application/wsdl+xml +application/wspolicy+xml +application/x-pki-message +application/x-www-form-urlencoded +application/x-x509-ca-cert +application/x-x509-ca-ra-cert +application/x-x509-next-ca-cert +application/x400-bp +application/xacml+xml +application/xcap-att+xml +application/xcap-caps+xml +application/xcap-diff+xml +application/xcap-el+xml +application/xcap-error+xml +application/xcap-ns+xml +application/xcon-conference-info-diff+xml +application/xcon-conference-info+xml +application/xenc+xml +application/xfdf +application/xhtml+xml +application/xliff+xml +application/xml +application/xml-dtd +application/xml-external-parsed-entity +application/xml-patch+xml +application/xmpp+xml +application/xop+xml +application/xslt+xml +application/xv+xml +application/yang +application/yang-data+cbor +application/yang-data+json +application/yang-data+xml +application/yang-patch+json +application/yang-patch+xml +application/yin+xml +application/zip +application/zlib +application/zstd +audio/1d-interleaved-parityfec +audio/32kadpcm +audio/3gpp +audio/3gpp2 +audio/aac +audio/ac3 +audio/AMR +audio/AMR-WB +audio/amr-wb+ +audio/aptx +audio/asc +audio/ATRAC-ADVANCED-LOSSLESS +audio/ATRAC-X +audio/ATRAC3 +audio/basic +audio/BV16 +audio/BV32 +audio/clearmode +audio/CN +audio/DAT12 +audio/dls +audio/dsr-es201108 +audio/dsr-es202050 +audio/dsr-es202211 +audio/dsr-es202212 +audio/DV +audio/DVI4 +audio/eac3 +audio/encaprtp +audio/EVRC +audio/EVRC-QCP +audio/EVRC0 +audio/EVRC1 +audio/EVRCB +audio/EVRCB0 +audio/EVRCB1 +audio/EVRCNW +audio/EVRCNW0 +audio/EVRCNW1 +audio/EVRCWB +audio/EVRCWB0 +audio/EVRCWB1 +audio/EVS +audio/example +audio/flexfec +audio/fwdred +audio/G711-0 +audio/G719 +audio/G7221 +audio/G722 +audio/G723 +audio/G726-16 +audio/G726-24 +audio/G726-32 +audio/G726-40 +audio/G728 +audio/G729 +audio/G7291 +audio/G729D +audio/G729E +audio/GSM +audio/GSM-EFR +audio/GSM-HR-08 +audio/iLBC +audio/ip-mr_v2.5 +audio/L8 +audio/L16 +audio/L20 +audio/L24 +audio/LPC +audio/MELP +audio/MELP600 +audio/MELP1200 +audio/MELP2400 +audio/mhas +audio/mobile-xmf +audio/MPA +audio/mp4 +audio/MP4A-LATM +audio/mpa-robust +audio/mpeg +audio/mpeg4-generic +audio/ogg +audio/opus +audio/parityfec +audio/PCMA +audio/PCMA-WB +audio/PCMU +audio/PCMU-WB +audio/prs.sid +audio/QCELP +audio/raptorfec +audio/RED +audio/rtp-enc-aescm128 +audio/rtploopback +audio/rtp-midi +audio/rtx +audio/scip +audio/SMV +audio/SMV0 +audio/SMV-QCP +audio/sofa +audio/sp-midi +audio/speex +audio/t140c +audio/t38 +audio/telephone-event +audio/TETRA_ACELP +audio/TETRA_ACELP_BB +audio/tone +audio/TSVCIS +audio/UEMCLIP +audio/ulpfec +audio/usac +audio/VDVI +audio/VMR-WB +audio/vnd.3gpp.iufp +audio/vnd.4SB +audio/vnd.audiokoz +audio/vnd.CELP +audio/vnd.cisco.nse +audio/vnd.cmles.radio-events +audio/vnd.cns.anp1 +audio/vnd.cns.inf1 +audio/vnd.dece.audio +audio/vnd.digital-winds +audio/vnd.dlna.adts +audio/vnd.dolby.heaac.1 +audio/vnd.dolby.heaac.2 +audio/vnd.dolby.mlp +audio/vnd.dolby.mps +audio/vnd.dolby.pl2 +audio/vnd.dolby.pl2x +audio/vnd.dolby.pl2z +audio/vnd.dolby.pulse.1 +audio/vnd.dra +audio/vnd.dts +audio/vnd.dts.hd +audio/vnd.dts.uhd +audio/vnd.dvb.file +audio/vnd.everad.plj +audio/vnd.hns.audio +audio/vnd.lucent.voice +audio/vnd.ms-playready.media.pya +audio/vnd.nokia.mobile-xmf +audio/vnd.nortel.vbk +audio/vnd.nuera.ecelp4800 +audio/vnd.nuera.ecelp7470 +audio/vnd.nuera.ecelp9600 +audio/vnd.octel.sbc +audio/vnd.presonus.multitrack +audio/vnd.qcelp +audio/vnd.rhetorex.32kadpcm +audio/vnd.rip +audio/vnd.sealedmedia.softseal.mpeg +audio/vnd.vmx.cvsd +audio/vorbis +audio/vorbis-config +example/example +font/collection +font/otf +font/sfnt +font/ttf +font/woff +font/woff2 +image/aces +image/avci +image/avcs +image/avif +image/bmp +image/cgm +image/dicom-rle +image/dpx +image/emf +image/example +image/fits +image/g3fax +image/gif +image/heic +image/heic-sequence +image/heif +image/heif-sequence +image/hej2k +image/hsj2 +image/ief +image/jls +image/jp2 +image/jpeg +image/jph +image/jphc +image/jpm +image/jpx +image/jxr +image/jxrA +image/jxrS +image/jxs +image/jxsc +image/jxsi +image/jxss +image/ktx +image/ktx2 +image/naplps +image/png +image/prs.btif +image/prs.pti +image/pwg-raster +image/svg+xml +image/t38 +image/tiff +image/tiff-fx +image/vnd.adobe.photoshop +image/vnd.airzip.accelerator.azv +image/vnd.cns.inf2 +image/vnd.dece.graphic +image/vnd.djvu +image/vnd.dwg +image/vnd.dxf +image/vnd.dvb.subtitle +image/vnd.fastbidsheet +image/vnd.fpx +image/vnd.fst +image/vnd.fujixerox.edmics-mmr +image/vnd.fujixerox.edmics-rlc +image/vnd.globalgraphics.pgb +image/vnd.microsoft.icon +image/vnd.mix +image/vnd.ms-modi +image/vnd.mozilla.apng +image/vnd.net-fpx +image/vnd.pco.b16 +image/vnd.radiance +image/vnd.sealed.png +image/vnd.sealedmedia.softseal.gif +image/vnd.sealedmedia.softseal.jpg +image/vnd.svf +image/vnd.tencent.tap +image/vnd.valve.source.texture +image/vnd.wap.wbmp +image/vnd.xiff +image/vnd.zbrush.pcx +image/wmf +image/emf +image/wmf +message/bhttp +message/CPIM +message/delivery-status +message/disposition-notification +message/example +message/external-body +message/feedback-report +message/global +message/global-delivery-status +message/global-disposition-notification +message/global-headers +message/http +message/imdn+xml +message/news +message/partial +message/rfc822 +message/s-http +message/sip +message/sipfrag +message/tracking-status +message/vnd.si.simp +message/vnd.wfa.wsc +model/3mf +model/e57 +model/example +model/gltf-binary +model/gltf+json +model/iges +model/mesh +model/mtl +model/obj +model/prc +model/step +model/step+xml +model/step+zip +model/step-xml+zip +model/stl +model/u3d +model/vnd.collada+xml +model/vnd.dwf +model/vnd.flatland.3dml +model/vnd.gdl +model/vnd.gs-gdl +model/vnd.gtw +model/vnd.moml+xml +model/vnd.mts +model/vnd.opengex +model/vnd.parasolid.transmit.binary +model/vnd.parasolid.transmit.text +model/vnd.pytha.pyox +model/vnd.rosette.annotated-data-model +model/vnd.sap.vds +model/vnd.usdz+zip +model/vnd.valve.source.compiled-map +model/vnd.vtu +model/vrml +model/x3d-vrml +model/x3d+fastinfoset +model/x3d+xml +multipart/alternative +multipart/appledouble +multipart/byteranges +multipart/digest +multipart/encrypted +multipart/example +multipart/form-data +multipart/header-set +multipart/mixed +multipart/multilingual +multipart/parallel +multipart/related +multipart/report +multipart/signed +multipart/vnd.bint.med-plus +multipart/voice-message +multipart/x-mixed-replace +text/csv-schema +text/directory +text/dns +text/ecmascript +text/encaprtp +text/enriched +text/example +text/fhirpath +text/flexfec +text/fwdred +text/gff3 +text/grammar-ref-list +text/hl7v2 +text/html +text/javascript +text/jcr-cnd +text/markdown +text/mizar +text/n3 +text/parameters +text/parityfec +text/plain +text/provenance-notation +text/prs.fallenstein.rst +text/prs.lines.tag +text/prs.prop.logic +text/raptorfec +text/RED +text/rfc822-headers +text/richtext +text/rtf +text/rtp-enc-aescm128 +text/rtploopback +text/rtx +text/SGML +text/shaclc +text/shex +text/spdx +text/strings +text/t140 +text/tab-separated-values +text/troff +text/turtle +text/ulpfec +text/uri-list +text/vcard +text/vnd.a +text/vnd.abc +text/vnd.ascii-art +text/vnd.curl +text/vnd.debian.copyright +text/vnd.DMClientScript +text/vnd.dvb.subtitle +text/vnd.esmertec.theme-descriptor +text/vnd.familysearch.gedcom +text/vnd.ficlab.flt +text/vnd.fly +text/vnd.fmi.flexstor +text/vnd.gml +text/vnd.graphviz +text/vnd.hans +text/vnd.hgl +text/vnd.in3d.3dml +text/vnd.in3d.spot +text/vnd.IPTC.NewsML +text/vnd.IPTC.NITF +text/vnd.latex-z +text/vnd.motorola.reflex +text/vnd.ms-mediapackage +text/vnd.net2phone.commcenter.command +text/vnd.radisys.msml-basic-layout +text/vnd.senx.warpscript +text/vnd.si.uricatalogue +text/vnd.sun.j2me.app-descriptor +text/vnd.sosi +text/vnd.trolltech.linguist +text/vnd.wap.si +text/vnd.wap.sl +text/vnd.wap.wml +text/vnd.wap.wmlscript +text/vtt +text/xml +text/xml-external-parsed-entity +video/1d-interleaved-parityfec +video/3gpp +video/3gpp2 +video/3gpp-tt +video/AV1 +video/BMPEG +video/BT656 +video/CelB +video/DV +video/encaprtp +video/example +video/FFV1 +video/flexfec +video/H261 +video/H263 +video/H263-1998 +video/H263-2000 +video/H264 +video/H264-RCDO +video/H264-SVC +video/H265 +video/iso.segment +video/JPEG +video/jpeg2000 +video/jxsv +video/mj2 +video/MP1S +video/MP2P +video/MP2T +video/mp4 +video/MP4V-ES +video/MPV +video/mpeg +video/mpeg4-generic +video/nv +video/ogg +video/parityfec +video/pointer +video/quicktime +video/raptorfec +video/raw +video/rtp-enc-aescm128 +video/rtploopback +video/rtx +video/scip +video/smpte291 +video/SMPTE292M +video/ulpfec +video/vc1 +video/vc2 +video/vnd.CCTV +video/vnd.dece.hd +video/vnd.dece.mobile +video/vnd.dece.mp4 +video/vnd.dece.pd +video/vnd.dece.sd +video/vnd.dece.video +video/vnd.directv.mpeg +video/vnd.directv.mpeg-tts +video/vnd.dlna.mpeg-tts +video/vnd.dvb.file +video/vnd.fvt +video/vnd.hns.video +video/vnd.iptvforum.1dparityfec-1010 +video/vnd.iptvforum.1dparityfec-2005 +video/vnd.iptvforum.2dparityfec-1010 +video/vnd.iptvforum.2dparityfec-2005 +video/vnd.iptvforum.ttsavc +video/vnd.iptvforum.ttsmpeg2 +video/vnd.motorola.video +video/vnd.motorola.videop +video/vnd.mpegurl +video/vnd.ms-playready.media.pyv +video/vnd.nokia.interleaved-multimedia +video/vnd.nokia.mp4vr +video/vnd.nokia.videovoip +video/vnd.objectvideo +video/vnd.radgamettools.bink +video/vnd.radgamettools.smacker +video/vnd.sealed.mpeg1 +video/vnd.sealed.mpeg4 +video/vnd.sealed.swf +video/vnd.sealedmedia.softseal.mov +video/vnd.uvvu.mp4 +video/vnd.youtube.yt +video/vnd.vivo +video/VP8 +video/VP9 diff --git a/vendor/nim-http-utils/tests/tvectors.nim b/vendor/nim-http-utils/tests/tvectors.nim index 702091699..e932c377d 100644 --- a/vendor/nim-http-utils/tests/tvectors.nim +++ b/vendor/nim-http-utils/tests/tvectors.nim @@ -983,3 +983,237 @@ suite "HTTP Procedures test suite": res3.get() == MediaType.init(vector[1][3]) res4.get() == MediaType.init(vector[1][4]) res5.get() == MediaType.init(vector[1][5]) + + test "Content-Type header parser mime-types vectors test": + let filename = "tests/mimetypes.txt" + for line in filename.lines(): + if len(line) != 0: + check: + getContentType(line).isOk() + getContentType(line & "; charset=utf-8").isOk() + getContentType(line & "; charset=\"utf-8\"").isOk() + + test "Content-Type header parser test vectors": + + const + Token = "!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyz" & + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + QdText = + "\t !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ" & + "[]^_`abcdefghijklmnopqrstuvwxyz{|}~" & + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F" & + "\x90\x91\x92\x93\x94\x95\x96\x97\x99\x99\x9A\x9B\x9C\x9D\x9E\x9F" & + "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xAA\xA9\xAA\xAB\xAC\xAD\xAE\xAF" & + "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xBB\xB9\xBA\xBB\xBC\xBD\xBE\xBF" & + "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xCC\xC9\xCA\xCB\xCC\xCD\xCE\xCF" & + "\xD0\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xDD\xD9\xDA\xDB\xDC\xDD\xDE\xDF" & + "\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xEE\xE9\xEA\xEB\xEC\xEE\xEE\xEF" & + "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xFF\xF9\xFA\xFB\xFC\xFF\xFE\xFF" + + FailureVectors = [ + "", + "\x7F", + "\x80", + "\xFF", + " ", + "\t", + "text", + "html", + "text/", + "text\\", + " text/html", + "\xFFtext/html", + "\x80text/html", + "\x7Ftext/html", + "tex\x7Ft/html", + "text/\xFFhtml", + "text/\x80html", + "text/\x7Fhtml", + "text/html;", + "text/html; ", + "text/html;a", + "text/html;\xFF", + "text/html;\x80", + "text/html;\x7F", + "text/html;a=;", + "text/html;a=b;b=c;c=d;", + "text/html;a=b;b=c;c=d; ", + "text/html;a=\"", + "text/html;a=\"\"\"", + "text/html;a=\x7F", + "text/html;a=\x80", + "text/html;a=\xFF", + "text/html;a=\x00", + "text/html;a=\x1F", + "text/html;a=\"\x00\"", + "text/html;a=\"\x1F\"", + "text/html;a= " + ] + + SuccessVectors = [ + ("text/html;a=", ("text/html", + @[("a", "")])), + ("text/html", ("text/html", + @[])), + ("text/html;a=\"\"", ("text/html", + @[("a", "")])), + ("text/html;a=\"\\\\\"", ("text/html", + @[("a", "\\")])), + ("text/html;a=\"\\\"\"", ("text/html", + @[("a", "\"")])), + ("text/html;a=\"\\aa\"", ("text/html", + @[("a", "aa")])), + ("text/html;a=\"\x80\xFF\"", ("text/html", + @[("a", "\x80\xFF")])), + ("text/html;a=\"\t\"", ("text/html", + @[("a", "\t")])), + ("text/html;a=\" \"", ("text/html", + @[("a", " ")])), + ("text/html;a=b", ("text/html", + @[("a", "b")])), + ("text/html;a=\"b\"", ("text/html", + @[("a", "b")])), + ("text/html;a=b;b=c", ("text/html", + @[("a", "b"), ("b", "c")])), + ("text/html;a=b;b=c;c=d", ("text/html", + @[("a", "b"), ("b", "c"), ("c", "d")])), + ("text/html;a=;b=;c=", ("text/html", + @[("a", ""), ("b", ""), ("c", "")])), + ("text/html;a=;b=c;c=d", ("text/html", + @[("a", ""), ("b", "c"), ("c", "d")])), + ("text/html;a=b;b=;c=d", ("text/html", + @[("a", "b"), ("b", ""), ("c", "d")])), + ("text/html;a=b;b=c;c=", ("text/html", + @[("a", "b"), ("b", "c"), ("c", "")])), + ("text/html;a=;b=\"\";c=", ("text/html", + @[("a", ""), ("b", ""), ("c", "")])), + ("text/html;a=;b=\"\";c=\"\"", ("text/html", + @[("a", ""), ("b", ""), ("c", "")])) + ] + for item in FailureVectors: + check getContentType(item).isErr() + + for item in SuccessVectors: + let res = getContentType(item[0]) + check res.isOk() + let content = res.get() + check: + content.mediaType.media & "/" & content.mediaType.subtype == item[1][0] + let params = content.params + check: + len(params) == len(item[1][1]) + for index, param in params.pairs(): + check: + param[0] == item[1][1][index][0] + param[1] == item[1][1][index][1] + + block: + # Token/Token; Token=Token; Token="QdText" + let contentType = Token & "/" & Token & "; " & + Token & "=" & Token & "; " & + Token & "=\"" & QdText & "\"" + let res = getContentType(contentType) + check res.isOk() + let data = res.get() + check: + data.mediaType.media == Token + data.mediaType.subtype == Token + data.params[0] == (name: Token, value: Token) + data.params[1] == (name: Token, value: QdText) + + test "isValid(MediaType) test": + let filename = "tests/mimetypes.txt" + for line in filename.lines(): + if len(line) != 0: + check isValid(MediaType.init(line)) == true + check: + isValid(MediaType.init("*/*")) == true + isValid(MediaType.init("application/*")) == true + + test "isWildCard(MediaType) test": + let filename = "tests/mimetypes.txt" + for line in filename.lines(): + if len(line) != 0: + check isWildCard(MediaType.init(line)) == false + check: + isWildCard(MediaType.init("*/*")) == true + isWildCard(MediaType.init("text/*")) == true + isWildCard(MediaType.init("image/*")) == true + + test "(ContentTypeData, MediaType) comparison": + let filename = "tests/mimetypes.txt" + for line in filename.lines(): + if len(line) != 0: + let + contentType1 = getContentType(line & "; charset=utf-8").tryGet() + contentType2 = getContentType(line & "; charset=ISO-8859-1").tryGet() + mediaType = MediaType.init(line) + + check: + contentType1 == mediaType + contentType2 == mediaType + contentType1 == MediaType.init("*/*") + + test "(ContentTypeData, ContentTypeData) comparison": + let filename = "tests/mimetypes.txt" + for line in filename.lines(): + if len(line) != 0: + let + contentType1 = getContentType(line).tryGet() + contentType2 = getContentType(line & "; charset=\"utf-8\"").tryGet() + contentType3 = getContentType(line & "; charset=utf-8").tryGet() + contentType4 = getContentType(line & "; ChArSeT=utf-8").tryGet() + contentType5 = getContentType(line & "; ChArSeT=UTF-8").tryGet() + contentType6 = getContentType(line & "; ChArSeT=ISO-8859-1").tryGet() + contentType7 = getContentType(line & "; ChArSeT=iso-8859-1").tryGet() + + check: + contentType1 == contentType1 + contentType1 != contentType2 + contentType1 != contentType3 + contentType1 != contentType4 + contentType1 != contentType5 + contentType1 != contentType6 + contentType1 != contentType7 + + contentType2 == contentType2 + contentType2 == contentType3 + contentType2 == contentType4 + contentType2 == contentType5 + contentType2 != contentType6 + contentType2 != contentType7 + + contentType3 == contentType3 + contentType3 == contentType4 + contentType3 == contentType5 + contentType3 != contentType6 + contentType3 != contentType7 + + contentType4 == contentType4 + contentType4 == contentType5 + contentType4 != contentType6 + contentType4 != contentType7 + + contentType5 == contentType5 + contentType5 != contentType6 + contentType5 != contentType7 + + contentType6 == contentType6 + contentType6 == contentType7 + + contentType7 == contentType7 + + test "ContenTypeData to string test": + let filename = "tests/mimetypes.txt" + for line in filename.lines(): + if len(line) != 0: + let header = line & "; charset=\"utf-8\"; boundary=\"boundary\"" + let + contentType1 = getContentType( + line & "; charset=utf-8; boundary=boundary").tryGet() + contentType2 = getContentType(line).tryGet() + check: + $contentType1 == header + $contentType2 == line + check: + $ContentTypeData(status: HttpStatus.Failure) == "" diff --git a/vendor/nim-json-rpc/.github/workflows/ci.yml b/vendor/nim-json-rpc/.github/workflows/ci.yml index 1e0bec5fe..24e957d13 100644 --- a/vendor/nim-json-rpc/.github/workflows/ci.yml +++ b/vendor/nim-json-rpc/.github/workflows/ci.yml @@ -26,11 +26,11 @@ jobs: include: - target: os: linux - builder: ubuntu-18.04 + builder: ubuntu-20.04 shell: bash - target: os: macos - builder: macos-10.15 + builder: macos-11 shell: bash - target: os: windows @@ -153,10 +153,6 @@ jobs: - name: Run tests shell: bash run: | - if [[ "${{ matrix.target.os }}" == "windows" ]]; then - # https://github.com/status-im/nimbus-eth2/issues/3121 - export NIMFLAGS="-d:nimRawSetjmp" - fi nim --version nimble --version nimble install -y --depsOnly diff --git a/vendor/nim-json-rpc/.gitignore b/vendor/nim-json-rpc/.gitignore index 47d6cfaaa..45ad3b967 100644 --- a/vendor/nim-json-rpc/.gitignore +++ b/vendor/nim-json-rpc/.gitignore @@ -18,3 +18,5 @@ nimcache/ .vscode +nimble.develop +nimble.paths diff --git a/vendor/nim-json-rpc/README.md b/vendor/nim-json-rpc/README.md index 9089eb19d..2ed2e3eef 100644 --- a/vendor/nim-json-rpc/README.md +++ b/vendor/nim-json-rpc/README.md @@ -293,9 +293,9 @@ The `RpcServer` type is given as a simple inheritable wrapper/container that sim Currently there are plans for the following transports to be implemented: * [x] Sockets -* [ ] HTTP +* [x] HTTP * [ ] IPC -* [ ] Websockets +* [x] Websockets Transport specific server need only call the `route` procedure using a string fetched from the transport in order to invoke the requested RPC. diff --git a/vendor/nim-json-rpc/config.nims b/vendor/nim-json-rpc/config.nims new file mode 100644 index 000000000..7c9db3205 --- /dev/null +++ b/vendor/nim-json-rpc/config.nims @@ -0,0 +1,4 @@ +# begin Nimble config (version 1) +when fileExists("nimble.paths"): + include "nimble.paths" +# end Nimble config diff --git a/vendor/nim-json-rpc/json_rpc/clients/config.nim b/vendor/nim-json-rpc/json_rpc/clients/config.nim index 1f6cb378e..6a51a4acf 100644 --- a/vendor/nim-json-rpc/json_rpc/clients/config.nim +++ b/vendor/nim-json-rpc/json_rpc/clients/config.nim @@ -1,5 +1,5 @@ const - json_rpc_websocket_package {.strdefine.} = "websock" + json_rpc_websocket_package {.strdefine.} = "news" useNews* = json_rpc_websocket_package == "news" when json_rpc_websocket_package notin ["websock", "news"]: diff --git a/vendor/nim-json-rpc/json_rpc/clients/websocketclient.nim b/vendor/nim-json-rpc/json_rpc/clients/websocketclient.nim index 9cbecc053..0609a7978 100644 --- a/vendor/nim-json-rpc/json_rpc/clients/websocketclient.nim +++ b/vendor/nim-json-rpc/json_rpc/clients/websocketclient.nim @@ -128,6 +128,7 @@ else: proc connect*( client: RpcWebSocketClient, uri: string, compression = false, + hooks: seq[Hook] = @[], flags: set[TLSFlags] = {NoVerifyHost, NoVerifyServerName}) {.async.} = var ext: seq[ExtFactory] = if compression: @[deflateFactory()] else: @[] @@ -135,6 +136,7 @@ else: let ws = await WebSocket.connect( uri=uri, factories=ext, + hooks=hooks, flags=flags ) client.transport = ws diff --git a/vendor/nim-json-rpc/json_rpc/rpcproxy.nim b/vendor/nim-json-rpc/json_rpc/rpcproxy.nim index f22b68e7f..f4a03bd2d 100644 --- a/vendor/nim-json-rpc/json_rpc/rpcproxy.nim +++ b/vendor/nim-json-rpc/json_rpc/rpcproxy.nim @@ -40,7 +40,7 @@ proc getWebSocketClientConfig*( uri: string, compression: bool = false, flags: set[TLSFlags] = { - NoVerifyHost, NoVerifyServerName}): ClientConfig = + TLSFlags.NoVerifyHost, TLSFlags.NoVerifyServerName}): ClientConfig = ClientConfig(kind: WebSocket, wsUri: uri, compression: compression, flags: flags) proc proxyCall(client: RpcClient, name: string): RpcProc = @@ -82,7 +82,10 @@ proc connectToProxy(proxy: RpcProxy): Future[void] = of Http: return proxy.httpClient.connect(proxy.httpUri) of WebSocket: - return proxy.webSocketClient.connect(proxy.wsUri, proxy.compression, proxy.flags) + return proxy.webSocketClient.connect( + uri = proxy.wsUri, + compression = proxy.compression, + flags = proxy.flags) proc start*(proxy: RpcProxy) {.async.} = proxy.rpcHttpServer.start() diff --git a/vendor/nim-json-rpc/json_rpc/servers/httpserver.nim b/vendor/nim-json-rpc/json_rpc/servers/httpserver.nim index 8cbf29512..1e7b2dc5d 100644 --- a/vendor/nim-json-rpc/json_rpc/servers/httpserver.nim +++ b/vendor/nim-json-rpc/json_rpc/servers/httpserver.nim @@ -5,7 +5,7 @@ import chronos/apps/http/[httpserver, shttpserver], ".."/[errors, server] -export server +export server, shttpserver logScope: topics = "JSONRPC-HTTP-SERVER" @@ -14,13 +14,31 @@ type ReqStatus = enum Success, Error, ErrorFailure + # HttpAuthHook: handle CORS, JWT auth, etc. in HTTP header + # before actual request processed + # return value: + # - nil: auth success, continue execution + # - HttpResponse: could not authenticate, stop execution + # and return the response + HttpAuthHook* = proc(request: HttpRequestRef): Future[HttpResponseRef] + {.gcsafe, raises: [Defect, CatchableError].} + RpcHttpServer* = ref object of RpcServer httpServers: seq[HttpServerRef] + authHooks: seq[HttpAuthHook] -proc processClientRpc(rpcServer: RpcServer): HttpProcessCallback = +proc processClientRpc(rpcServer: RpcHttpServer): HttpProcessCallback = return proc (req: RequestFence): Future[HttpResponseRef] {.async.} = if req.isOk(): let request = req.get() + + # if hook result is not nil, + # it means we should return immediately + for hook in rpcServer.authHooks: + let res = await hook(request) + if not res.isNil: + return res + let body = await request.getBody() let future = rpcServer.route(string.fromBytes(body)) @@ -177,36 +195,36 @@ proc addSecureHttpServer*(server: RpcHttpServer, for a in resolvedAddresses(address, port): server.addSecureHttpServer(a, tlsPrivateKey, tlsCertificate) -proc new*(T: type RpcHttpServer): T = - T(router: RpcRouter.init(), httpServers: @[]) +proc new*(T: type RpcHttpServer, authHooks: seq[HttpAuthHook] = @[]): T = + T(router: RpcRouter.init(), httpServers: @[], authHooks: authHooks) -proc new*(T: type RpcHttpServer, router: RpcRouter): T = - T(router: router, httpServers: @[]) +proc new*(T: type RpcHttpServer, router: RpcRouter, authHooks: seq[HttpAuthHook] = @[]): T = + T(router: router, httpServers: @[], authHooks: authHooks) -proc newRpcHttpServer*(): RpcHttpServer = - RpcHttpServer.new() +proc newRpcHttpServer*(authHooks: seq[HttpAuthHook] = @[]): RpcHttpServer = + RpcHttpServer.new(authHooks) -proc newRpcHttpServer*(router: RpcRouter): RpcHttpServer = - RpcHttpServer.new(router) +proc newRpcHttpServer*(router: RpcRouter, authHooks: seq[HttpAuthHook] = @[]): RpcHttpServer = + RpcHttpServer.new(router, authHooks) -proc newRpcHttpServer*(addresses: openArray[TransportAddress]): RpcHttpServer = +proc newRpcHttpServer*(addresses: openArray[TransportAddress], authHooks: seq[HttpAuthHook] = @[]): RpcHttpServer = ## Create new server and assign it to addresses ``addresses``. - result = newRpcHttpServer() + result = newRpcHttpServer(authHooks) result.addHttpServers(addresses) -proc newRpcHttpServer*(addresses: openArray[string]): RpcHttpServer = +proc newRpcHttpServer*(addresses: openArray[string], authHooks: seq[HttpAuthHook] = @[]): RpcHttpServer = ## Create new server and assign it to addresses ``addresses``. - result = newRpcHttpServer() + result = newRpcHttpServer(authHooks) result.addHttpServers(addresses) -proc newRpcHttpServer*(addresses: openArray[string], router: RpcRouter): RpcHttpServer = +proc newRpcHttpServer*(addresses: openArray[string], router: RpcRouter, authHooks: seq[HttpAuthHook] = @[]): RpcHttpServer = ## Create new server and assign it to addresses ``addresses``. - result = newRpcHttpServer(router) + result = newRpcHttpServer(router, authHooks) result.addHttpServers(addresses) -proc newRpcHttpServer*(addresses: openArray[TransportAddress], router: RpcRouter): RpcHttpServer = +proc newRpcHttpServer*(addresses: openArray[TransportAddress], router: RpcRouter, authHooks: seq[HttpAuthHook] = @[]): RpcHttpServer = ## Create new server and assign it to addresses ``addresses``. - result = newRpcHttpServer(router) + result = newRpcHttpServer(router, authHooks) result.addHttpServers(addresses) proc start*(server: RpcHttpServer) = diff --git a/vendor/nim-json-rpc/json_rpc/servers/websocketserver.nim b/vendor/nim-json-rpc/json_rpc/servers/websocketserver.nim index eb53c0b7b..15c4aa7d1 100644 --- a/vendor/nim-json-rpc/json_rpc/servers/websocketserver.nim +++ b/vendor/nim-json-rpc/json_rpc/servers/websocketserver.nim @@ -10,51 +10,34 @@ logScope: topics = "JSONRPC-WS-SERVER" type - RpcWebSocketServerAuth* = ##\ - ## Authenticator function. On error, the resulting `HttpCode` is sent back\ - ## to the client and the `string` argument will be used in an exception,\ - ## following. - proc(req: HttpTable): Result[void,(HttpCode,string)] - {.gcsafe, raises: [Defect].} + # WsAuthHook: handle CORS, JWT auth, etc. in HTTP header + # before actual request processed + # return value: + # - true: auth success, continue execution + # - false: could not authenticate, stop execution + # and return the response + WsAuthHook* = proc(request: HttpRequest): Future[bool] + {.gcsafe, raises: [Defect, CatchableError].} RpcWebSocketServer* = ref object of RpcServer - authHook: Option[RpcWebSocketServerAuth] ## Authorization call back handler server: StreamServer wsserver: WSServer - - HookEx = ref object of Hook - handler: RpcWebSocketServerAuth ## from `RpcWebSocketServer` - request: HttpRequest ## current request needed for error response - -proc authWithHtCodeResponse(ctx: Hook, headers: HttpTable): - Future[Result[void, string]] {.async, gcsafe, raises: [Defect].} = - ## Wrapper around authorization handler which is stored in the - ## extended `Hook` object. - let - cty = ctx.HookEx - rc = cty.handler(headers) - if rc.isErr: - await cty.request.stream.writer.sendError(rc.error[0]) - return err(rc.error[1]) - return ok() + authHooks: seq[WsAuthHook] proc handleRequest(rpc: RpcWebSocketServer, request: HttpRequest) {.async.} = trace "Handling request:", uri = request.uri.path trace "Initiating web socket connection." - # Authorization handler constructor (if enabled) - var hooks: seq[Hook] - if rpc.authHook.isSome: - let hookEx = HookEx( - append: nil, - request: request, - handler: rpc.authHook.get, - verify: authWithHtCodeResponse) - hooks = @[hookEx.Hook] + # if hook result is false, + # it means we should return immediately + for hook in rpc.authHooks: + let res = await hook(request) + if not res: + return try: let server = rpc.wsserver - let ws = await server.handleRequest(request, hooks = hooks) + let ws = await server.handleRequest(request) if ws.readyState != ReadyState.Open: error "Failed to open websocket connection" return @@ -94,25 +77,27 @@ proc handleRequest(rpc: RpcWebSocketServer, request: HttpRequest) {.async.} = error "WebSocket error:", exception = exc.msg proc initWebsocket(rpc: RpcWebSocketServer, compression: bool, - authHandler: Option[RpcWebSocketServerAuth]) = + authHooks: seq[WsAuthHook], + rng: Rng) = if compression: let deflateFactory = deflateFactory() - rpc.wsserver = WSServer.new(factories = [deflateFactory]) + rpc.wsserver = WSServer.new(factories = [deflateFactory], rng = rng) else: - rpc.wsserver = WSServer.new() - rpc.authHook = authHandler + rpc.wsserver = WSServer.new(rng = rng) + rpc.authHooks = authHooks proc newRpcWebSocketServer*( address: TransportAddress, compression: bool = false, flags: set[ServerFlags] = {ServerFlags.TcpNoDelay,ServerFlags.ReuseAddr}, - authHandler = none(RpcWebSocketServerAuth)): RpcWebSocketServer = + authHooks: seq[WsAuthHook] = @[], + rng = newRng()): RpcWebSocketServer = var server = new(RpcWebSocketServer) proc processCallback(request: HttpRequest): Future[void] = handleRequest(server, request) - server.initWebsocket(compression, authHandler) + server.initWebsocket(compression, authHooks, rng) server.server = HttpServer.create( address, processCallback, @@ -126,13 +111,15 @@ proc newRpcWebSocketServer*( port: Port, compression: bool = false, flags: set[ServerFlags] = {ServerFlags.TcpNoDelay, ServerFlags.ReuseAddr}, - authHandler = none(RpcWebSocketServerAuth)): RpcWebSocketServer = + authHooks: seq[WsAuthHook] = @[], + rng = newRng()): RpcWebSocketServer = newRpcWebSocketServer( initTAddress(host, port), compression, flags, - authHandler + authHooks, + rng ) proc newRpcWebSocketServer*( @@ -145,13 +132,14 @@ proc newRpcWebSocketServer*( tlsFlags: set[TLSFlags] = {}, tlsMinVersion = TLSVersion.TLS12, tlsMaxVersion = TLSVersion.TLS12, - authHandler = none(RpcWebSocketServerAuth)): RpcWebSocketServer = + authHooks: seq[WsAuthHook] = @[], + rng = newRng()): RpcWebSocketServer = var server = new(RpcWebSocketServer) proc processCallback(request: HttpRequest): Future[void] = handleRequest(server, request) - server.initWebsocket(compression, authHandler) + server.initWebsocket(compression, authHooks, rng) server.server = TlsHttpServer.create( address, tlsPrivateKey, @@ -176,7 +164,8 @@ proc newRpcWebSocketServer*( tlsFlags: set[TLSFlags] = {}, tlsMinVersion = TLSVersion.TLS12, tlsMaxVersion = TLSVersion.TLS12, - authHandler = none(RpcWebSocketServerAuth)): RpcWebSocketServer = + authHooks: seq[WsAuthHook] = @[], + rng = newRng()): RpcWebSocketServer = newRpcWebSocketServer( initTAddress(host, port), @@ -187,7 +176,8 @@ proc newRpcWebSocketServer*( tlsFlags, tlsMinVersion, tlsMaxVersion, - authHandler + authHooks, + rng ) proc start*(server: RpcWebSocketServer) = diff --git a/vendor/nim-json-rpc/nim.cfg b/vendor/nim-json-rpc/nim.cfg new file mode 100644 index 000000000..371f6d79d --- /dev/null +++ b/vendor/nim-json-rpc/nim.cfg @@ -0,0 +1,5 @@ +# Avoid some rare stack corruption while using exceptions with a SEH-enabled +# toolchain: https://github.com/status-im/nimbus-eth2/issues/3121 +@if windows and not vcc: + --define:nimRawSetjmp +@end diff --git a/vendor/nim-json-rpc/nimble.lock b/vendor/nim-json-rpc/nimble.lock new file mode 100644 index 000000000..aa50f983c --- /dev/null +++ b/vendor/nim-json-rpc/nimble.lock @@ -0,0 +1,204 @@ +{ + "version": 1, + "packages": { + "unittest2": { + "version": "0.0.4", + "vcsRevision": "f180f596c88dfd266f746ed6f8dbebce39c824db", + "url": "https://github.com/status-im/nim-unittest2.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "fa309c41eaf6ef57895b9e603f2620a2f6e11780" + } + }, + "stew": { + "version": "0.1.0", + "vcsRevision": "6ad35b876fb6ebe0dfee0f697af173acc47906ee", + "url": "https://github.com/status-im/nim-stew.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "46d58c4feb457f3241e3347778334e325dce5268" + } + }, + "bearssl": { + "version": "0.1.5", + "vcsRevision": "ba80e2a0d7ae8aab666cee013e38ff8d33a3e5e7", + "url": "https://github.com/status-im/nim-bearssl", + "downloadMethod": "git", + "dependencies": [ + "unittest2" + ], + "checksums": { + "sha1": "383abd5becc77bf8e365b780a29d20529e1d9c4c" + } + }, + "httputils": { + "version": "0.3.0", + "vcsRevision": "689da19e9e9cfff4ced85e2b25c6b2b5598ed079", + "url": "https://github.com/status-im/nim-http-utils.git", + "downloadMethod": "git", + "dependencies": [ + "stew" + ], + "checksums": { + "sha1": "4ad3ad68d13c50184180ab4b2eacc0bd7ed2ed44" + } + }, + "chronos": { + "version": "3.0.11", + "vcsRevision": "17fed89c99beac5a92d3668d0d3e9b0e4ac13936", + "url": "https://github.com/status-im/nim-chronos.git", + "downloadMethod": "git", + "dependencies": [ + "stew", + "bearssl", + "httputils", + "unittest2" + ], + "checksums": { + "sha1": "f6fffc87571e5f76af2a77c4ebcc0e00909ced4e" + } + }, + "testutils": { + "version": "0.4.2", + "vcsRevision": "aa6e5216f4b4ab5aa971cdcdd70e1ec1203cedf2", + "url": "https://github.com/status-im/nim-testutils", + "downloadMethod": "git", + "dependencies": [ + "unittest2" + ], + "checksums": { + "sha1": "94427e0cce0e0c5841edcd3a6530b4e6b857a3cb" + } + }, + "faststreams": { + "version": "0.3.0", + "vcsRevision": "1b561a9e71b6bdad1c1cdff753418906037e9d09", + "url": "https://github.com/status-im/nim-faststreams.git", + "downloadMethod": "git", + "dependencies": [ + "stew", + "testutils", + "chronos", + "unittest2" + ], + "checksums": { + "sha1": "97edf9797924af48566a0af8267203dc21d80c77" + } + }, + "serialization": { + "version": "0.1.0", + "vcsRevision": "fcd0eadadde0ee000a63df8ab21dc4e9f015a790", + "url": "https://github.com/status-im/nim-serialization.git", + "downloadMethod": "git", + "dependencies": [ + "faststreams", + "unittest2", + "stew" + ], + "checksums": { + "sha1": "fef59519892cac70cccd81b612085caaa5e3e6cf" + } + }, + "json_serialization": { + "version": "0.1.0", + "vcsRevision": "c5f0e2465e8375dfc7aa0f56ccef67cb680bc6b0", + "url": "https://github.com/status-im/nim-json-serialization.git", + "downloadMethod": "git", + "dependencies": [ + "serialization", + "stew" + ], + "checksums": { + "sha1": "d89d79d0679a3a41b350e3ad4be56c0308cc5ec6" + } + }, + "chronicles": { + "version": "0.10.2", + "vcsRevision": "1682096306ddba8185dcfac360a8c3f952d721e4", + "url": "https://github.com/status-im/nim-chronicles.git", + "downloadMethod": "git", + "dependencies": [ + "testutils", + "json_serialization" + ], + "checksums": { + "sha1": "9a5bebb76b0f7d587a31e621d260119279e91c76" + } + }, + "asynctest": { + "version": "0.3.1", + "vcsRevision": "5347c59b4b057443a014722aa40800cd8bb95c69", + "url": "https://github.com/status-im/asynctest.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "53e0b610d13700296755a4ebe789882cae47a3b9" + } + }, + "nimcrypto": { + "version": "0.5.4", + "vcsRevision": "a5742a9a214ac33f91615f3862c7b099aec43b00", + "url": "https://github.com/cheatfate/nimcrypto", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "f76c87707cd4e96355b8bb6ef27e7f8b0aac1e08" + } + }, + "zlib": { + "version": "0.1.0", + "vcsRevision": "74cdeb54b21bededb5a515d36f608bc1850555a2", + "url": "https://github.com/status-im/nim-zlib", + "downloadMethod": "git", + "dependencies": [ + "stew" + ], + "checksums": { + "sha1": "01d330dc4c1924e56b1559ee73bc760e526f635c" + } + }, + "websock": { + "version": "0.1.0", + "vcsRevision": "73edde4417f7b45003113b7a34212c3ccd95b9fd", + "url": "https://github.com/status-im/nim-websock", + "downloadMethod": "git", + "dependencies": [ + "chronos", + "httputils", + "chronicles", + "stew", + "asynctest", + "nimcrypto", + "bearssl", + "zlib" + ], + "checksums": { + "sha1": "ec2b137543f280298ca48de9ed4461a033ba88d3" + } + }, + "news": { + "version": "0.5", + "vcsRevision": "e79420e835489132aaa412f993b565f5dd6295f4", + "url": "https://github.com/status-im/news", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "a5f1789bf650822156712fd3bdec1bf6ab4ac42e" + } + }, + "stint": { + "version": "0.0.1", + "vcsRevision": "036c71d06a6b22f8f967ba9d54afd2189c3872ca", + "url": "https://github.com/status-im/stint.git", + "downloadMethod": "git", + "dependencies": [ + "stew" + ], + "checksums": { + "sha1": "0f187a2115315ca898e5f9a30c5e506cf6057062" + } + } + } +} \ No newline at end of file diff --git a/vendor/nim-json-rpc/tests/all.nim b/vendor/nim-json-rpc/tests/all.nim index a5c83e3e2..38e23f291 100644 --- a/vendor/nim-json-rpc/tests/all.nim +++ b/vendor/nim-json-rpc/tests/all.nim @@ -9,3 +9,4 @@ import when not useNews: # The proxy implementation is based on websock import testproxy + import testhook diff --git a/vendor/nim-json-rpc/tests/nim.cfg b/vendor/nim-json-rpc/tests/nim.cfg new file mode 100644 index 000000000..371f6d79d --- /dev/null +++ b/vendor/nim-json-rpc/tests/nim.cfg @@ -0,0 +1,5 @@ +# Avoid some rare stack corruption while using exceptions with a SEH-enabled +# toolchain: https://github.com/status-im/nimbus-eth2/issues/3121 +@if windows and not vcc: + --define:nimRawSetjmp +@end diff --git a/vendor/nim-json-rpc/tests/testhook.nim b/vendor/nim-json-rpc/tests/testhook.nim new file mode 100644 index 000000000..326f11c9a --- /dev/null +++ b/vendor/nim-json-rpc/tests/testhook.nim @@ -0,0 +1,86 @@ +import + unittest, json, chronicles, + websock/websock, + ../json_rpc/[rpcclient, rpcserver, clients/config] + +const + serverHost = "localhost" + serverPort = 8547 + serverAddress = serverHost & ":" & $serverPort + +proc setupServer*(srv: RpcServer) = + srv.rpc("testHook") do(input: string): + return %("Hello " & input) + +proc authHeaders(): seq[(string, string)] = + @[("Auth-Token", "Good Token")] + +suite "HTTP server hook test": + proc mockAuth(req: HttpRequestRef): Future[HttpResponseRef] {.async.} = + if req.headers.getString("Auth-Token") == "Good Token": + return HttpResponseRef(nil) + + return await req.respond(Http401, "Unauthorized access") + + let srv = newRpcHttpServer([serverAddress], @[HttpAuthHook(mockAuth)]) + srv.setupServer() + srv.start() + + test "no auth token": + let client = newRpcHttpClient() + waitFor client.connect(serverHost, Port(serverPort), false) + expect ErrorResponse: + let r = waitFor client.call("testHook", %[%"abc"]) + + test "good auth token": + let client = newRpcHttpClient(getHeaders = authHeaders) + waitFor client.connect(serverHost, Port(serverPort), false) + let r = waitFor client.call("testHook", %[%"abc"]) + check r.getStr == "Hello abc" + + waitFor srv.closeWait() + +proc wsAuthHeaders(ctx: Hook, + headers: var HttpTable): Result[void, string] + {.gcsafe, raises: [Defect].} = + headers.add("Auth-Token", "Good Token") + return ok() + +suite "Websocket server hook test": + let hook = Hook(append: wsAuthHeaders) + + proc mockAuth(req: websock.HttpRequest): Future[bool] {.async.} = + if not req.headers.contains("Auth-Token"): + await req.sendResponse(code = Http403, data = "Missing Auth-Token") + return false + + let token = req.headers.getString("Auth-Token") + if token != "Good Token": + await req.sendResponse(code = Http401, data = "Unauthorized access") + return false + + return true + + let srv = newRpcWebSocketServer( + "127.0.0.1", + Port(8545), + authHooks = @[WsAuthHook(mockAuth)] + ) + srv.setupServer() + srv.start() + let client = newRpcWebSocketClient() + + test "no auth token": + try: + waitFor client.connect("ws://127.0.0.1:8545/") + check false + except CatchableError as e: + check e.msg == "Server did not reply with a websocket upgrade: Header code: 403 Header reason: Forbidden Address: 127.0.0.1:8545" + + test "good auth token": + waitFor client.connect("ws://127.0.0.1:8545/", hooks = @[hook]) + let r = waitFor client.call("testHook", %[%"abc"]) + check r.getStr == "Hello abc" + + srv.stop() + waitFor srv.closeWait() diff --git a/vendor/nim-json-serialization/.gitignore b/vendor/nim-json-serialization/.gitignore index ff45144c9..f2e7e9b9a 100644 --- a/vendor/nim-json-serialization/.gitignore +++ b/vendor/nim-json-serialization/.gitignore @@ -1,2 +1,4 @@ nimcache *.exe +nimble.develop +nimble.paths diff --git a/vendor/nim-json-serialization/config.nims b/vendor/nim-json-serialization/config.nims new file mode 100644 index 000000000..7c9db3205 --- /dev/null +++ b/vendor/nim-json-serialization/config.nims @@ -0,0 +1,4 @@ +# begin Nimble config (version 1) +when fileExists("nimble.paths"): + include "nimble.paths" +# end Nimble config diff --git a/vendor/nim-json-serialization/json_serialization/reader.nim b/vendor/nim-json-serialization/json_serialization/reader.nim index b71875b8c..ba39bdc42 100644 --- a/vendor/nim-json-serialization/json_serialization/reader.nim +++ b/vendor/nim-json-serialization/json_serialization/reader.nim @@ -394,6 +394,55 @@ iterator readObject*(r: var JsonReader, proc isNotNilCheck[T](x: ref T not nil) {.compileTime.} = discard proc isNotNilCheck[T](x: ptr T not nil) {.compileTime.} = discard +func isFieldExpected*(T: type): bool {.compileTime.} = + T isnot Option + +func totalExpectedFields*(T: type): int {.compileTime.} = + mixin isFieldExpected, + enumAllSerializedFields + + enumAllSerializedFields(T): + if isFieldExpected(FieldType): + inc result + +func setBitInWord(x: var uint, bit: int) {.inline.} = + let mask = uint(1) shl bit + x = x or mask + +const bitsPerWord = sizeof(uint) * 8 + +func expectedFieldsBitmask*(TT: type): auto {.compileTime.} = + type T = TT + + mixin isFieldExpected, + enumAllSerializedFields + + const requiredWords = + (totalSerializedFields(T) + bitsPerWord - 1) div bitsPerWord + + var res: array[requiredWords, uint] + + var i = 0 + enumAllSerializedFields(T): + if isFieldExpected(FieldType): + res[i div bitsPerWord].setBitInWord(i mod bitsPerWord) + inc i + + return res + +template setBitInArray[N](data: var array[N, uint], bitIdx: int) = + when data.len > 1: + setBitInWord(data[bitIdx div bitsPerWord], bitIdx mod bitsPerWord) + else: + setBitInWord(data[0], bitIdx) + +func isBitwiseSubsetOf[N](lhs, rhs: array[N, uint]): bool = + for i in low(lhs) .. high(lhs): + if (lhs[i] and rhs[i]) != lhs[i]: + return false + + true + # this construct catches `array[N, char]` which otherwise won't decompose into # openArray[char] - we treat any array-like thing-of-characters as a string in # the output @@ -564,44 +613,54 @@ proc readValue*[T](r: var JsonReader, value: var T) type T = type(value) r.skipToken tkCurlyLe - const expectedFields = T.totalSerializedFields - var readFields = 0 - when expectedFields > 0: - let fields = T.fieldReadersTable(ReaderType) - var expectedFieldPos = 0 + when T.totalSerializedFields > 0: + let + fieldsTable = T.fieldReadersTable(ReaderType) + + const + expectedFields = T.expectedFieldsBitmask + + var + encounteredFields: typeof(expectedFields) + mostLikelyNextField = 0 + while true: # Have the assignment parsed of the AVP if r.lexer.lazyTok == tkQuoted: r.lexer.accept if r.lexer.lazyTok != tkString: break - # Calculate/assemble handler + when T is tuple: - var reader = fields[][expectedFieldPos].reader - expectedFieldPos += 1 + let fieldIdx = mostLikelyNextField + mostLikelyNextField += 1 else: - var reader = findFieldReader(fields[], r.lexer.strVal, expectedFieldPos) - if reader != nil: + let fieldIdx = findFieldIdx(fieldsTable[], + r.lexer.strVal, + mostLikelyNextField) + if fieldIdx != -1: + let reader = fieldsTable[][fieldIdx].reader r.lexer.next() r.skipToken tkColon reader(value, r) - inc readFields - else: + encounteredFields.setBitInArray(fieldIdx) + elif r.allowUnknownFields: r.lexer.next() r.skipToken tkColon - if r.allowUnknownFields: - r.skipSingleJsValue() - else: - const typeName = typetraits.name(T) - r.raiseUnexpectedField(r.lexer.strVal, string typeName) + r.skipSingleJsValue() + else: + const typeName = typetraits.name(T) + r.raiseUnexpectedField(r.lexer.strVal, cstring typeName) + if r.lexer.lazyTok == tkComma: r.lexer.next() else: break - if r.requireAllFields and readFields != expectedFields: - const typeName = typetraits.name(T) - r.raiseIncompleteObject(typeName) + if r.requireAllFields and + not expectedFields.isBitwiseSubsetOf(encounteredFields): + const typeName = typetraits.name(T) + r.raiseIncompleteObject(typeName) r.lexer.accept r.skipToken tkCurlyRi diff --git a/vendor/nim-json-serialization/json_serialization/std/options.nim b/vendor/nim-json-serialization/json_serialization/std/options.nim index 39be41a9a..414152a0f 100644 --- a/vendor/nim-json-serialization/json_serialization/std/options.nim +++ b/vendor/nim-json-serialization/json_serialization/std/options.nim @@ -1,17 +1,31 @@ import std/options, ../../json_serialization/[reader, writer, lexer] export options +template writeObjectField*(w: var JsonWriter, + record: auto, + fieldName: static string, + field: Option): bool = + mixin writeObjectField + + if field.isSome: + writeObjectField(w, record, fieldName, field.get) + else: + false + proc writeValue*(writer: var JsonWriter, value: Option) = + mixin writeValue + if value.isSome: writer.writeValue value.get else: writer.writeValue JsonString("null") proc readValue*[T](reader: var JsonReader, value: var Option[T]) = + mixin readValue + let tok = reader.lexer.lazyTok if tok == tkNull: reset value reader.lexer.next() else: value = some reader.readValue(T) - diff --git a/vendor/nim-json-serialization/json_serialization/stew/results.nim b/vendor/nim-json-serialization/json_serialization/stew/results.nim new file mode 100644 index 000000000..ad958e1b5 --- /dev/null +++ b/vendor/nim-json-serialization/json_serialization/stew/results.nim @@ -0,0 +1,37 @@ +import + stew/results, ../../json_serialization/[reader, writer, lexer] + +export + results + +template writeObjectField*[T](w: var JsonWriter, + record: auto, + fieldName: static string, + field: Result[T, void]): bool = + mixin writeObjectField + + if field.isOk: + writeObjectField(w, record, fieldName, field.get) + else: + false + +proc writeValue*[T](writer: var JsonWriter, value: Result[T, void]) = + mixin writeValue + + if value.isOk: + writer.writeValue value.get + else: + writer.writeValue JsonString("null") + +proc readValue*[T](reader: var JsonReader, value: var Result[T, void]) = + mixin readValue + + let tok = reader.lexer.lazyTok + if tok == tkNull: + reset value + reader.lexer.next() + else: + value.ok reader.readValue(T) + +func isFieldExpected*[T, E](_: type[Result[T, E]]): bool {.compileTime.} = + false diff --git a/vendor/nim-json-serialization/json_serialization/writer.nim b/vendor/nim-json-serialization/json_serialization/writer.nim index a90646ecb..dabb89c6f 100644 --- a/vendor/nim-json-serialization/json_serialization/writer.nim +++ b/vendor/nim-json-serialization/json_serialization/writer.nim @@ -103,9 +103,7 @@ template endRecordField*(w: var JsonWriter) = endRecord(w) w.state = AfterField -proc writeIterable*(w: var JsonWriter, collection: auto) = - mixin writeValue - +iterator stepwiseArrayCreation*[C](w: var JsonWriter, collection: C): auto = append '[' if w.hasPrettyOutput: @@ -122,7 +120,7 @@ proc writeIterable*(w: var JsonWriter, collection: auto) = indent() w.state = RecordExpected - w.writeValue(e) + yield e first = false if w.hasPrettyOutput: @@ -132,6 +130,11 @@ proc writeIterable*(w: var JsonWriter, collection: auto) = append ']' +proc writeIterable*(w: var JsonWriter, collection: auto) = + mixin writeValue + for e in w.stepwiseArrayCreation(collection): + w.writeValue(e) + proc writeArray*[T](w: var JsonWriter, elements: openArray[T]) = writeIterable(w, elements) @@ -142,8 +145,24 @@ template isStringLike(v: string|cstring|openArray[char]|seq[char]): bool = true template isStringLike[N](v: array[N, char]): bool = true template isStringLike(v: auto): bool = false +template writeObjectField*[FieldType, RecordType](w: var JsonWriter, + record: RecordType, + fieldName: static string, + field: FieldType): bool = + mixin writeFieldIMPL, writeValue + + type + R = type record + + w.writeFieldName(fieldName) + when RecordType is tuple: + w.writeValue(field) + else: + w.writeFieldIMPL(FieldTag[R, fieldName], field, record) + true + proc writeValue*(w: var JsonWriter, value: auto) = - mixin enumInstanceSerializedFields, writeValue, writeFieldIMPL + mixin enumInstanceSerializedFields, writeValue when value is JsonNode: append if w.hasPrettyOutput: value.pretty @@ -199,7 +218,7 @@ proc writeValue*(w: var JsonWriter, value: auto) = w.stream.writeText ord(value) elif value is range: - when low(value) < 0: + when low(typeof(value)) < 0: w.stream.writeText int64(value) else: w.stream.writeText uint64(value) @@ -216,13 +235,12 @@ proc writeValue*(w: var JsonWriter, value: auto) = w.writeArray(value) elif value is (object or tuple): - w.beginRecord(type(value)) type RecordType = type value + w.beginRecord RecordType value.enumInstanceSerializedFields(fieldName, field): - type FieldType = type field - w.writeFieldName(fieldName) - w.writeFieldIMPL(FieldTag[RecordType, fieldName, FieldType], field, value) - w.state = AfterField + mixin writeObjectField + if writeObjectField(w, value, fieldName, field): + w.state = AfterField w.endRecord() else: diff --git a/vendor/nim-json-serialization/nimble.lock b/vendor/nim-json-serialization/nimble.lock new file mode 100644 index 000000000..6d48a98d2 --- /dev/null +++ b/vendor/nim-json-serialization/nimble.lock @@ -0,0 +1,105 @@ +{ + "version": 1, + "packages": { + "unittest2": { + "version": "0.0.4", + "vcsRevision": "f180f596c88dfd266f746ed6f8dbebce39c824db", + "url": "https://github.com/status-im/nim-unittest2.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "fa309c41eaf6ef57895b9e603f2620a2f6e11780" + } + }, + "stew": { + "version": "0.1.0", + "vcsRevision": "6ad35b876fb6ebe0dfee0f697af173acc47906ee", + "url": "https://github.com/status-im/nim-stew.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "46d58c4feb457f3241e3347778334e325dce5268" + } + }, + "httputils": { + "version": "0.3.0", + "vcsRevision": "689da19e9e9cfff4ced85e2b25c6b2b5598ed079", + "url": "https://github.com/status-im/nim-http-utils.git", + "downloadMethod": "git", + "dependencies": [ + "stew" + ], + "checksums": { + "sha1": "4ad3ad68d13c50184180ab4b2eacc0bd7ed2ed44" + } + }, + "bearssl": { + "version": "0.1.5", + "vcsRevision": "ba80e2a0d7ae8aab666cee013e38ff8d33a3e5e7", + "url": "https://github.com/status-im/nim-bearssl", + "downloadMethod": "git", + "dependencies": [ + "unittest2" + ], + "checksums": { + "sha1": "383abd5becc77bf8e365b780a29d20529e1d9c4c" + } + }, + "chronos": { + "version": "3.0.11", + "vcsRevision": "17fed89c99beac5a92d3668d0d3e9b0e4ac13936", + "url": "https://github.com/status-im/nim-chronos.git", + "downloadMethod": "git", + "dependencies": [ + "stew", + "bearssl", + "httputils", + "unittest2" + ], + "checksums": { + "sha1": "f6fffc87571e5f76af2a77c4ebcc0e00909ced4e" + } + }, + "testutils": { + "version": "0.4.2", + "vcsRevision": "aa6e5216f4b4ab5aa971cdcdd70e1ec1203cedf2", + "url": "https://github.com/status-im/nim-testutils", + "downloadMethod": "git", + "dependencies": [ + "unittest2" + ], + "checksums": { + "sha1": "94427e0cce0e0c5841edcd3a6530b4e6b857a3cb" + } + }, + "faststreams": { + "version": "0.3.0", + "vcsRevision": "1b561a9e71b6bdad1c1cdff753418906037e9d09", + "url": "https://github.com/status-im/nim-faststreams.git", + "downloadMethod": "git", + "dependencies": [ + "stew", + "testutils", + "chronos", + "unittest2" + ], + "checksums": { + "sha1": "97edf9797924af48566a0af8267203dc21d80c77" + } + }, + "serialization": { + "version": "0.1.0", + "vcsRevision": "fcd0eadadde0ee000a63df8ab21dc4e9f015a790", + "url": "https://github.com/status-im/nim-serialization.git", + "downloadMethod": "git", + "dependencies": [ + "faststreams", + "unittest2", + "stew" + ], + "checksums": { + "sha1": "fef59519892cac70cccd81b612085caaa5e3e6cf" + } + } + } +} \ No newline at end of file diff --git a/vendor/nim-json-serialization/tests/test_serialization.nim b/vendor/nim-json-serialization/tests/test_serialization.nim index ddf0692ed..094186ef9 100644 --- a/vendor/nim-json-serialization/tests/test_serialization.nim +++ b/vendor/nim-json-serialization/tests/test_serialization.nim @@ -4,7 +4,8 @@ import serialization/testing/generic_suite, ../json_serialization, ./utils, ../json_serialization/lexer, - ../json_serialization/std/[options, sets, tables] + ../json_serialization/std/[options, sets, tables], + ../json_serialization/stew/results type Foo = object @@ -72,9 +73,43 @@ type entry, exit: TokKind dup: bool + HoldsResultOpt* = object + o*: Opt[Simple] + r*: ref Simple + + WithCustomFieldRule* = object + str*: string + intVal*: int + + OtherOptionTest* = object + a*: Option[Meter] + b*: Option[Meter] + + NestedOptionTest* = object + c*: Option[OtherOptionTest] + d*: Option[OtherOptionTest] + + SeqOptionTest* = object + a*: seq[Option[Meter]] + b*: Meter + + OtherOptionTest2* = object + a*: Option[Meter] + b*: Option[Meter] + c*: Option[Meter] + var customVisit: TokenRegistry +Json.useCustomSerialization(WithCustomFieldRule.intVal): + read: + try: + parseInt reader.readValue(string) + except ValueError: + reader.raiseUnexpectedValue("string encoded integer expected") + write: + writer.writeValue $value + template registerVisit(reader: var JsonReader; body: untyped): untyped = if customVisit.entry == tkError: customVisit.entry = reader.lexer.lazyTok @@ -322,12 +357,106 @@ suite "toJson tests": r == Json.decode("""{"type":"uint8", "renamed":"field"}""", HasUnusualFieldNames) test "Option types": + check: + 2 == static(HoldsOption.totalSerializedFields) + 1 == static(HoldsOption.totalExpectedFields) + + 2 == static(Foo.totalSerializedFields) + 2 == static(Foo.totalExpectedFields) + let h1 = HoldsOption(o: some Simple(x: 1, y: "2", distance: Meter(3))) h2 = HoldsOption(r: newSimple(1, "2", Meter(3))) + h3 = Json.decode("""{"r":{"distance":3,"x":1,"y":"2"}}""", + HoldsOption, requireAllFields = true) Json.roundtripTest h1, """{"r":null,"o":{"distance":3,"x":1,"y":"2"}}""" - Json.roundtripTest h2, """{"r":{"distance":3,"x":1,"y":"2"},"o":null}""" + Json.roundtripTest h2, """{"r":{"distance":3,"x":1,"y":"2"}}""" + + check h3 == h2 + + expect SerializationError: + let h4 = Json.decode("""{"o":{"distance":3,"x":1,"y":"2"}}""", + HoldsOption, requireAllFields = true) + + test "Nested option types": + let + h3 = OtherOptionTest() + h4 = OtherOptionTest(a: some Meter(1)) + h5 = OtherOptionTest(b: some Meter(2)) + h6 = OtherOptionTest(a: some Meter(3), b: some Meter(4)) + + Json.roundtripTest h3, """{}""" + Json.roundtripTest h4, """{"a":1}""" + Json.roundtripTest h5, """{"b":2}""" + Json.roundtripTest h6, """{"a":3,"b":4}""" + + let + arr = @[some h3, some h4, some h5, some h6, none(OtherOptionTest)] + results = @[ + """{"c":{},"d":{}}""", + """{"c":{},"d":{"a":1}}""", + """{"c":{},"d":{"b":2}}""", + """{"c":{},"d":{"a":3,"b":4}}""", + """{"c":{}}""", + """{"c":{"a":1},"d":{}}""", + """{"c":{"a":1},"d":{"a":1}}""", + """{"c":{"a":1},"d":{"b":2}}""", + """{"c":{"a":1},"d":{"a":3,"b":4}}""", + """{"c":{"a":1}}""", + """{"c":{"b":2},"d":{}}""", + """{"c":{"b":2},"d":{"a":1}}""", + """{"c":{"b":2},"d":{"b":2}}""", + """{"c":{"b":2},"d":{"a":3,"b":4}}""", + """{"c":{"b":2}}""", + """{"c":{"a":3,"b":4},"d":{}}""", + """{"c":{"a":3,"b":4},"d":{"a":1}}""", + """{"c":{"a":3,"b":4},"d":{"b":2}}""", + """{"c":{"a":3,"b":4},"d":{"a":3,"b":4}}""", + """{"c":{"a":3,"b":4}}""", + """{"d":{}}""", + """{"d":{"a":1}}""", + """{"d":{"b":2}}""", + """{"d":{"a":3,"b":4}}""", + """{}""" + ] + + + var r = 0 + for a in arr: + for b in arr: + Json.roundtripTest NestedOptionTest(c: a, d: b), results[r] + r.inc + + Json.roundtripTest SeqOptionTest(a: @[some 5.Meter, none Meter], b: Meter(5)), """{"a":[5,null],"b":5}""" + Json.roundtripTest OtherOptionTest2(a: some 5.Meter, b: none Meter, c: some 10.Meter), """{"a":5,"c":10}""" + + test "Result Opt types": + check: + false == static(isFieldExpected Opt[Simple]) + 2 == static(HoldsResultOpt.totalSerializedFields) + 1 == static(HoldsResultOpt.totalExpectedFields) + + let + h1 = HoldsResultOpt(o: Opt[Simple].ok Simple(x: 1, y: "2", distance: Meter(3))) + h2 = HoldsResultOpt(r: newSimple(1, "2", Meter(3))) + + Json.roundtripTest h1, """{"o":{"distance":3,"x":1,"y":"2"},"r":null}""" + Json.roundtripTest h2, """{"r":{"distance":3,"x":1,"y":"2"}}""" + + let + h3 = Json.decode("""{"r":{"distance":3,"x":1,"y":"2"}}""", + HoldsResultOpt, requireAllFields = true) + + check h3 == h2 + + expect SerializationError: + let h4 = Json.decode("""{"o":{"distance":3,"x":1,"y":"2"}}""", + HoldsResultOpt, requireAllFields = true) + + test "Custom field serialization": + let obj = WithCustomFieldRule(str: "test", intVal: 10) + Json.roundtripTest obj, """{"str":"test","intVal":"10"}""" test "Case object as field": let diff --git a/vendor/nim-libbacktrace/.gitignore b/vendor/nim-libbacktrace/.gitignore index 69015f6a8..f621d63c5 100644 --- a/vendor/nim-libbacktrace/.gitignore +++ b/vendor/nim-libbacktrace/.gitignore @@ -11,3 +11,5 @@ nimcache *.exe *.dll +nimble.develop +nimble.paths diff --git a/vendor/nim-libbacktrace/config.nims b/vendor/nim-libbacktrace/config.nims new file mode 100644 index 000000000..7c9db3205 --- /dev/null +++ b/vendor/nim-libbacktrace/config.nims @@ -0,0 +1,4 @@ +# begin Nimble config (version 1) +when fileExists("nimble.paths"): + include "nimble.paths" +# end Nimble config diff --git a/vendor/nim-libbacktrace/libbacktrace.nim b/vendor/nim-libbacktrace/libbacktrace.nim index a35518591..0784c0536 100644 --- a/vendor/nim-libbacktrace/libbacktrace.nim +++ b/vendor/nim-libbacktrace/libbacktrace.nim @@ -21,7 +21,7 @@ when defined(nimStackTraceOverride) and defined(nimHasStacktracesModule): # there, but we might still want to import this module with a global # "--import:libbacktrace" Nim compiler flag. when not (defined(nimscript) or defined(js)): - import algorithm, libbacktrace_wrapper, os, system/ansi_c, strutils + import algorithm, libbacktrace/wrapper, os, system/ansi_c, strutils const topLevelPath = currentSourcePath.parentDir().replace('\\', '/') @@ -118,4 +118,3 @@ when not (defined(nimscript) or defined(js)): when defined(nimStackTraceOverride) and declared(registerStackTraceOverrideGetDebuggingInfo): registerStackTraceOverrideGetDebuggingInfo(getDebuggingInfo) - diff --git a/vendor/nim-libbacktrace/libbacktrace.nimble b/vendor/nim-libbacktrace/libbacktrace.nimble index 6a183116a..105c4cd8c 100644 --- a/vendor/nim-libbacktrace/libbacktrace.nimble +++ b/vendor/nim-libbacktrace/libbacktrace.nimble @@ -14,7 +14,7 @@ author = "Status Research & Development GmbH" description = "Nim wrapper for libbacktrace" license = "MIT or Apache License 2.0" installDirs = @["vendor/whereami/src", "install"] -installFiles = @["libbacktrace_wrapper.c", "libbacktrace_wrapper.cpp", "libbacktrace_wrapper.h", "libbacktrace_wrapper.nim"] +installFiles = @["libbacktrace_wrapper.c", "libbacktrace_wrapper.cpp", "libbacktrace_wrapper.h", "libbacktrace/wrapper.nim"] requires "nim >= 1.0" @@ -24,4 +24,3 @@ before install: when defined(windows): make = "mingw32-make" exec make - diff --git a/vendor/nim-libbacktrace/libbacktrace_wrapper.nim b/vendor/nim-libbacktrace/libbacktrace/wrapper.nim similarity index 99% rename from vendor/nim-libbacktrace/libbacktrace_wrapper.nim rename to vendor/nim-libbacktrace/libbacktrace/wrapper.nim index 0e5b4f7db..a8b8aa588 100644 --- a/vendor/nim-libbacktrace/libbacktrace_wrapper.nim +++ b/vendor/nim-libbacktrace/libbacktrace/wrapper.nim @@ -41,4 +41,3 @@ type # Char pointers in the returned struct need to be freed by the caller. proc get_debugging_info_c*(program_counters: ptr cuintptr_t, max_length: cint): ptr DebuggingInfo {. importc: "get_debugging_info_c", header: "libbacktrace_wrapper.h".} - diff --git a/vendor/nim-libbacktrace/nimble.lock b/vendor/nim-libbacktrace/nimble.lock new file mode 100644 index 000000000..a05d20dd3 --- /dev/null +++ b/vendor/nim-libbacktrace/nimble.lock @@ -0,0 +1,4 @@ +{ + "version": 1, + "packages": {} +} \ No newline at end of file diff --git a/vendor/nim-libbacktrace/vendor/libbacktrace-upstream/libtool b/vendor/nim-libbacktrace/vendor/libbacktrace-upstream/libtool index 07d6eceec..effa3fc1f 100755 --- a/vendor/nim-libbacktrace/vendor/libbacktrace-upstream/libtool +++ b/vendor/nim-libbacktrace/vendor/libbacktrace-upstream/libtool @@ -2,7 +2,7 @@ # libtool - Provide generalized library-building support services. # Generated automatically by config.status (libbacktrace) version-unused -# Libtool was configured on host fv-az198-461: +# Libtool was configured on host fv-az83-748: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, diff --git a/vendor/nim-libp2p/.assets/full-logo.svg b/vendor/nim-libp2p/.assets/full-logo.svg new file mode 100644 index 000000000..92be1a9fd --- /dev/null +++ b/vendor/nim-libp2p/.assets/full-logo.svg @@ -0,0 +1,1141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/nim-libp2p/.assets/small-logo.svg b/vendor/nim-libp2p/.assets/small-logo.svg new file mode 100644 index 000000000..621f3eaa9 --- /dev/null +++ b/vendor/nim-libp2p/.assets/small-logo.svg @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/nim-libp2p/.github/workflows/bumper.yml b/vendor/nim-libp2p/.github/workflows/bumper.yml new file mode 100644 index 000000000..d16c38f6b --- /dev/null +++ b/vendor/nim-libp2p/.github/workflows/bumper.yml @@ -0,0 +1,36 @@ +name: Bumper +on: + push: + branches: + - unstable + - bumper + workflow_dispatch: + +jobs: + bumpNimbus: + runs-on: ubuntu-latest + steps: + - name: Clone NBC + uses: actions/checkout@v2 + with: + repository: status-im/nimbus-eth2 + ref: unstable + path: nbc + submodules: true + fetch-depth: 0 + token: ${{ secrets.ACTIONS_GITHUB_TOKEN }} + + - name: Checkout this ref + run: | + cd nbc/vendor/nim-libp2p + git checkout $GITHUB_SHA + + - name: Commit this bump + run: | + cd nbc + git config --global user.email "${{ github.actor }}@users.noreply.github.com" + git config --global user.name = "${{ github.actor }}" + git commit -a -m "auto-bump nim-libp2p" + git branch -D nim-libp2p-auto-bump-${GITHUB_REF##*/} || true + git switch -c nim-libp2p-auto-bump-${GITHUB_REF##*/} + git push -f origin nim-libp2p-auto-bump-${GITHUB_REF##*/} diff --git a/vendor/nim-libp2p/.github/workflows/ci.yml b/vendor/nim-libp2p/.github/workflows/ci.yml index 9ea293eb0..d671424ba 100644 --- a/vendor/nim-libp2p/.github/workflows/ci.yml +++ b/vendor/nim-libp2p/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: cpu: amd64 #- os: windows #cpu: i386 - branch: [version-1-2, devel] + branch: [version-1-2, version-1-6] include: - target: os: linux @@ -32,7 +32,7 @@ jobs: shell: bash - target: os: macos - builder: macos-10.15 + builder: macos-12 shell: bash - target: os: windows @@ -162,94 +162,7 @@ jobs: - name: Run tests run: | - if [[ "${{ matrix.target.os }}" == "windows" ]]; then - # https://github.com/status-im/nimbus-eth2/issues/3121 - export NIMFLAGS="-d:nimRawSetjmp" - fi nim --version nimble --version nimble install_pinned nimble test - - bumpNBC-stable: - if: github.ref == 'refs/heads/master' - needs: build - runs-on: ubuntu-latest - steps: - - uses: status-im/github-app-token@v1 - name: Generate token - id: generate-token - with: - app_id: ${{ secrets.BUMP_BOT_APP_ID }} - private_key: ${{ secrets.BUMP_BOT_APP_PRIVATE_KEY }} - - - name: Clone NBC - uses: actions/checkout@v2 - with: - repository: status-im/nimbus-eth2 - ref: unstable - path: nbc - submodules: true - fetch-depth: 0 - - - name: Checkout this ref - run: | - cd nbc/vendor/nim-libp2p - git checkout $GITHUB_SHA - - - name: Commit this bump - run: | - cd nbc - git config --global user.email "${{ github.actor }}@users.noreply.github.com" - git config --global user.name = "${{ github.actor }}" - git commit -a -m "auto-bump nim-libp2p" - - - name: Make PR - uses: peter-evans/create-pull-request@v3.5.0 - with: - branch: nim-libp2p-auto-bump - path: nbc - token: ${{ steps.generate-token.outputs.token }} - title: nim-libp2p auto bump - - bumpNBC-unstable: - if: github.ref == 'refs/heads/unstable' - needs: build - runs-on: ubuntu-latest - steps: - - uses: status-im/github-app-token@v1 - name: Generate token - id: generate-token - with: - app_id: ${{ secrets.BUMP_BOT_APP_ID }} - private_key: ${{ secrets.BUMP_BOT_APP_PRIVATE_KEY }} - - - name: Clone NBC - uses: actions/checkout@v2 - with: - repository: status-im/nimbus-eth2 - ref: unstable - path: nbc - submodules: true - fetch-depth: 0 - - - name: Checkout this ref - run: | - cd nbc/vendor/nim-libp2p - git checkout $GITHUB_SHA - - - name: Commit this bump - run: | - cd nbc - git config --global user.email "${{ github.actor }}@users.noreply.github.com" - git config --global user.name = "${{ github.actor }}" - git commit -a -m "auto-bump nim-libp2p" - - - name: Make PR - uses: peter-evans/create-pull-request@v3.5.0 - with: - branch: nim-libp2p-auto-bump-unstable - path: nbc - token: ${{ steps.generate-token.outputs.token }} - title: nim-libp2p unstable auto bump - draft: true diff --git a/vendor/nim-libp2p/.github/workflows/codecov.yml b/vendor/nim-libp2p/.github/workflows/codecov.yml index f82646063..860ab7849 100644 --- a/vendor/nim-libp2p/.github/workflows/codecov.yml +++ b/vendor/nim-libp2p/.github/workflows/codecov.yml @@ -25,6 +25,8 @@ jobs: ] steps: - uses: actions/checkout@v2 + with: + fetch-depth: 0 - name: Run run: | sudo apt-get update @@ -63,6 +65,8 @@ jobs: ] steps: - uses: actions/checkout@v2 + with: + fetch-depth: 0 - name: Run run: | sudo apt-get update @@ -104,6 +108,8 @@ jobs: ] steps: - uses: actions/checkout@v2 + with: + fetch-depth: 0 - name: Run run: | sudo apt-get update diff --git a/vendor/nim-libp2p/.github/workflows/doc.yml b/vendor/nim-libp2p/.github/workflows/doc.yml new file mode 100644 index 000000000..862c571ea --- /dev/null +++ b/vendor/nim-libp2p/.github/workflows/doc.yml @@ -0,0 +1,99 @@ +name: Docgen +on: + push: + workflow_dispatch: + + +jobs: + build: + timeout-minutes: 20 + + name: 'Generate & upload documentation' + runs-on: 'ubuntu-20.04' + continue-on-error: true + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: true + + - uses: jiro4989/setup-nim-action@v1 + with: + nim-version: 'stable' + + - name: Generate doc + run: | + nim --version + nimble --version + nimble install_pinned + # nim doc can "fail", but the doc is still generated + nim doc --git.url:https://github.com/status-im/nim-libp2p --git.commit:${GITHUB_REF##*/} --outdir:${GITHUB_REF##*/} --project libp2p || true + + # check that the folder exists + ls ${GITHUB_REF##*/} + + - name: Clone the gh-pages branch + uses: actions/checkout@v2 + with: + repository: status-im/nim-libp2p + ref: gh-pages + path: subdoc + submodules: true + fetch-depth: 0 + + - name: Commit & push + run: | + cd subdoc + + # Delete merged branches doc's + for branch in $(git branch -vv | grep ': gone]' | awk '{print $1}'); do rm -rf $branch; done + + # Update / create this branch doc + rm -rf ${GITHUB_REF##*/} + mv ../${GITHUB_REF##*/} . + + # Remove .idx files + # NOTE: git also uses idx files in his + # internal folder, hence the `*` instead of `.` + find * -name "*.idx" -delete + git add . + git config --global user.email "${{ github.actor }}@users.noreply.github.com" + git config --global user.name = "${{ github.actor }}" + git commit -a -m "update docs for ${GITHUB_REF##*/}" + git push origin gh-pages + + update_site: + if: github.ref == 'refs/heads/master' + name: 'Rebuild website' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - uses: actions/setup-python@v2 + with: + python-version: 3.x + + - name: Generate website + run: pip install mkdocs-material && mkdocs build + + - name: Clone the gh-pages branch + uses: actions/checkout@v2 + with: + repository: status-im/nim-libp2p + ref: gh-pages + path: subdoc + fetch-depth: 0 + + - name: Commit & push + run: | + cd subdoc + + rm -rf docs + mv ../site docs + + git add . + git config --global user.email "${{ github.actor }}@users.noreply.github.com" + git config --global user.name = "${{ github.actor }}" + git commit -a -m "update website" + git push origin gh-pages diff --git a/vendor/nim-libp2p/.github/workflows/multi_nim.yml b/vendor/nim-libp2p/.github/workflows/multi_nim.yml index 391f3971b..4b52a8159 100644 --- a/vendor/nim-libp2p/.github/workflows/multi_nim.yml +++ b/vendor/nim-libp2p/.github/workflows/multi_nim.yml @@ -29,7 +29,7 @@ jobs: shell: bash - target: os: macos - builder: macos-10.15 + builder: macos-12 shell: bash - target: os: windows @@ -160,10 +160,6 @@ jobs: - name: Run tests run: | - if [[ "${{ matrix.target.os }}" == "windows" ]]; then - # https://github.com/status-im/nimbus-eth2/issues/3121 - export NIMFLAGS="-d:nimRawSetjmp" - fi nim --version nimble --version nimble install -y --depsOnly diff --git a/vendor/nim-libp2p/.gitignore b/vendor/nim-libp2p/.gitignore index e2d515b38..ec585b0d3 100644 --- a/vendor/nim-libp2p/.gitignore +++ b/vendor/nim-libp2p/.gitignore @@ -13,3 +13,5 @@ build/ .vscode/ .DS_Store tests/pubsub/testgossipsub +nimble.develop +nimble.paths diff --git a/vendor/nim-libp2p/.pinned b/vendor/nim-libp2p/.pinned index 46f7cb1a4..f85d7a2e5 100644 --- a/vendor/nim-libp2p/.pinned +++ b/vendor/nim-libp2p/.pinned @@ -1,17 +1,16 @@ -asynctest;https://github.com/markspanbroek/asynctest@#5347c59b4b057443a014722aa40800cd8bb95c69 -bearssl;https://github.com/status-im/nim-bearssl@#0ebb1d7a4af5f4b4d4756a9b6dbfe5d411fa55d9 -chronicles;https://github.com/status-im/nim-chronicles@#2a2681b60289aaf7895b7056f22616081eb1a882 -chronos;https://github.com/status-im/nim-chronos@#875d7d8e6ef0803ae1c331dbf76b1981b0caeb15 -dnsclient;https://github.com/ba0f3/dnsclient.nim@#fbb76f8af8a33ab818184a7d4406d9fee20993be +bearssl;https://github.com/status-im/nim-bearssl@#25009951ff8e0006171d566e3c7dc73a8231c2ed +chronicles;https://github.com/status-im/nim-chronicles@#32ac8679680ea699f7dbc046e8e0131cac97d41a +chronos;https://github.com/status-im/nim-chronos@#41b82cdea34744148600b67a9154331b76181189 +dnsclient;https://github.com/ba0f3/dnsclient.nim@#4960de2b345f567b12f09a08e9967af104ab39a3 faststreams;https://github.com/status-im/nim-faststreams@#49e2c52eb5dda46b1c9c10d079abe7bffe6cea89 httputils;https://github.com/status-im/nim-http-utils@#f83fbce4d6ec7927b75be3f85e4fa905fcb69788 -json_serialization;https://github.com/status-im/nim-json-serialization@#3509706517f3562cbcbe9d94988eccdd80474ab8 -metrics;https://github.com/status-im/nim-metrics@#11edec862f96e42374bc2d584c84cc88d5d1f95f -nimcrypto;https://github.com/cheatfate/nimcrypto@#a5742a9a214ac33f91615f3862c7b099aec43b00 -secp256k1;https://github.com/status-im/nim-secp256k1@#e092373a5cbe1fa25abfc62e0f2a5f138dc3fb13 -serialization;https://github.com/status-im/nim-serialization@#9631fbd1c81c8b25ff8740df440ca7ba87fa6131 -stew;https://github.com/status-im/nim-stew@#cdb1f213d073fd2ecbdaf35a866417657da9294c -testutils;https://github.com/status-im/nim-testutils@#aa6e5216f4b4ab5aa971cdcdd70e1ec1203cedf2 -unittest2;https://github.com/status-im/nim-unittest2@#4e2893eacb916c7678fdc4935ff7420f13bf3a9c -websock;https://github.com/status-im/nim-websock@#8927db93f6ca96abaacfea39f8ca50ce9d41bcdb -zlib;https://github.com/status-im/nim-zlib@#74cdeb54b21bededb5a515d36f608bc1850555a2 \ No newline at end of file +json_serialization;https://github.com/status-im/nim-json-serialization@#e5b18fb710c3d0167ec79f3b892f5a7a1bc6d1a4 +metrics;https://github.com/status-im/nim-metrics@#9070af9c830e93e5239ddc488cd65aa6f609ba73 +nimcrypto;https://github.com/cheatfate/nimcrypto@#24e006df85927f64916e60511620583b11403178 +secp256k1;https://github.com/status-im/nim-secp256k1@#5340cf188168d6afcafc8023770d880f067c0b2f +serialization;https://github.com/status-im/nim-serialization@#493d18b8292fc03aa4f835fd825dea1183f97466 +stew;https://github.com/status-im/nim-stew@#598246620da5c41d0e92a8dd6aab0755381b21cd +testutils;https://github.com/status-im/nim-testutils@#dfc4c1b39f9ded9baf6365014de2b4bfb4dafc34 +unittest2;https://github.com/status-im/nim-unittest2@#f180f596c88dfd266f746ed6f8dbebce39c824db +websock;https://github.com/status-im/nim-websock@#8a72c0f7690802753b1d59887745b1ce1f0c8b3d +zlib;https://github.com/status-im/nim-zlib@#6a6670afba6b97b29b920340e2641978c05ab4d8 \ No newline at end of file diff --git a/vendor/nim-libp2p/README.md b/vendor/nim-libp2p/README.md index f8dfec30c..61018ee81 100644 --- a/vendor/nim-libp2p/README.md +++ b/vendor/nim-libp2p/README.md @@ -1,5 +1,5 @@

- libp2p hex logo + nim-libp2p logo

The Nim implementation of the libp2p Networking Stack.

@@ -7,7 +7,7 @@

- +

@@ -18,28 +18,16 @@ ## Introduction -An implementation of [libp2p](https://libp2p.io/) in Nim. - -## Project Status -libp2p is used in production by a few projects at [Status](https://github.com/status-im), including [Nimbus](https://github.com/status-im/nimbus-eth2). - -While far from complete, currently available components are stable. - -Check our [examples folder](/examples) to get started! +An implementation of [libp2p](https://libp2p.io/) in [Nim](https://nim-lang.org/). # Table of Contents - [Background](#background) - [Install](#install) - - [Prerequisite](#prerequisite) -- [Usage](#usage) - - [API](#api) - - [Getting Started](#getting-started) - - [Tutorials and Examples](#tutorials-and-examples) - - [Using the Go Daemon](#using-the-go-daemon) +- [Getting Started](#getting-started) +- [Modules](#modules) +- [Users](#users) - [Development](#development) - - [Tests](#tests) - - [Packages](#packages) -- [Contribute](#contribute) + - [Contribute](#contribute) - [Core Developers](#core-developers) - [License](#license) @@ -54,33 +42,61 @@ libp2p grew out of IPFS, but it is built so that lots of people can use it, for - [Here](https://github.com/libp2p/libp2p#description) is an overview of libp2p and its implementations in other programming languages. ## Install +**Prerequisite** +- [Nim](https://nim-lang.org/install.html) ``` nimble install libp2p ``` -### Prerequisite -- [Nim](https://nim-lang.org/install.html) -## Usage +## Getting Started +You'll find the documentation [here](https://status-im.github.io/nim-libp2p/docs/). -### API -The specification is available in the [docs/api](docs/api) folder. +**Go Daemon:** +Please find the installation and usage intructions in [daemonapi.md](examples/go-daemon/daemonapi.md). -### Getting Started -Please read the [GETTING_STARTED.md](docs/GETTING_STARTED.md) guide. +## Modules -### Tutorials and Examples -Example code can be found in the [examples folder](/examples). +List of packages modules implemented in nim-libp2p: -#### Direct Chat Tutorial -- [Part I](https://our.status.im/nim-libp2p-tutorial-a-peer-to-peer-chat-example-1/): Set up the main function and use multi-thread for processing IO. -- [Part II](https://our.status.im/nim-libp2p-tutorial-a-peer-to-peer-chat-example-2/): Dial remote peer and allow customized user input commands. -- [Part III](https://our.status.im/nim-libp2p-tutorial-a-peer-to-peer-chat-example-3/): Configure and establish a libp2p node. +| Name | Description | +| ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | +| **Libp2p** | | +| [libp2p](libp2p/switch.nim) | The core of the project | +| [connmanager](libp2p/connmanager.nim) | Connection manager | +| [identify / push identify](libp2p/protocols/identify.nim) | [Identify](https://docs.libp2p.io/concepts/protocols/#identify) protocol | +| [ping](libp2p/protocols/ping.nim) | [Ping](https://docs.libp2p.io/concepts/protocols/#ping) protocol | +| [libp2p-daemon-client](libp2p/daemon/daemonapi.nim) | [go-daemon](https://github.com/libp2p/go-libp2p-daemon) nim wrapper | +| [interop-libp2p](tests/testinterop.nim) | Interop tests | +| **Transports** | | +| [libp2p-tcp](libp2p/transports/tcptransport.nim) | TCP transport | +| [libp2p-ws](libp2p/transports/wstransport.nim) | WebSocket & WebSocket Secure transport | +| **Secure Channels** | | +| [libp2p-secio](libp2p/protocols/secure/secio.nim) | [Secio](https://docs.libp2p.io/concepts/protocols/#secio) secure channel | +| [libp2p-noise](libp2p/protocols/secure/noise.nim) | [Noise](https://github.com/libp2p/specs/tree/master/noise) secure channel | +| [libp2p-plaintext](libp2p/protocols/secure/plaintext.nim) | [Plain Text](https://github.com/libp2p/specs/tree/master/plaintext) for development purposes | +| **Stream Multiplexers** | | +| [libp2p-mplex](libp2p/muxers/mplex/mplex.nim) | [MPlex](https://github.com/libp2p/specs/tree/master/mplex) multiplexer | +| **Data Types** | | +| [peer-id](libp2p/peerid.nim) | [Cryptographic identifiers](https://docs.libp2p.io/concepts/peer-id/) | +| [peer-store](libp2p/peerstore.nim) | ["Phone book" of known peers](https://docs.libp2p.io/concepts/peer-id/#peerinfo) | +| [multiaddress](libp2p/multiaddress.nim) | [Composable network addresses](https://github.com/multiformats/multiaddr) | +| [signed envelope](libp2p/signed_envelope.nim) | [Signed generic data container](https://github.com/libp2p/specs/blob/master/RFC/0002-signed-envelopes.md) | +| [routing record](libp2p/routing_record.nim) | [Signed peer dialing informations](https://github.com/libp2p/specs/blob/master/RFC/0003-routing-records.md) | +| **Utilities** | | +| [libp2p-crypto](libp2p/crypto) | Cryptographic backend | +| [libp2p-crypto-secp256k1](libp2p/crypto/secp.nim) | | +| **Pubsub** | | +| [libp2p-pubsub](libp2p/protocols/pubsub/pubsub.nim) | Pub-Sub generic interface | +| [libp2p-floodsub](libp2p/protocols/pubsub/floodsub.nim) | FloodSub implementation | +| [libp2p-gossipsub](libp2p/protocols/pubsub/gossipsub.nim) | [GossipSub](https://docs.libp2p.io/concepts/publish-subscribe/) implementation | +## Users -### Using the Go Daemon -Please find the installation and usage intructions in [daemonapi.md](docs/api/libp2p/daemonapi.md). - -Examples can be found in the [examples/go-daemon folder](https://github.com/status-im/nim-libp2p/tree/readme/examples/go-daemon); +nim-libp2p is used by: +- [Nimbus](https://github.com/status-im/nimbus-eth2), an Ethereum client +- [nwaku](https://github.com/status-im/nwaku), a decentralized messaging application +- [nim-codex](https://github.com/status-im/nim-codex), a decentralized storage application +- (open a pull request if you want to be included here) ## Development **Clone and Install dependencies:** @@ -90,96 +106,45 @@ git clone https://github.com/status-im/nim-libp2p cd nim-libp2p nimble install ``` -#### Run unit tests + +**Run unit tests** ```sh # run all the unit tests nimble test ``` -The code follows the [Status Nim Style Guide](https://status-im.github.io/nim-style-guide/). -### Packages - -List of packages currently in existence for nim-libp2p: - -#### Libp2p -- [libp2p](https://github.com/status-im/nim-libp2p) -- [libp2p-daemon-client](https://github.com/status-im/nim-libp2p/blob/master/libp2p/daemon/daemonapi.nim) -- [interop-libp2p](https://github.com/status-im/nim-libp2p/blob/master/tests/testinterop.nim) - -#### Transports -- [libp2p-tcp](https://github.com/status-im/nim-libp2p/blob/master/libp2p/transports/tcptransport.nim) -- [libp2p-ws](https://github.com/status-im/nim-libp2p/blob/master/libp2p/transports/wstransport.nim) - -#### Secure Channels -- [libp2p-secio](https://github.com/status-im/nim-libp2p/blob/master/libp2p/protocols/secure/secio.nim) -- [libp2p-noise](https://github.com/status-im/nim-libp2p/blob/master/libp2p/protocols/secure/noise.nim) -- [libp2p-plaintext](https://github.com/status-im/nim-libp2p/blob/master/libp2p/protocols/secure/plaintext.nim) - -#### Stream Multiplexers -- [libp2p-mplex](https://github.com/status-im/nim-libp2p/blob/master/libp2p/muxers/mplex/mplex.nim) - -#### Utilities -- [libp2p-crypto](https://github.com/status-im/nim-libp2p/tree/master/libp2p/crypto) -- [libp2p-crypto-secp256k1](https://github.com/status-im/nim-libp2p/blob/master/libp2p/crypto/secp.nim) - -#### Data Types -- [peer-id](https://github.com/status-im/nim-libp2p/blob/master/libp2p/peer.nim) -- [peer-info](https://github.com/status-im/nim-libp2p/blob/master/libp2p/peerinfo.nim) - -#### Pubsub -- [libp2p-pubsub](https://github.com/status-im/nim-libp2p/blob/master/libp2p/protocols/pubsub/pubsub.nim) -- [libp2p-floodsub](https://github.com/status-im/nim-libp2p/blob/master/libp2p/protocols/pubsub/floodsub.nim) -- [libp2p-gossipsub](https://github.com/status-im/nim-libp2p/blob/master/libp2p/protocols/pubsub/gossipsub.nim) - - -Packages that exist in the original libp2p specs and are under active development: -- libp2p-daemon -- libp2p-webrtc-direct -- libp2p-webrtc-star -- libp2p-spdy -- libp2p-bootstrap -- libp2p-kad-dht -- libp2p-mdns -- libp2p-webrtc-star -- libp2p-delegated-content-routing -- libp2p-delegated-peer-routing -- libp2p-nat-mgnr -- libp2p-utils - -** Note that the current stack reflects the minimal requirements for the upcoming Eth2 implementation. - -### Tips and tricks - -#### enable expensive metrics: - -```bash -nim c -d:libp2p_expensive_metrics some_file.nim -``` - -#### use identify metrics - -```bash -nim c -d:libp2p_agents_metrics -d:KnownLibP2PAgents=nimbus,lighthouse,prysm,teku some_file.nim -``` - -### specify gossipsub specific topics to measure - -```bash -nim c -d:KnownLibP2PTopics=topic1,topic2,topic3 some_file.nim -``` - -## Contribute +### Contribute The libp2p implementation in Nim is a work in progress. We welcome contributors to help out! Specifically, you can: - Go through the modules and **check out existing issues**. This would be especially useful for modules in active development. Some knowledge of IPFS/libp2p may be required, as well as the infrastructure behind it. - **Perform code reviews**. Feel free to let us know if you found anything that can a) speed up the project development b) ensure better quality and c) reduce possible future bugs. -- **Add tests**. Help nim-libp2p to be more robust by adding more tests to the [tests folder](https://github.com/status-im/nim-libp2p/tree/master/tests). +- **Add tests**. Help nim-libp2p to be more robust by adding more tests to the [tests folder](tests/). The code follows the [Status Nim Style Guide](https://status-im.github.io/nim-style-guide/). ### Core Developers [@cheatfate](https://github.com/cheatfate), [Dmitriy Ryajov](https://github.com/dryajov), [Tanguy](https://github.com/Menduist), [Zahary Karadjov](https://github.com/zah) +### Tips and tricks + +**enable expensive metrics:** + +```bash +nim c -d:libp2p_expensive_metrics some_file.nim +``` + +**use identify metrics** + +```bash +nim c -d:libp2p_agents_metrics -d:KnownLibP2PAgents=nimbus,lighthouse,prysm,teku some_file.nim +``` + +**specify gossipsub specific topics to measure** + +```bash +nim c -d:KnownLibP2PTopics=topic1,topic2,topic3 some_file.nim +``` + ## License Licensed and distributed under either of @@ -191,4 +156,3 @@ or * Apache License, Version 2.0, ([LICENSE-APACHEv2](LICENSE-APACHEv2) or http://www.apache.org/licenses/LICENSE-2.0) at your option. These files may not be copied, modified, or distributed except according to those terms. - diff --git a/vendor/nim-libp2p/config.nims b/vendor/nim-libp2p/config.nims index d26e195ff..da72649d4 100644 --- a/vendor/nim-libp2p/config.nims +++ b/vendor/nim-libp2p/config.nims @@ -2,5 +2,22 @@ if dirExists("nimbledeps/pkgs"): switch("NimblePath", "nimbledeps/pkgs") -when (NimMajor, NimMinor) > (1, 2): - switch("hint", "XCannotRaiseY:off") \ No newline at end of file +switch("warning", "CaseTransition:off") +switch("warning", "ObservableStores:off") +switch("warning", "LockLevel:off") +--define:chronosStrictException +--styleCheck:usages +if (NimMajor, NimMinor) < (1, 6): + --styleCheck:hint +else: + --styleCheck:error + +# Avoid some rare stack corruption while using exceptions with a SEH-enabled +# toolchain: https://github.com/status-im/nimbus-eth2/issues/3121 +if defined(windows) and not defined(vcc): + --define:nimRawSetjmp + +# begin Nimble config (version 1) +when fileExists("nimble.paths"): + include "nimble.paths" +# end Nimble config diff --git a/vendor/nim-libp2p/docs/API.md b/vendor/nim-libp2p/docs/API.md deleted file mode 100644 index 3af9f1c0e..000000000 --- a/vendor/nim-libp2p/docs/API.md +++ /dev/null @@ -1,3 +0,0 @@ -# API - -Coming Soon... \ No newline at end of file diff --git a/vendor/nim-libp2p/docs/GETTING_STARTED.md b/vendor/nim-libp2p/docs/GETTING_STARTED.md deleted file mode 100644 index a0cb72a1a..000000000 --- a/vendor/nim-libp2p/docs/GETTING_STARTED.md +++ /dev/null @@ -1,7 +0,0 @@ -# Getting Started -Welcome to nim-libp2p! - - -To get started, please look at the [tutorials](../examples/tutorial_1_connect.md) - -For more concrete examples, you can look at the [hello world example](../examples/helloworld.nim) or the [direct chat](../examples/directchat.nim) diff --git a/vendor/nim-libp2p/docs/README.md b/vendor/nim-libp2p/docs/README.md deleted file mode 100644 index f6a82fbd2..000000000 --- a/vendor/nim-libp2p/docs/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# Introduction -This folder contains the documentation for each nim-libp2p module and the sample code for the tutorials. - -# Table of Contents -### [Getting Started](GETTING_STARTED.md) -### Tutorials -- P2P Chat Example - - [part I](tutorial/directchat/start.nim) - - [part II](tutorial/directchat/second.nim) -### API Specifications -- libp2p - - [libp2p-daemon-client](api/libp2p/daemonapi.md) - - [interop-libp2p](api/libp2p/interop.md) -- transports - - [libp2p-tcp](api/transports/tcptransport.md) -- secure channels - - [libp2p-secio](api/secure_channels/secio.md) -- stream multiplexers - - [libp2p-mplex](api/stream_multiplexers/mplex.md) -- utilities - - [libp2p-crypto](api/utilities/crypto.md) - - [libp2p-crypto-secp256k1](api/utilities/secp256k1.md) -- data types - - [peer-id](api/data_types/peer.md) - - [peer-info](api/data_types/peerinfo.md) -- pubsub - - [libp2p-pubsub](api/pubsub/pubsub.md) - - [libp2p-floodsub](api/pubsub/floodsub.md) - - [libp2p-gossipsub](api/pubsub/gossipsub.md) \ No newline at end of file diff --git a/vendor/nim-libp2p/docs/api/data_types/peer.md b/vendor/nim-libp2p/docs/api/data_types/peer.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/nim-libp2p/docs/api/data_types/peerinfo.md b/vendor/nim-libp2p/docs/api/data_types/peerinfo.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/nim-libp2p/docs/api/libp2p/interop.md b/vendor/nim-libp2p/docs/api/libp2p/interop.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/nim-libp2p/docs/api/pubsub/floodsub.md b/vendor/nim-libp2p/docs/api/pubsub/floodsub.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/nim-libp2p/docs/api/pubsub/gossipsub.md b/vendor/nim-libp2p/docs/api/pubsub/gossipsub.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/nim-libp2p/docs/api/pubsub/pubsub.md b/vendor/nim-libp2p/docs/api/pubsub/pubsub.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/nim-libp2p/docs/api/secure_channels/secio.md b/vendor/nim-libp2p/docs/api/secure_channels/secio.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/nim-libp2p/docs/api/stream_multiplexers/mplex.md b/vendor/nim-libp2p/docs/api/stream_multiplexers/mplex.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/nim-libp2p/docs/api/transports/tcptransport.md b/vendor/nim-libp2p/docs/api/transports/tcptransport.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/nim-libp2p/docs/api/utilities/crypto.md b/vendor/nim-libp2p/docs/api/utilities/crypto.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/nim-libp2p/docs/api/utilities/secp256k1.md b/vendor/nim-libp2p/docs/api/utilities/secp256k1.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/nim-libp2p/docs/tutorial/directchat/second.nim b/vendor/nim-libp2p/docs/tutorial/directchat/second.nim deleted file mode 100644 index 2c7b1a3a2..000000000 --- a/vendor/nim-libp2p/docs/tutorial/directchat/second.nim +++ /dev/null @@ -1,149 +0,0 @@ -when not(compileOption("threads")): - {.fatal: "Please, compile this program with the --threads:on option!".} - -import tables, strformat, strutils -import chronos -import ../libp2p/[switch, - multistream, - crypto/crypto, - protocols/identify, - connection, - transports/transport, - transports/tcptransport, - multiaddress, - peerinfo, - peerid, - protocols/protocol, - protocols/secure/secure, - protocols/secure/secio, - muxers/muxer, - muxers/mplex/mplex] - -const ChatCodec = "/nim-libp2p/chat/1.0.0" -const DefaultAddr = "/ip4/127.0.0.1/tcp/55505" - -const Help = """ - Commands: /[?|hep|connect|disconnect|exit] - help: Prints this help - connect: dials a remote peer - disconnect: ends current session - exit: closes the chat -""" - -type ChatProto = ref object of LPProtocol - switch: Switch # a single entry point for dialing and listening to peer - transp: StreamTransport # transport streams between read & write file descriptor - conn: Connection # create and close read & write stream - connected: bool # if the node is connected to another peer - started: bool # if the node has started - -# copied from https://github.com/status-im/nimbus-eth2/blob/0ed657e953740a92458f23033d47483ffa17ccb0/beacon_chain/eth2_network.nim#L109-L115 -proc initAddress(T: type MultiAddress, str: string): T = - let address = MultiAddress.init(str) - if IPFS.match(address) and matchPartial(multiaddress.TCP, address): - result = address - else: - raise newException(MultiAddressError, - "Invalid bootstrap node multi-address") - -proc dialPeer(p: ChatProto, address: string) {.async.} = - let multiAddr = MultiAddress.initAddress(address); - let parts = address.split("/") - let remotePeer = PeerInfo.init(parts[^1], - [multiAddr]) - - echo &"dialing peer: {multiAddr}" - p.conn = await p.switch.dial(remotePeer, ChatCodec) - p.connected = true - -proc readAndPrint(p: ChatProto) {.async.} = - while true: - while p.connected: - echo cast[string](await p.conn.readLp(1024)) - await sleepAsync(100.millis) - -proc writeAndPrint(p: ChatProto) {.async.} = - while true: - if not p.connected: - echo "type an address or wait for a connection:" - echo "type /[help|?] for help" - - let line = await p.transp.readLine() - if line.startsWith("/help") or line.startsWith("/?") or not p.started: - echo Help - continue - - if line.startsWith("/disconnect"): - echo "Ending current session" - if p.connected and p.conn.closed.not: - await p.conn.close() - p.connected = false - elif line.startsWith("/connect"): - if p.connected: - var yesno = "N" - echo "a session is already in progress, do you want end it [y/N]?" - yesno = await p.transp.readLine() - if yesno.cmpIgnoreCase("y") == 0: - await p.conn.close() - p.connected = false - elif yesno.cmpIgnoreCase("n") == 0: - continue - else: - echo "unrecognized response" - continue - - echo "enter address of remote peer" - let address = await p.transp.readLine() - if address.len > 0: - await p.dialPeer(address) - - elif line.startsWith("/exit"): - if p.connected and p.conn.closed.not: - await p.conn.close() - p.connected = false - - await p.switch.stop() - echo "quitting..." - quit(0) - else: - if p.connected: - await p.conn.writeLp(line) - else: - try: - if line.startsWith("/") and "ipfs" in line: - await p.dialPeer(line) - except: - echo &"unable to dial remote peer {line}" - echo getCurrentExceptionMsg() - -proc readWriteLoop(p: ChatProto) {.async.} = - asyncSpawn p.writeAndPrint() # execute the async function but does not block - asyncSpawn p.readAndPrint() - -proc processInput(rfd: AsyncFD) {.async.} = - let transp = fromPipe(rfd) - while true: - let a = await transp.readLine() - echo "You just entered: " & a - -proc readInput(wfd: AsyncFD) {.thread.} = - ## This procedure performs reading from `stdin` and sends data over - ## pipe to main thread. - let transp = fromPipe(wfd) - - while true: - let line = stdin.readLine() - discard waitFor transp.write(line & "\r\n") - -proc main() {.async.} = - let (rfd, wfd) = createAsyncPipe() - if rfd == asyncInvalidPipe or wfd == asyncInvalidPipe: - raise newException(ValueError, "Could not initialize pipe!") - - var thread: Thread[AsyncFD] - thread.createThread(readInput, wfd) - - await processInput(rfd) - -when isMainModule: # isMainModule = true when the module is compiled as the main file - waitFor(main()) diff --git a/vendor/nim-libp2p/docs/tutorial/directchat/start.nim b/vendor/nim-libp2p/docs/tutorial/directchat/start.nim deleted file mode 100644 index 7e7b8326f..000000000 --- a/vendor/nim-libp2p/docs/tutorial/directchat/start.nim +++ /dev/null @@ -1,39 +0,0 @@ -when not(compileOption("threads")): - {.fatal: "Please, compile this program with the --threads:on option!".} - -import chronos # an efficient library for async - -proc processInput(rfd: AsyncFD) {.async.} = - echo "Type something below to see if the multithread IO works:\nType 'exit' to exit." - - let transp = fromPipe(rfd) - while true: - let a = await transp.readLine() - - if a == "exit": - quit(0); - - echo "You just entered: " & a - -proc readInput(wfd: AsyncFD) {.thread.} = - ## This procedure performs reading from `stdin` and sends data over - ## pipe to main thread. - let transp = fromPipe(wfd) - - while true: - let line = stdin.readLine() - discard waitFor transp.write(line & "\r\n") - -proc main() {.async.} = - let (rfd, wfd) = createAsyncPipe() - if rfd == asyncInvalidPipe or wfd == asyncInvalidPipe: - raise newException(ValueError, "Could not initialize pipe!") - - var thread: Thread[AsyncFD] - thread.createThread(readInput, wfd) - - await processInput(rfd) - -when isMainModule: # isMainModule = true when the module is compiled as the main file - waitFor(main()) - \ No newline at end of file diff --git a/vendor/nim-libp2p/docs/tutorial/second.nim b/vendor/nim-libp2p/docs/tutorial/second.nim deleted file mode 100644 index 8db26392f..000000000 --- a/vendor/nim-libp2p/docs/tutorial/second.nim +++ /dev/null @@ -1,205 +0,0 @@ -when not(compileOption("threads")): - {.fatal: "Please, compile this program with the --threads:on option!".} - -import tables, strformat, strutils, bearssl -import chronos # an efficient library for async -import ../libp2p/[switch, # manage transports, a single entry point for dialing and listening - builders, # helper to build the switch object - multistream, # tag stream with short header to identify it - multicodec, # multicodec utilities - crypto/crypto, # cryptographic functions - errors, # error handling utilities - protocols/identify, # identify the peer info of a peer - stream/connection, # create and close stream read / write connections - transports/transport, # listen and dial to other peers using p2p protocol - transports/tcptransport, # listen and dial to other peers using client-server protocol - multiaddress, # encode different addressing schemes. For example, /ip4/7.7.7.7/tcp/6543 means it is using IPv4 protocol and TCP - peerinfo, # manage the information of a peer, such as peer ID and public / private key - peerid, # Implement how peers interact - protocols/protocol, # define the protocol base type - protocols/secure/secure, # define the protocol of secure connection - protocols/secure/secio, # define the protocol of secure input / output, allows encrypted communication that uses public keys to validate signed messages instead of a certificate authority like in TLS - muxers/muxer, # define an interface for stream multiplexing, allowing peers to offer many protocols over a single connection - muxers/mplex/mplex] # define some contants and message types for stream multiplexing - -const ChatCodec = "/nim-libp2p/chat/1.0.0" -const DefaultAddr = "/ip4/127.0.0.1/tcp/55505" - -const Help = """ - Commands: /[?|hep|connect|disconnect|exit] - help: Prints this help - connect: dials a remote peer - disconnect: ends current session - exit: closes the chat -""" - -type ChatProto = ref object of LPProtocol - switch: Switch # a single entry point for dialing and listening to peer - transp: StreamTransport # transport streams between read & write file descriptor - conn: Connection # create and close read & write stream - connected: bool # if the node is connected to another peer - started: bool # if the node has started - -proc readAndPrint(p: ChatProto) {.async.} = - while true: - var strData = await p.conn.readLp(1024) - strData &= '\0'.uint8 - var str = cast[cstring](addr strdata[0]) - echo $p.switch.peerInfo.peerId & ": " & $str - await sleepAsync(100.millis) - -proc dialPeer(p: ChatProto, address: string) {.async.} = - let - multiAddr = MultiAddress.init(address).tryGet() - # split the peerId part /p2p/... - peerIdBytes = multiAddr[multiCodec("p2p")] - .tryGet() - .protoAddress() - .tryGet() - remotePeer = PeerId.init(peerIdBytes).tryGet() - # split the wire address - ip4Addr = multiAddr[multiCodec("ip4")].tryGet() - tcpAddr = multiAddr[multiCodec("tcp")].tryGet() - wireAddr = ip4Addr & tcpAddr - - echo &"dialing peer: {multiAddr}" - p.conn = await p.switch.dial(remotePeer, @[wireAddr], ChatCodec) - p.connected = true - asyncSpawn p.readAndPrint() - -proc writeAndPrint(p: ChatProto) {.async.} = - while true: - if not p.connected: - echo "type an address or wait for a connection:" - echo "type /[help|?] for help" - - let line = await p.transp.readLine() - if line.startsWith("/help") or line.startsWith("/?") or not p.started: - echo Help - continue - - if line.startsWith("/disconnect"): - echo "Ending current session" - if p.connected and p.conn.closed.not: - await p.conn.close() - p.connected = false - elif line.startsWith("/connect"): - if p.connected: - var yesno = "N" - echo "a session is already in progress, do you want end it [y/N]?" - yesno = await p.transp.readLine() - if yesno.cmpIgnoreCase("y") == 0: - await p.conn.close() - p.connected = false - elif yesno.cmpIgnoreCase("n") == 0: - continue - else: - echo "unrecognized response" - continue - - echo "enter address of remote peer" - let address = await p.transp.readLine() - if address.len > 0: - await p.dialPeer(address) - - elif line.startsWith("/exit"): - if p.connected and p.conn.closed.not: - await p.conn.close() - p.connected = false - - await p.switch.stop() - echo "quitting..." - quit(0) - else: - if p.connected: - await p.conn.writeLp(line) - else: - try: - if line.startsWith("/") and "p2p" in line: - await p.dialPeer(line) - except: - echo &"unable to dial remote peer {line}" - echo getCurrentExceptionMsg() - -proc readWriteLoop(p: ChatProto) {.async.} = - await p.writeAndPrint() - -proc newChatProto(switch: Switch, transp: StreamTransport): ChatProto = - var chatproto = ChatProto(switch: switch, transp: transp, codecs: @[ChatCodec]) - - # create handler for incoming connection - proc handle(stream: Connection, proto: string) {.async.} = - if chatproto.connected and not chatproto.conn.closed: - echo "a chat session is already in progress - disconnecting!" - await stream.close() - else: - chatproto.conn = stream - chatproto.connected = true - await chatproto.readAndPrint() - - # assign the new handler - chatproto.handler = handle - return chatproto - -proc readInput(wfd: AsyncFD) {.thread.} = - ## This procedure performs reading from `stdin` and sends data over - ## pipe to main thread. - let transp = fromPipe(wfd) - - while true: - let line = stdin.readLine() - discard waitFor transp.write(line & "\r\n") - -proc processInput(rfd: AsyncFD, rng: ref BrHmacDrbgContext) {.async.} = - let transp = fromPipe(rfd) - - let seckey = PrivateKey.random(RSA, rng[]).get() - var localAddress = DefaultAddr - while true: - echo &"Type an address to bind to or Enter to use the default {DefaultAddr}" - let a = await transp.readLine() - try: - if a.len > 0: - localAddress = a - break - # uise default - break - except: - echo "invalid address" - localAddress = DefaultAddr - continue - - var switch = SwitchBuilder - .init() - .withRng(rng) - .withPrivateKey(seckey) - .withAddress(MultiAddress.init(localAddress).tryGet()) - .build() - - let chatProto = newChatProto(switch, transp) - switch.mount(chatProto) - let libp2pFuts = await switch.start() - chatProto.started = true - - let id = $switch.peerInfo.peerId - echo "PeerId: " & id - echo "listening on: " - for a in switch.peerInfo.addrs: - echo &"{a}/p2p/{id}" - - await chatProto.readWriteLoop() - await allFuturesThrowing(libp2pFuts) - -proc main() {.async.} = - let rng = newRng() # Singe random number source for the whole application - let (rfd, wfd) = createAsyncPipe() - if rfd == asyncInvalidPipe or wfd == asyncInvalidPipe: - raise newException(ValueError, "Could not initialize pipe!") - - var thread: Thread[AsyncFD] - thread.createThread(readInput, wfd) - - await processInput(rfd, rng) - -when isMainModule: # isMainModule = true when the module is compiled as the main file - waitFor(main()) diff --git a/vendor/nim-libp2p/docs/tutorial/start.nim b/vendor/nim-libp2p/docs/tutorial/start.nim deleted file mode 100644 index 7e7b8326f..000000000 --- a/vendor/nim-libp2p/docs/tutorial/start.nim +++ /dev/null @@ -1,39 +0,0 @@ -when not(compileOption("threads")): - {.fatal: "Please, compile this program with the --threads:on option!".} - -import chronos # an efficient library for async - -proc processInput(rfd: AsyncFD) {.async.} = - echo "Type something below to see if the multithread IO works:\nType 'exit' to exit." - - let transp = fromPipe(rfd) - while true: - let a = await transp.readLine() - - if a == "exit": - quit(0); - - echo "You just entered: " & a - -proc readInput(wfd: AsyncFD) {.thread.} = - ## This procedure performs reading from `stdin` and sends data over - ## pipe to main thread. - let transp = fromPipe(wfd) - - while true: - let line = stdin.readLine() - discard waitFor transp.write(line & "\r\n") - -proc main() {.async.} = - let (rfd, wfd) = createAsyncPipe() - if rfd == asyncInvalidPipe or wfd == asyncInvalidPipe: - raise newException(ValueError, "Could not initialize pipe!") - - var thread: Thread[AsyncFD] - thread.createThread(readInput, wfd) - - await processInput(rfd) - -when isMainModule: # isMainModule = true when the module is compiled as the main file - waitFor(main()) - \ No newline at end of file diff --git a/vendor/nim-libp2p/examples/README.md b/vendor/nim-libp2p/examples/README.md new file mode 100644 index 000000000..18b6ca855 --- /dev/null +++ b/vendor/nim-libp2p/examples/README.md @@ -0,0 +1,6 @@ +# nim-libp2p documentation + +Welcome to the nim-libp2p documentation! + +Here, you'll find [tutorials](tutorial_1_connect.md) to help you get started, as well as [examples](directchat.nim) and +the [full reference](https://status-im.github.io/nim-libp2p/master/libp2p.html). diff --git a/vendor/nim-libp2p/examples/circuitrelay.nim b/vendor/nim-libp2p/examples/circuitrelay.nim new file mode 100644 index 000000000..290c47399 --- /dev/null +++ b/vendor/nim-libp2p/examples/circuitrelay.nim @@ -0,0 +1,76 @@ +import chronos, stew/byteutils +import ../libp2p, + ../libp2p/protocols/relay/[relay, client] + +# Helper to create a circuit relay node +proc createCircuitRelaySwitch(r: Relay): Switch = + SwitchBuilder.new() + .withRng(newRng()) + .withAddresses(@[ MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() ]) + .withTcpTransport() + .withMplex() + .withNoise() + .withCircuitRelay(r) + .build() + +proc main() {.async.} = + # Create a custom protocol + let customProtoCodec = "/test" + var proto = new LPProtocol + proto.codec = customProtoCodec + proto.handler = proc(conn: Connection, proto: string) {.async.} = + var msg = string.fromBytes(await conn.readLp(1024)) + echo "1 - Dst Received: ", msg + assert "test1" == msg + await conn.writeLp("test2") + msg = string.fromBytes(await conn.readLp(1024)) + echo "2 - Dst Received: ", msg + assert "test3" == msg + await conn.writeLp("test4") + + let + relay = Relay.new() + clSrc = RelayClient.new() + clDst = RelayClient.new() + + # Create three hosts, enable relay client on two of them. + # The third one can relay connections for other peers. + # RelayClient can use a relay, Relay is a relay. + swRel = createCircuitRelaySwitch(relay) + swSrc = createCircuitRelaySwitch(clSrc) + swDst = createCircuitRelaySwitch(clDst) + + # Create a relay address to swDst using swRel as the relay + addrs = MultiAddress.init($swRel.peerInfo.addrs[0] & "/p2p/" & + $swRel.peerInfo.peerId & "/p2p-circuit/p2p/" & + $swDst.peerInfo.peerId).get() + + swDst.mount(proto) + + await swRel.start() + await swSrc.start() + await swDst.start() + + # Connect both Src and Dst to the relay, but not to each other. + await swSrc.connect(swRel.peerInfo.peerId, swRel.peerInfo.addrs) + await swDst.connect(swRel.peerInfo.peerId, swRel.peerInfo.addrs) + + # Dst reserve a slot on the relay. + let rsvp = await clDst.reserve(swRel.peerInfo.peerId, swRel.peerInfo.addrs) + + # Src dial Dst using the relay + let conn = await swSrc.dial(swDst.peerInfo.peerId, @[ addrs ], customProtoCodec) + + await conn.writeLp("test1") + var msg = string.fromBytes(await conn.readLp(1024)) + echo "1 - Src Received: ", msg + assert "test2" == msg + await conn.writeLp("test3") + msg = string.fromBytes(await conn.readLp(1024)) + echo "2 - Src Received: ", msg + assert "test4" == msg + + await relay.stop() + await allFutures(swSrc.stop(), swDst.stop(), swRel.stop()) + +waitFor(main()) diff --git a/vendor/nim-libp2p/examples/directchat.nim b/vendor/nim-libp2p/examples/directchat.nim index 121f03142..9e7d99ce1 100644 --- a/vendor/nim-libp2p/examples/directchat.nim +++ b/vendor/nim-libp2p/examples/directchat.nim @@ -2,7 +2,7 @@ when not(compileOption("threads")): {.fatal: "Please, compile this program with the --threads:on option!".} import - strformat, strutils, bearssl, + strformat, strutils, stew/byteutils, chronos, ../libp2p diff --git a/vendor/nim-libp2p/docs/api/libp2p/daemonapi.md b/vendor/nim-libp2p/examples/go-daemon/daemonapi.md similarity index 100% rename from vendor/nim-libp2p/docs/api/libp2p/daemonapi.md rename to vendor/nim-libp2p/examples/go-daemon/daemonapi.md diff --git a/vendor/nim-libp2p/examples/helloworld.nim b/vendor/nim-libp2p/examples/helloworld.nim index 1bec3e3a9..9f5f1cbe7 100644 --- a/vendor/nim-libp2p/examples/helloworld.nim +++ b/vendor/nim-libp2p/examples/helloworld.nim @@ -1,4 +1,3 @@ -import bearssl import chronos # an efficient library for async import stew/byteutils # various utils import ../libp2p # when installed through nimble, just use `import libp2p` @@ -26,7 +25,7 @@ proc new(T: typedesc[TestProto]): T = ## # Helper to create a switch/node ## -proc createSwitch(ma: MultiAddress, rng: ref BrHmacDrbgContext): Switch = +proc createSwitch(ma: MultiAddress, rng: ref HmacDrbgContext): Switch = var switch = SwitchBuilder .new() .withRng(rng) # Give the application RNG diff --git a/vendor/nim-libp2p/examples/tutorial_1_connect.md b/vendor/nim-libp2p/examples/tutorial_1_connect.md index 03a488925..0dd6543d6 100644 --- a/vendor/nim-libp2p/examples/tutorial_1_connect.md +++ b/vendor/nim-libp2p/examples/tutorial_1_connect.md @@ -1,15 +1,18 @@ -Hi all, welcome to the first article of the nim-libp2p's tutorial series! +# Simple ping tutorial -_This tutorial is for everyone who is interested in building peer-to-peer chatting applications. No Nim programming experience is needed._ +Hi all, welcome to the first nim-libp2p tutorial! + +!!! tips "" + This tutorial is for everyone who is interested in building peer-to-peer applications. No Nim programming experience is needed. To give you a quick overview, **Nim** is the programming language we are using and **nim-libp2p** is the Nim implementation of [libp2p](https://libp2p.io/), a modular library that enables the development of peer-to-peer network applications. Hope you'll find it helpful in your journey of learning. Happy coding! ;) -# Before you start +## Before you start The only prerequisite here is [Nim](https://nim-lang.org/), the programming language with a Python-like syntax and a performance similar to C. Detailed information can be found [here](https://nim-lang.org/docs/tut1.html). -Install Nim via their official website: [https://nim-lang.org/install.html](https://nim-lang.org/install.html) +Install Nim via their [official website](https://nim-lang.org/install.html). Check Nim's installation via `nim --version` and its package manager Nimble via `nimble --version`. You can now install the latest version of `nim-libp2p`: @@ -17,25 +20,24 @@ You can now install the latest version of `nim-libp2p`: nimble install libp2p@#master ``` -# A simple ping application +## A simple ping application We'll start by creating a simple application, which is starting two libp2p [switch](https://docs.libp2p.io/concepts/stream-multiplexing/#switch-swarm), and pinging each other using the [Ping](https://docs.libp2p.io/concepts/protocols/#ping) protocol. -_TIP: You can extract the code from this tutorial by running `nim c -r tools/markdown_runner.nim examples/tutorial_1_connect.md` in the libp2p folder!_ +!!! tips "" + You can extract the code from this tutorial by running `nim c -r tools/markdown_runner.nim examples/tutorial_1_connect.md` in the libp2p folder! Let's create a `part1.nim`, and import our dependencies: ```nim -import bearssl import chronos import libp2p import libp2p/protocols/ping ``` -[bearssl](https://github.com/status-im/nim-bearssl) is used as a [cryptographic pseudorandom number generator](https://en.wikipedia.org/wiki/Cryptographically-secure_pseudorandom_number_generator) [chronos](https://github.com/status-im/nim-chronos) the asynchronous framework used by `nim-libp2p` Next, we'll create an helper procedure to create our switches. A switch needs a bit of configuration, and it will be easier to do this configuration only once: ```nim -proc createSwitch(ma: MultiAddress, rng: ref BrHmacDrbgContext): Switch = +proc createSwitch(ma: MultiAddress, rng: ref HmacDrbgContext): Switch = var switch = SwitchBuilder .new() .withRng(rng) # Give the application RNG @@ -60,17 +62,17 @@ proc main() {.async, gcsafe.} = localAddress = MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() pingProtocol = Ping.new(rng=rng) ``` -We created some variables that we'll need for the rest of the application: the global `rng` instance, our `localAddress`, and an instance of the `Ping` protocol. +We created some variables that we'll need for the rest of the application: the global `rng` instance, our `localAddress`, and an instance of the `Ping` protocol. The address is in the [MultiAddress](https://github.com/multiformats/multiaddr) format. The port `0` means "take any port available". -`tryGet` is procedure which is part of the [nim-result](https://github.com/arnetheduck/nim-result/), that will throw an exception if the supplied MultiAddress is not valid. +`tryGet` is procedure which is part of [nim-result](https://github.com/arnetheduck/nim-result/), that will throw an exception if the supplied MultiAddress is invalid. We can now create our two switches: ```nim let switch1 = createSwitch(localAddress, rng) switch2 = createSwitch(localAddress, rng) - + switch1.mount(pingProtocol) await switch1.start() @@ -78,7 +80,7 @@ We can now create our two switches: ``` We've **mounted** the `pingProtocol` on our first switch. This means that the first switch will actually listen for any ping requests coming in, and handle them accordingly. -Now that we've started the nodes, they are listening for incoming peers. +Now that we've started the nodes, they are listening for incoming peers. We can find out which port was attributed, and the resulting local addresses, by using `switch1.peerInfo.addrs`. We'll **dial** the first switch from the second one, by specifying it's **Peer ID**, it's **MultiAddress** and the **`Ping` protocol codec**: @@ -97,7 +99,7 @@ We now have a `Ping` connection setup between the second and the first switch, w And that's it! Just a little bit of cleanup: shutting down the switches, waiting for them to stop, and we'll call our `main` procedure: ```nim await allFutures(switch1.stop(), switch2.stop()) # close connections and shutdown all transports - + waitFor(main()) ``` diff --git a/vendor/nim-libp2p/examples/tutorial_2_customproto.md b/vendor/nim-libp2p/examples/tutorial_2_customproto.md index 9fc6116e4..aa3366c8b 100644 --- a/vendor/nim-libp2p/examples/tutorial_2_customproto.md +++ b/vendor/nim-libp2p/examples/tutorial_2_customproto.md @@ -1,11 +1,11 @@ +# Custom protocol in libp2p + In the [previous tutorial](tutorial_1_connect.md), we've looked at how to create a simple ping program using the `nim-libp2p`. We'll now look at how to create a custom protocol inside the libp2p -# Custom protocol in libp2p Let's create a `part2.nim`, and import our dependencies: ```nim -import bearssl import chronos import stew/byteutils @@ -22,7 +22,7 @@ type TestProto = ref object of LPProtocol We've set a [protocol ID](https://docs.libp2p.io/concepts/protocols/#protocol-ids), and created a custom `LPProtocol`. In a more complex protocol, we could use this structure to store interesting variables. -A protocol generally has two part: and handling/server part, and a dialing/client part. +A protocol generally has two part: and handling/server part, and a dialing/client part. Theses two parts can be identical, but in our trivial protocol, the server will wait for a message from the client, and the client will send a message, so we have to handle the two cases separately. Let's start with the server part: @@ -30,13 +30,15 @@ Let's start with the server part: proc new(T: typedesc[TestProto]): T = # every incoming connections will in be handled in this closure proc handle(conn: Connection, proto: string) {.async, gcsafe.} = + # Read up to 1024 bytes from this connection, and transform them into + # a string echo "Got from remote - ", string.fromBytes(await conn.readLp(1024)) # We must close the connections ourselves when we're done with it await conn.close() return T(codecs: @[TestCodec], handler: handle) ``` -This is a constructor for our `TestProto`, that will specify our `codecs` and a `handler`, which will be called for each incoming peer asking for this protocol. +This is a constructor for our `TestProto`, that will specify our `codecs` and a `handler`, which will be called for each incoming peer asking for this protocol. In our handle, we simply read a message from the connection and `echo` it. We can now create our client part: @@ -54,12 +56,12 @@ proc main() {.async, gcsafe.} = testProto = TestProto.new() switch1 = newStandardSwitch(rng=rng) switch2 = newStandardSwitch(rng=rng) - + switch1.mount(testProto) - + await switch1.start() await switch2.start() - + let conn = await switch2.dial(switch1.peerInfo.peerId, switch1.peerInfo.addrs, TestCodec) await testProto.hello(conn) @@ -70,7 +72,7 @@ proc main() {.async, gcsafe.} = await allFutures(switch1.stop(), switch2.stop()) # close connections and shutdown all transports ``` -This is very similar to the first tutorial's `main`, the only noteworthy difference is that we use `newStandardSwitch`, which is similar to `createSwitch` but is bundled directly in libp2p +This is very similar to the first tutorial's `main`, the only noteworthy difference is that we use `newStandardSwitch`, which is similar to the `createSwitch` of the first tutorial, but is bundled directly in libp2p We can now wrap our program by calling our main proc: ```nim diff --git a/vendor/nim-libp2p/libp2p.nim b/vendor/nim-libp2p/libp2p.nim index a07bbf0ca..46f802320 100644 --- a/vendor/nim-libp2p/libp2p.nim +++ b/vendor/nim-libp2p/libp2p.nim @@ -1,40 +1,72 @@ -## Nim-LibP2P -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -import - libp2p/[protobuf/minprotobuf, - muxers/muxer, - muxers/mplex/mplex, - stream/lpstream, - stream/bufferstream, - stream/connection, - transports/transport, - transports/tcptransport, - protocols/secure/noise, - cid, - multihash, - multibase, - multicodec, - errors, - switch, - peerid, - peerinfo, - multiaddress, - builders, - crypto/crypto, - protocols/pubsub] +when defined(nimdoc): + ## Welcome to the nim-libp2p reference! + ## + ## On the left, you'll find a switch that allows you to see private + ## procedures. By default, you'll only see the public one (marked with `{.public.}`) + ## + ## The difference between public and private procedures is that public procedure + ## stay backward compatible during the Major version, whereas private ones can + ## change at each new Minor version. + ## + ## If you're new to nim-libp2p, you can find a tutorial `here`_ + ## that can help you get started. -import bearssl + # Import stuff for doc + import libp2p/[ + protobuf/minprotobuf, + switch, + stream/lpstream, + builders, + transports/tcptransport, + transports/wstransport, + protocols/ping, + protocols/pubsub, + peerid, + peerinfo, + peerstore, + multiaddress] -export - minprotobuf, switch, peerid, peerinfo, - connection, multiaddress, crypto, lpstream, - bufferstream, bearssl, muxer, mplex, transport, - tcptransport, noise, errors, cid, multihash, - multicodec, builders, pubsub + proc dummyPrivateProc*() = + ## A private proc example + discard +else: + import + libp2p/[protobuf/minprotobuf, + muxers/muxer, + muxers/mplex/mplex, + stream/lpstream, + stream/bufferstream, + stream/connection, + transports/transport, + transports/tcptransport, + transports/wstransport, + protocols/secure/noise, + protocols/ping, + cid, + multihash, + multibase, + multicodec, + errors, + switch, + peerid, + peerinfo, + multiaddress, + builders, + crypto/crypto, + protocols/pubsub] + + export + minprotobuf, switch, peerid, peerinfo, + connection, multiaddress, crypto, lpstream, + bufferstream, muxer, mplex, transport, + tcptransport, noise, errors, cid, multihash, + multicodec, builders, pubsub diff --git a/vendor/nim-libp2p/libp2p.nimble b/vendor/nim-libp2p/libp2p.nimble index 513d83491..fb2ef486c 100644 --- a/vendor/nim-libp2p/libp2p.nimble +++ b/vendor/nim-libp2p/libp2p.nimble @@ -18,31 +18,21 @@ requires "nim >= 1.2.0", "stew#head", "websock" -const nimflags = - "--verbosity:0 --hints:off " & - "--warning[CaseTransition]:off --warning[ObservableStores]:off " & - "--warning[LockLevel]:off " & - "-d:chronosStrictException " & - "--styleCheck:usages --styleCheck:hint " - proc runTest(filename: string, verify: bool = true, sign: bool = true, moreoptions: string = "") = - var excstr = "nim c --opt:speed -d:debug -d:libp2p_agents_metrics -d:libp2p_protobuf_metrics -d:libp2p_network_protocols_metrics -d:libp2p_mplex_metrics " + var excstr = "nim c --skipParentCfg --opt:speed -d:debug -d:libp2p_agents_metrics -d:libp2p_protobuf_metrics -d:libp2p_network_protocols_metrics -d:libp2p_mplex_metrics " + excstr.add(" -d:chronicles_sinks=textlines[stdout],json[dynamic] -d:chronicles_log_level=TRACE ") + excstr.add(" -d:chronicles_runtime_filtering=TRUE ") excstr.add(" " & getEnv("NIMFLAGS") & " ") - excstr.add(" " & nimflags & " ") + excstr.add(" --verbosity:0 --hints:off ") excstr.add(" -d:libp2p_pubsub_sign=" & $sign) excstr.add(" -d:libp2p_pubsub_verify=" & $verify) excstr.add(" " & moreoptions & " ") - if verify and sign: - # build it with TRACE and JSON logs - exec excstr & " -d:chronicles_log_level=TRACE -d:chronicles_sinks:json" & " tests/" & filename - # build it again, to run it with less verbose logs - exec excstr & " -d:chronicles_log_level=INFO -r" & " tests/" & filename + exec excstr & " -r " & " tests/" & filename rmFile "tests/" & filename.toExe proc buildSample(filename: string, run = false) = - var excstr = "nim c --opt:speed --threads:on -d:debug " - excstr.add(" " & nimflags & " ") + var excstr = "nim c --opt:speed --threads:on -d:debug --verbosity:0 --hints:off " excstr.add(" examples/" & filename) exec excstr if run: @@ -51,7 +41,7 @@ proc buildSample(filename: string, run = false) = proc buildTutorial(filename: string) = discard gorge "cat " & filename & " | nim c -r --hints:off tools/markdown_runner.nim | " & - " nim " & nimflags & " c -" + " nim --verbosity:0 --hints:off c -" task testnative, "Runs libp2p native tests": runTest("testnative") @@ -99,6 +89,7 @@ task test_slim, "Runs the (slimmed down) test suite": task examples_build, "Build the samples": buildSample("directchat") buildSample("helloworld", true) + buildSample("circuitrelay", true) buildTutorial("examples/tutorial_1_connect.md") buildTutorial("examples/tutorial_2_customproto.md") diff --git a/vendor/nim-libp2p/libp2p/builders.nim b/vendor/nim-libp2p/libp2p/builders.nim index d77031b15..828fc5283 100644 --- a/vendor/nim-libp2p/libp2p/builders.nim +++ b/vendor/nim-libp2p/libp2p/builders.nim @@ -1,45 +1,54 @@ -## Nim-Libp2p -## Copyright (c) 2020 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +## This module contains a Switch Building helper. +runnableExamples: + let switch = + SwitchBuilder.new() + .withRng(rng) + .withAddresses(multiaddress) + # etc + .build() + +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import - options, tables, chronos, chronicles, bearssl, + options, tables, chronos, chronicles, sequtils, switch, peerid, peerinfo, stream/connection, multiaddress, crypto/crypto, transports/[transport, tcptransport], - muxers/[muxer, mplex/mplex], - protocols/[identify, secure/secure, secure/noise, relay], + muxers/[muxer, mplex/mplex, yamux/yamux], + protocols/[identify, secure/secure, secure/noise, autonat], + protocols/relay/[relay, client, rtransport], connmanager, upgrademngrs/muxedupgrade, nameresolving/nameresolver, - errors + errors, utility export switch, peerid, peerinfo, connection, multiaddress, crypto, errors type - TransportProvider* = proc(upgr: Upgrade): Transport {.gcsafe, raises: [Defect].} + TransportProvider* {.public.} = proc(upgr: Upgrade): Transport {.gcsafe, raises: [Defect].} SecureProtocol* {.pure.} = enum Noise, Secio {.deprecated.} - MplexOpts = object - enable: bool - newMuxer: MuxerConstructor - SwitchBuilder* = ref object privKey: Option[PrivateKey] addresses: seq[MultiAddress] secureManagers: seq[SecureProtocol] - mplexOpts: MplexOpts + muxers: seq[MuxerProvider] transports: seq[TransportProvider] - rng: ref BrHmacDrbgContext + rng: ref HmacDrbgContext maxConnections: int maxIn: int sendSignedPeerRecord: bool @@ -49,10 +58,11 @@ type agentVersion: string nameResolver: NameResolver peerStoreCapacity: Option[int] - isCircuitRelay: bool - circuitRelayCanHop: bool + autonat: bool + circuitRelay: Relay -proc new*(T: type[SwitchBuilder]): T = +proc new*(T: type[SwitchBuilder]): T {.public.} = + ## Creates a SwitchBuilder let address = MultiAddress .init("/ip4/127.0.0.1/tcp/0") @@ -67,22 +77,30 @@ proc new*(T: type[SwitchBuilder]): T = maxOut: -1, maxConnsPerPeer: MaxConnectionsPerPeer, protoVersion: ProtoVersion, - agentVersion: AgentVersion, - isCircuitRelay: false) + agentVersion: AgentVersion) + +proc withPrivateKey*(b: SwitchBuilder, privateKey: PrivateKey): SwitchBuilder {.public.} = + ## Set the private key of the switch. Will be used to + ## generate a PeerId -proc withPrivateKey*(b: SwitchBuilder, privateKey: PrivateKey): SwitchBuilder = b.privKey = some(privateKey) b -proc withAddress*(b: SwitchBuilder, address: MultiAddress): SwitchBuilder = +proc withAddress*(b: SwitchBuilder, address: MultiAddress): SwitchBuilder {.public.} = + ## | Set the listening address of the switch + ## | Calling it multiple time will override the value + b.addresses = @[address] b -proc withAddresses*(b: SwitchBuilder, addresses: seq[MultiAddress]): SwitchBuilder = +proc withAddresses*(b: SwitchBuilder, addresses: seq[MultiAddress]): SwitchBuilder {.public.} = + ## | Set the listening addresses of the switch + ## | Calling it multiple time will override the value + b.addresses = addresses b -proc withSignedPeerRecord*(b: SwitchBuilder, sendIt = true): SwitchBuilder = +proc withSignedPeerRecord*(b: SwitchBuilder, sendIt = true): SwitchBuilder {.public.} = b.sendSignedPeerRecord = sendIt b @@ -90,7 +108,9 @@ proc withMplex*( b: SwitchBuilder, inTimeout = 5.minutes, outTimeout = 5.minutes, - maxChannCount = 200): SwitchBuilder = + maxChannCount = 200): SwitchBuilder {.public.} = + ## | Uses `Mplex `_ as a multiplexer + ## | `Timeout` is the duration after which a inactive connection will be closed proc newMuxer(conn: Connection): Muxer = Mplex.new( conn, @@ -98,67 +118,84 @@ proc withMplex*( outTimeout, maxChannCount) - b.mplexOpts = MplexOpts( - enable: true, - newMuxer: newMuxer, - ) - + assert b.muxers.countIt(it.codec == MplexCodec) == 0, "Mplex build multiple times" + b.muxers.add(MuxerProvider.new(newMuxer, MplexCodec)) b -proc withNoise*(b: SwitchBuilder): SwitchBuilder = +proc withYamux*(b: SwitchBuilder): SwitchBuilder = + proc newMuxer(conn: Connection): Muxer = Yamux.new(conn) + + assert b.muxers.countIt(it.codec == YamuxCodec) == 0, "Yamux build multiple times" + b.muxers.add(MuxerProvider.new(newMuxer, YamuxCodec)) + b + +proc withNoise*(b: SwitchBuilder): SwitchBuilder {.public.} = b.secureManagers.add(SecureProtocol.Noise) b -proc withTransport*(b: SwitchBuilder, prov: TransportProvider): SwitchBuilder = +proc withTransport*(b: SwitchBuilder, prov: TransportProvider): SwitchBuilder {.public.} = + ## Use a custom transport + runnableExamples: + let switch = + SwitchBuilder.new() + .withTransport(proc(upgr: Upgrade): Transport = TcpTransport.new(flags, upgr)) + .build() b.transports.add(prov) b -proc withTcpTransport*(b: SwitchBuilder, flags: set[ServerFlags] = {}): SwitchBuilder = +proc withTcpTransport*(b: SwitchBuilder, flags: set[ServerFlags] = {}): SwitchBuilder {.public.} = b.withTransport(proc(upgr: Upgrade): Transport = TcpTransport.new(flags, upgr)) -proc withRng*(b: SwitchBuilder, rng: ref BrHmacDrbgContext): SwitchBuilder = +proc withRng*(b: SwitchBuilder, rng: ref HmacDrbgContext): SwitchBuilder {.public.} = b.rng = rng b -proc withMaxConnections*(b: SwitchBuilder, maxConnections: int): SwitchBuilder = +proc withMaxConnections*(b: SwitchBuilder, maxConnections: int): SwitchBuilder {.public.} = + ## Maximum concurrent connections of the switch. You should either use this, or + ## `withMaxIn <#withMaxIn,SwitchBuilder,int>`_ & `withMaxOut<#withMaxOut,SwitchBuilder,int>`_ b.maxConnections = maxConnections b -proc withMaxIn*(b: SwitchBuilder, maxIn: int): SwitchBuilder = +proc withMaxIn*(b: SwitchBuilder, maxIn: int): SwitchBuilder {.public.} = + ## Maximum concurrent incoming connections. Should be used with `withMaxOut<#withMaxOut,SwitchBuilder,int>`_ b.maxIn = maxIn b -proc withMaxOut*(b: SwitchBuilder, maxOut: int): SwitchBuilder = +proc withMaxOut*(b: SwitchBuilder, maxOut: int): SwitchBuilder {.public.} = + ## Maximum concurrent outgoing connections. Should be used with `withMaxIn<#withMaxIn,SwitchBuilder,int>`_ b.maxOut = maxOut b -proc withMaxConnsPerPeer*(b: SwitchBuilder, maxConnsPerPeer: int): SwitchBuilder = +proc withMaxConnsPerPeer*(b: SwitchBuilder, maxConnsPerPeer: int): SwitchBuilder {.public.} = b.maxConnsPerPeer = maxConnsPerPeer b -proc withPeerStore*(b: SwitchBuilder, capacity: int): SwitchBuilder = +proc withPeerStore*(b: SwitchBuilder, capacity: int): SwitchBuilder {.public.} = b.peerStoreCapacity = some(capacity) b -proc withProtoVersion*(b: SwitchBuilder, protoVersion: string): SwitchBuilder = +proc withProtoVersion*(b: SwitchBuilder, protoVersion: string): SwitchBuilder {.public.} = b.protoVersion = protoVersion b -proc withAgentVersion*(b: SwitchBuilder, agentVersion: string): SwitchBuilder = +proc withAgentVersion*(b: SwitchBuilder, agentVersion: string): SwitchBuilder {.public.} = b.agentVersion = agentVersion b -proc withNameResolver*(b: SwitchBuilder, nameResolver: NameResolver): SwitchBuilder = +proc withNameResolver*(b: SwitchBuilder, nameResolver: NameResolver): SwitchBuilder {.public.} = b.nameResolver = nameResolver b -proc withRelayTransport*(b: SwitchBuilder, canHop: bool): SwitchBuilder = - b.isCircuitRelay = true - b.circuitRelayCanHop = canHop +proc withAutonat*(b: SwitchBuilder): SwitchBuilder = + b.autonat = true + b + +proc withCircuitRelay*(b: SwitchBuilder, r: Relay = Relay.new()): SwitchBuilder = + b.circuitRelay = r b proc build*(b: SwitchBuilder): Switch - {.raises: [Defect, LPError].} = + {.raises: [Defect, LPError], public.} = if b.rng == nil: # newRng could fail raise newException(Defect, "Cannot initialize RNG") @@ -179,18 +216,11 @@ proc build*(b: SwitchBuilder): Switch protoVersion = b.protoVersion, agentVersion = b.agentVersion) - let - muxers = block: - var muxers: Table[string, MuxerProvider] - if b.mplexOpts.enable: - muxers[MplexCodec] = MuxerProvider.new(b.mplexOpts.newMuxer, MplexCodec) - muxers - let identify = Identify.new(peerInfo, b.sendSignedPeerRecord) connManager = ConnManager.new(b.maxConnsPerPeer, b.maxConnections, b.maxIn, b.maxOut) ms = MultistreamSelect.new() - muxedUpgrade = MuxedUpgrade.new(identify, muxers, secureManagerInstances, connManager, ms) + muxedUpgrade = MuxedUpgrade.new(identify, b.muxers, secureManagerInstances, connManager, ms) let transports = block: @@ -215,17 +245,21 @@ proc build*(b: SwitchBuilder): Switch peerInfo = peerInfo, transports = transports, identity = identify, - muxers = muxers, secureManagers = secureManagerInstances, connManager = connManager, ms = ms, nameResolver = b.nameResolver, peerStore = peerStore) - if b.isCircuitRelay: - let relay = Relay.new(switch, b.circuitRelayCanHop) - switch.mount(relay) - switch.addTransport(RelayTransport.new(relay, muxedUpgrade)) + if b.autonat: + let autonat = Autonat.new(switch) + switch.mount(autonat) + + if not isNil(b.circuitRelay): + if b.circuitRelay of RelayClient: + switch.addTransport(RelayTransport.new(RelayClient(b.circuitRelay), muxedUpgrade)) + b.circuitRelay.setup(switch) + switch.mount(b.circuitRelay) return switch @@ -246,7 +280,9 @@ proc newStandardSwitch*( nameResolver: NameResolver = nil, sendSignedPeerRecord = false, peerStoreCapacity = 1000): Switch - {.raises: [Defect, LPError].} = + {.raises: [Defect, LPError], public.} = + ## Helper for common switch configurations. + if SecureProtocol.Secio in secureManagers: quit("Secio is deprecated!") # use of secio is unsafe diff --git a/vendor/nim-libp2p/libp2p/cid.nim b/vendor/nim-libp2p/libp2p/cid.nim index 7af403567..1f18f8201 100644 --- a/vendor/nim-libp2p/libp2p/cid.nim +++ b/vendor/nim-libp2p/libp2p/cid.nim @@ -1,15 +1,18 @@ -## Nim-LibP2P -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. ## This module implementes CID (Content IDentifier). -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import tables, hashes import multibase, multicodec, multihash, vbuffer, varint diff --git a/vendor/nim-libp2p/libp2p/connmanager.nim b/vendor/nim-libp2p/libp2p/connmanager.nim index 76de2da07..b7ac3d87a 100644 --- a/vendor/nim-libp2p/libp2p/connmanager.nim +++ b/vendor/nim-libp2p/libp2p/connmanager.nim @@ -1,13 +1,16 @@ -## Nim-LibP2P -## Copyright (c) 2020 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/[options, tables, sequtils, sets] import pkg/[chronos, chronicles, metrics] @@ -30,9 +33,6 @@ const type TooManyConnectionsError* = object of LPError - ConnProvider* = proc(): Future[Connection] - {.gcsafe, closure, raises: [Defect].} - ConnEventKind* {.pure.} = enum Connected, # A connection was made and securely upgraded - there may be # more than one concurrent connection thus more than one upgrade @@ -81,6 +81,10 @@ type peerEvents: array[PeerEventKind, OrderedSet[PeerEventHandler]] peerStore*: PeerStore + ConnectionSlot* = object + connManager: ConnManager + direction: Direction + proc newTooManyConnectionsError(): ref TooManyConnectionsError {.inline.} = result = newException(TooManyConnectionsError, "Too many connections") @@ -401,90 +405,39 @@ proc storeConn*(c: ConnManager, conn: Connection) trace "Stored connection", conn, direction = $conn.dir, connections = c.conns.len -proc trackConn(c: ConnManager, - provider: ConnProvider, - sema: AsyncSemaphore): - Future[Connection] {.async.} = - var conn: Connection - try: - conn = await provider() - - if isNil(conn): - return - - trace "Got connection", conn - - proc semaphoreMonitor() {.async.} = - try: - await conn.join() - except CatchableError as exc: - trace "Exception in semaphore monitor, ignoring", exc = exc.msg - - sema.release() - - asyncSpawn semaphoreMonitor() - except CatchableError as exc: - trace "Exception tracking connection", exc = exc.msg - if not isNil(conn): - await conn.close() - - raise exc - - return conn - -proc trackIncomingConn*(c: ConnManager, - provider: ConnProvider): - Future[Connection] {.async.} = - ## await for a connection slot before attempting - ## to call the connection provider - ## - - var conn: Connection - try: - trace "Tracking incoming connection" - await c.inSema.acquire() - conn = await c.trackConn(provider, c.inSema) - if isNil(conn): - trace "Couldn't acquire connection, releasing semaphore slot", dir = $Direction.In - c.inSema.release() - - return conn - except CatchableError as exc: - trace "Exception tracking connection", exc = exc.msg - c.inSema.release() - raise exc - -proc trackOutgoingConn*(c: ConnManager, - provider: ConnProvider, - forceDial = false): - Future[Connection] {.async.} = - ## try acquiring a connection if all slots - ## are already taken, raise TooManyConnectionsError - ## exception - ## - - trace "Tracking outgoing connection", count = c.outSema.count, - max = c.outSema.size +proc getIncomingSlot*(c: ConnManager): Future[ConnectionSlot] {.async.} = + await c.inSema.acquire() + return ConnectionSlot(connManager: c, direction: In) +proc getOutgoingSlot*(c: ConnManager, forceDial = false): Future[ConnectionSlot] {.async.} = if forceDial: c.outSema.forceAcquire() elif not c.outSema.tryAcquire(): trace "Too many outgoing connections!", count = c.outSema.count, max = c.outSema.size raise newTooManyConnectionsError() + return ConnectionSlot(connManager: c, direction: Out) - var conn: Connection - try: - conn = await c.trackConn(provider, c.outSema) - if isNil(conn): - trace "Couldn't acquire connection, releasing semaphore slot", dir = $Direction.Out - c.outSema.release() +proc release*(cs: ConnectionSlot) = + if cs.direction == In: + cs.connManager.inSema.release() + else: + cs.connManager.outSema.release() - return conn - except CatchableError as exc: - trace "Exception tracking connection", exc = exc.msg - c.outSema.release() - raise exc +proc trackConnection*(cs: ConnectionSlot, conn: Connection) = + if isNil(conn): + cs.release() + return + + proc semaphoreMonitor() {.async.} = + try: + await conn.join() + except CatchableError as exc: + trace "Exception in semaphore monitor, ignoring", exc = exc.msg + + cs.release() + + asyncSpawn semaphoreMonitor() proc storeMuxer*(c: ConnManager, muxer: Muxer, diff --git a/vendor/nim-libp2p/libp2p/crypto/chacha20poly1305.nim b/vendor/nim-libp2p/libp2p/crypto/chacha20poly1305.nim index 094423e52..8482897d8 100644 --- a/vendor/nim-libp2p/libp2p/crypto/chacha20poly1305.nim +++ b/vendor/nim-libp2p/libp2p/crypto/chacha20poly1305.nim @@ -1,11 +1,11 @@ -## Nim-Libp2p -## Copyright (c) 2020-2022 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. ## This module integrates BearSSL ChaCha20+Poly1305 ## @@ -15,19 +15,15 @@ # RFC @ https://tools.ietf.org/html/rfc7539 -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} -import bearssl +import bearssl/blockx from stew/assign2 import assign from stew/ranges/ptr_arith import baseAddr -# have to do this due to a nim bug and raises[] on callbacks -# https://github.com/nim-lang/Nim/issues/13905 -proc ourPoly1305CtmulRun*(key: pointer; iv: pointer; data: pointer; len: int; - aad: pointer; aadLen: int; tag: pointer; ichacha: pointer; - encrypt: cint) {.cdecl, importc: "br_poly1305_ctmul_run", - header: "bearssl_block.h".} - const ChaChaPolyKeySize = 32 ChaChaPolyNonceSize = 12 @@ -67,15 +63,16 @@ proc encrypt*(_: type[ChaChaPoly], else: nil - ourPoly1305CtmulRun( + poly1305CtmulRun( unsafeAddr key[0], unsafeAddr nonce[0], baseAddr(data), - data.len, + uint(data.len), ad, - aad.len, + uint(aad.len), baseAddr(tag), - chacha20CtRun, + # cast is required to workaround https://github.com/nim-lang/Nim/issues/13905 + cast[Chacha20Run](chacha20CtRun), #[encrypt]# 1.cint) proc decrypt*(_: type[ChaChaPoly], @@ -90,13 +87,14 @@ proc decrypt*(_: type[ChaChaPoly], else: nil - ourPoly1305CtmulRun( + poly1305CtmulRun( unsafeAddr key[0], unsafeAddr nonce[0], baseAddr(data), - data.len, + uint(data.len), ad, - aad.len, + uint(aad.len), baseAddr(tag), - chacha20CtRun, + # cast is required to workaround https://github.com/nim-lang/Nim/issues/13905 + cast[Chacha20Run](chacha20CtRun), #[decrypt]# 0.cint) diff --git a/vendor/nim-libp2p/libp2p/crypto/crypto.nim b/vendor/nim-libp2p/libp2p/crypto/crypto.nim index a9cde403e..1ccf8386f 100644 --- a/vendor/nim-libp2p/libp2p/crypto/crypto.nim +++ b/vendor/nim-libp2p/libp2p/crypto/crypto.nim @@ -1,14 +1,17 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. ## This module implements Public Key and Private Key interface for libp2p. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} from strutils import split, strip, cmpIgnoreCase @@ -69,17 +72,17 @@ when supported(PKScheme.Secp256k1): # We are still importing `ecnist` because, it is used for SECIO handshake, # but it will be impossible to create ECNIST keys or import ECNIST keys. -import ecnist, bearssl +import ecnist, bearssl/rand, bearssl/hash as bhash import ../protobuf/minprotobuf, ../vbuffer, ../multihash, ../multicodec import nimcrypto/[rijndael, twofish, sha2, hash, hmac] # We use `ncrutils` for constant-time hexadecimal encoding/decoding procedures. import nimcrypto/utils as ncrutils import ../utility import stew/results -export results +export results, utility # This is workaround for Nim's `import` bug -export rijndael, twofish, sha2, hash, hmac, ncrutils +export rijndael, twofish, sha2, hash, hmac, ncrutils, rand type DigestSheme* = enum @@ -158,26 +161,28 @@ type template orError*(exp: untyped, err: untyped): untyped = (exp.mapErr do (_: auto) -> auto: err) -proc newRng*(): ref BrHmacDrbgContext = +proc newRng*(): ref HmacDrbgContext = # You should only create one instance of the RNG per application / library # Ref is used so that it can be shared between components # TODO consider moving to bearssl - var seeder = brPrngSeederSystem(nil) + var seeder = prngSeederSystem(nil) if seeder == nil: return nil - var rng = (ref BrHmacDrbgContext)() - brHmacDrbgInit(addr rng[], addr sha256Vtable, nil, 0) + var rng = (ref HmacDrbgContext)() + hmacDrbgInit(rng[], addr sha256Vtable, nil, 0) if seeder(addr rng.vtable) == 0: return nil rng proc shuffle*[T]( - rng: ref BrHmacDrbgContext, + rng: ref HmacDrbgContext, x: var openArray[T]) = + if x.len == 0: return + var randValues = newSeqUninitialized[byte](len(x) * 2) - brHmacDrbgGenerate(rng[], randValues) + hmacDrbgGenerate(rng[], randValues) for i in countdown(x.high, 1): let @@ -186,7 +191,7 @@ proc shuffle*[T]( swap(x[i], x[y]) proc random*(T: typedesc[PrivateKey], scheme: PKScheme, - rng: var BrHmacDrbgContext, + rng: var HmacDrbgContext, bits = RsaDefaultKeySize): CryptoResult[PrivateKey] = ## Generate random private key for scheme ``scheme``. ## @@ -218,7 +223,7 @@ proc random*(T: typedesc[PrivateKey], scheme: PKScheme, else: err(SchemeError) -proc random*(T: typedesc[PrivateKey], rng: var BrHmacDrbgContext, +proc random*(T: typedesc[PrivateKey], rng: var HmacDrbgContext, bits = RsaDefaultKeySize): CryptoResult[PrivateKey] = ## Generate random private key using default public-key cryptography scheme. ## @@ -242,7 +247,7 @@ proc random*(T: typedesc[PrivateKey], rng: var BrHmacDrbgContext, err(SchemeError) proc random*(T: typedesc[KeyPair], scheme: PKScheme, - rng: var BrHmacDrbgContext, + rng: var HmacDrbgContext, bits = RsaDefaultKeySize): CryptoResult[KeyPair] = ## Generate random key pair for scheme ``scheme``. ## @@ -282,7 +287,7 @@ proc random*(T: typedesc[KeyPair], scheme: PKScheme, else: err(SchemeError) -proc random*(T: typedesc[KeyPair], rng: var BrHmacDrbgContext, +proc random*(T: typedesc[KeyPair], rng: var HmacDrbgContext, bits = RsaDefaultKeySize): CryptoResult[KeyPair] = ## Generate random private pair of keys using default public-key cryptography ## scheme. @@ -870,7 +875,7 @@ proc mac*(secret: Secret, id: int): seq[byte] {.inline.} = proc ephemeral*( scheme: ECDHEScheme, - rng: var BrHmacDrbgContext): CryptoResult[EcKeyPair] = + rng: var HmacDrbgContext): CryptoResult[EcKeyPair] = ## Generate ephemeral keys used to perform ECDHE. var keypair: EcKeyPair if scheme == Secp256r1: @@ -882,7 +887,7 @@ proc ephemeral*( ok(keypair) proc ephemeral*( - scheme: string, rng: var BrHmacDrbgContext): CryptoResult[EcKeyPair] = + scheme: string, rng: var HmacDrbgContext): CryptoResult[EcKeyPair] = ## Generate ephemeral keys used to perform ECDHE using string encoding. ## ## Currently supported encoding strings are P-256, P-384, P-521, if encoding diff --git a/vendor/nim-libp2p/libp2p/crypto/curve25519.nim b/vendor/nim-libp2p/libp2p/crypto/curve25519.nim index 4f66b1616..98a80d7e2 100644 --- a/vendor/nim-libp2p/libp2p/crypto/curve25519.nim +++ b/vendor/nim-libp2p/libp2p/crypto/curve25519.nim @@ -1,11 +1,11 @@ -## Nim-Libp2p -## Copyright (c) 2020-2022 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022-2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. ## This module integrates BearSSL Cyrve25519 mul and mulgen ## @@ -15,9 +15,12 @@ # RFC @ https://tools.ietf.org/html/rfc7748 -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} -import bearssl +import bearssl/[ec, rand, hash] import stew/results from stew/assign2 import assign export results @@ -28,7 +31,6 @@ const type Curve25519* = object Curve25519Key* = array[Curve25519KeySize, byte] - pcuchar = ptr char Curve25519Error* = enum Curver25519GenError @@ -46,7 +48,7 @@ proc byteswap(buf: var Curve25519Key) {.inline.} = buf[31 - i] = x proc mul*(_: type[Curve25519], point: var Curve25519Key, multiplier: Curve25519Key) = - let defaultBrEc = brEcGetDefault() + let defaultBrEc = ecGetDefault() # multiplier needs to be big-endian var @@ -54,15 +56,15 @@ proc mul*(_: type[Curve25519], point: var Curve25519Key, multiplier: Curve25519K multiplierBs.byteswap() let res = defaultBrEc.mul( - cast[pcuchar](addr point[0]), + addr point[0], Curve25519KeySize, - cast[pcuchar](addr multiplierBs[0]), + addr multiplierBs[0], Curve25519KeySize, EC_curve25519) assert res == 1 proc mulgen(_: type[Curve25519], dst: var Curve25519Key, point: Curve25519Key) = - let defaultBrEc = brEcGetDefault() + let defaultBrEc = ecGetDefault() var rpoint = point @@ -70,20 +72,20 @@ proc mulgen(_: type[Curve25519], dst: var Curve25519Key, point: Curve25519Key) = let size = defaultBrEc.mulgen( - cast[pcuchar](addr dst[0]), - cast[pcuchar](addr rpoint[0]), + addr dst[0], + addr rpoint[0], Curve25519KeySize, EC_curve25519) - + assert size == Curve25519KeySize proc public*(private: Curve25519Key): Curve25519Key = Curve25519.mulgen(result, private) -proc random*(_: type[Curve25519Key], rng: var BrHmacDrbgContext): Curve25519Key = +proc random*(_: type[Curve25519Key], rng: var HmacDrbgContext): Curve25519Key = var res: Curve25519Key - let defaultBrEc = brEcGetDefault() - let len = brEcKeygen( + let defaultBrEc = ecGetDefault() + let len = ecKeygen( addr rng.vtable, defaultBrEc, nil, addr res[0], EC_curve25519) # Per bearssl documentation, the keygen only fails if the curve is # unrecognised - diff --git a/vendor/nim-libp2p/libp2p/crypto/ecnist.nim b/vendor/nim-libp2p/libp2p/crypto/ecnist.nim index b212eb360..51786f3b1 100644 --- a/vendor/nim-libp2p/libp2p/crypto/ecnist.nim +++ b/vendor/nim-libp2p/libp2p/crypto/ecnist.nim @@ -1,11 +1,11 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. ## This module implements constant-time ECDSA and ECDHE for NIST elliptic ## curves secp256r1, secp384r1 and secp521r1. @@ -14,9 +14,12 @@ ## BearSSL library ## Copyright(C) 2018 Thomas Pornin . -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} -import bearssl +import bearssl/[ec, rand, hash] # We use `ncrutils` for constant-time hexadecimal encoding/decoding procedures. import nimcrypto/utils as ncrutils import minasn1 @@ -40,12 +43,12 @@ const type EcPrivateKey* = ref object - buffer*: array[BR_EC_KBUF_PRIV_MAX_SIZE, byte] - key*: BrEcPrivateKey + buffer*: array[EC_KBUF_PRIV_MAX_SIZE, byte] + key*: ec.EcPrivateKey EcPublicKey* = ref object - buffer*: array[BR_EC_KBUF_PUB_MAX_SIZE, byte] - key*: BrEcPublicKey + buffer*: array[EC_KBUF_PUB_MAX_SIZE, byte] + key*: ec.EcPublicKey EcKeyPair* = object seckey*: EcPrivateKey @@ -55,9 +58,9 @@ type buffer*: seq[byte] EcCurveKind* = enum - Secp256r1 = BR_EC_SECP256R1, - Secp384r1 = BR_EC_SECP384R1, - Secp521r1 = BR_EC_SECP521R1 + Secp256r1 = EC_secp256r1, + Secp384r1 = EC_secp384r1, + Secp521r1 = EC_secp521r1 EcPKI* = EcPrivateKey | EcPublicKey | EcSignature @@ -101,15 +104,15 @@ proc checkScalar(scalar: openArray[byte], curve: cint): uint32 = ## - ``scalar`` is lower than the curve ``order``. ## ## Otherwise, return ``0``. - var impl = brEcGetDefault() - var orderlen = 0 - var order = cast[ptr UncheckedArray[byte]](impl.order(curve, addr orderlen)) + var impl = ecGetDefault() + var orderlen: uint = 0 + var order = cast[ptr UncheckedArray[byte]](impl.order(curve, orderlen)) var z = 0'u32 var c = 0'i32 for u in scalar: z = z or u - if len(scalar) == orderlen: + if len(scalar) == int(orderlen): for i in 0.. getPublicKeyLength(cast[EcCurveKind](seckey.key.curve)) - if brEcComputePublicKey(ecimp, addr res.key, - addr res.buffer[0], unsafeAddr seckey.key) == 0: + if ecComputePub(ecimp, addr res.key, + addr res.buffer[0], unsafeAddr seckey.key) == 0: err(EcKeyIncorrectError) else: ok(res) @@ -264,7 +267,7 @@ proc getPublicKey*(seckey: EcPrivateKey): EcResult[EcPublicKey] = proc random*( T: typedesc[EcKeyPair], kind: EcCurveKind, - rng: var BrHmacDrbgContext): EcResult[T] = + rng: var HmacDrbgContext): EcResult[T] = ## Generate new random EC private and public keypair using BearSSL's ## HMAC-SHA256-DRBG algorithm. ## @@ -373,24 +376,24 @@ proc toBytes*(seckey: EcPrivateKey, data: var openArray[byte]): EcResult[int] = var p = Asn1Composite.init(Asn1Tag.Sequence) var c0 = Asn1Composite.init(0) var c1 = Asn1Composite.init(1) - if seckey.key.curve == BR_EC_SECP256R1: + if seckey.key.curve == EC_secp256r1: c0.write(Asn1Tag.Oid, Asn1OidSecp256r1) - elif seckey.key.curve == BR_EC_SECP384R1: + elif seckey.key.curve == EC_secp384r1: c0.write(Asn1Tag.Oid, Asn1OidSecp384r1) - elif seckey.key.curve == BR_EC_SECP521R1: + elif seckey.key.curve == EC_secp521r1: c0.write(Asn1Tag.Oid, Asn1OidSecp521r1) c0.finish() offset = pubkey.getOffset() if offset < 0: return err(EcKeyIncorrectError) - length = pubkey.key.qlen + length = int(pubkey.key.qlen) c1.write(Asn1Tag.BitString, pubkey.buffer.toOpenArray(offset, offset + length - 1)) c1.finish() offset = seckey.getOffset() if offset < 0: return err(EcKeyIncorrectError) - length = seckey.key.xlen + length = int(seckey.key.xlen) p.write(1'u64) p.write(Asn1Tag.OctetString, seckey.buffer.toOpenArray(offset, offset + length - 1)) @@ -421,18 +424,18 @@ proc toBytes*(pubkey: EcPublicKey, data: var openArray[byte]): EcResult[int] = var p = Asn1Composite.init(Asn1Tag.Sequence) var c = Asn1Composite.init(Asn1Tag.Sequence) c.write(Asn1Tag.Oid, Asn1OidEcPublicKey) - if pubkey.key.curve == BR_EC_SECP256R1: + if pubkey.key.curve == EC_secp256r1: c.write(Asn1Tag.Oid, Asn1OidSecp256r1) - elif pubkey.key.curve == BR_EC_SECP384R1: + elif pubkey.key.curve == EC_secp384r1: c.write(Asn1Tag.Oid, Asn1OidSecp384r1) - elif pubkey.key.curve == BR_EC_SECP521R1: + elif pubkey.key.curve == EC_secp521r1: c.write(Asn1Tag.Oid, Asn1OidSecp521r1) c.finish() p.write(c) let offset = getOffset(pubkey) if offset < 0: return err(EcKeyIncorrectError) - let length = pubkey.key.qlen + let length = int(pubkey.key.qlen) p.write(Asn1Tag.BitString, pubkey.buffer.toOpenArray(offset, offset + length - 1)) p.finish() @@ -638,8 +641,8 @@ proc init*(key: var EcPrivateKey, data: openArray[byte]): Result[void, Asn1Error if checkScalar(raw.toOpenArray(), curve) == 1'u32: key = new EcPrivateKey copyMem(addr key.buffer[0], addr raw.buffer[raw.offset], raw.length) - key.key.x = cast[ptr char](addr key.buffer[0]) - key.key.xlen = raw.length + key.key.x = addr key.buffer[0] + key.key.xlen = uint(raw.length) key.key.curve = curve ok() else: @@ -697,8 +700,8 @@ proc init*(pubkey: var EcPublicKey, data: openArray[byte]): Result[void, Asn1Err if checkPublic(raw.toOpenArray(), curve) != 0: pubkey = new EcPublicKey copyMem(addr pubkey.buffer[0], addr raw.buffer[raw.offset], raw.length) - pubkey.key.q = cast[ptr char](addr pubkey.buffer[0]) - pubkey.key.qlen = raw.length + pubkey.key.q = addr pubkey.buffer[0] + pubkey.key.qlen = uint(raw.length) pubkey.key.curve = curve ok() else: @@ -785,8 +788,8 @@ proc initRaw*(key: var EcPrivateKey, data: openArray[byte]): bool = let length = len(data) key = new EcPrivateKey copyMem(addr key.buffer[0], unsafeAddr data[0], length) - key.key.x = cast[ptr char](addr key.buffer[0]) - key.key.xlen = length + key.key.x = addr key.buffer[0] + key.key.xlen = uint(length) key.key.curve = curve result = true @@ -816,8 +819,8 @@ proc initRaw*(pubkey: var EcPublicKey, data: openArray[byte]): bool = let length = len(data) pubkey = new EcPublicKey copyMem(addr pubkey.buffer[0], unsafeAddr data[0], length) - pubkey.key.q = cast[ptr char](addr pubkey.buffer[0]) - pubkey.key.qlen = length + pubkey.key.q = addr pubkey.buffer[0] + pubkey.key.qlen = uint(length) pubkey.key.curve = curve result = true @@ -883,7 +886,7 @@ proc scalarMul*(pub: EcPublicKey, sec: EcPrivateKey): EcPublicKey = ## ## Returns point in curve as ``pub * sec`` or ``nil`` otherwise. doAssert((not isNil(pub)) and (not isNil(sec))) - var impl = brEcGetDefault() + var impl = ecGetDefault() if sec.key.curve in EcSupportedCurvesCint: if pub.key.curve == sec.key.curve: var key = new EcPublicKey @@ -891,9 +894,9 @@ proc scalarMul*(pub: EcPublicKey, sec: EcPrivateKey): EcPublicKey = let poffset = key.getOffset() let soffset = sec.getOffset() if poffset >= 0 and soffset >= 0: - let res = impl.mul(cast[ptr char](addr key.buffer[poffset]), + let res = impl.mul(addr key.buffer[poffset], key.key.qlen, - cast[ptr char](unsafeAddr sec.buffer[soffset]), + unsafeAddr sec.buffer[soffset], sec.key.xlen, key.key.curve) if res != 0: @@ -913,11 +916,11 @@ proc toSecret*(pubkey: EcPublicKey, seckey: EcPrivateKey, doAssert((not isNil(pubkey)) and (not isNil(seckey))) var mult = scalarMul(pubkey, seckey) if not isNil(mult): - if seckey.key.curve == BR_EC_SECP256R1: + if seckey.key.curve == EC_secp256r1: result = Secret256Length - elif seckey.key.curve == BR_EC_SECP384R1: + elif seckey.key.curve == EC_secp384r1: result = Secret384Length - elif seckey.key.curve == BR_EC_SECP521R1: + elif seckey.key.curve == EC_secp521r1: result = Secret521Length if len(data) >= result: var qplus1 = cast[pointer](cast[uint](mult.key.q) + 1'u) @@ -941,20 +944,20 @@ proc sign*[T: byte|char](seckey: EcPrivateKey, ## Get ECDSA signature of data ``message`` using private key ``seckey``. if isNil(seckey): return err(EcKeyIncorrectError) - var hc: BrHashCompatContext + var hc: HashCompatContext var hash: array[32, byte] - var impl = brEcGetDefault() + var impl = ecGetDefault() if seckey.key.curve in EcSupportedCurvesCint: var sig = new EcSignature sig.buffer = newSeq[byte](256) var kv = addr sha256Vtable kv.init(addr hc.vtable) if len(message) > 0: - kv.update(addr hc.vtable, unsafeAddr message[0], len(message)) + kv.update(addr hc.vtable, unsafeAddr message[0], uint(len(message))) else: kv.update(addr hc.vtable, nil, 0) - kv.output(addr hc.vtable, addr hash[0]) - let res = brEcdsaSignAsn1(impl, kv, addr hash[0], addr seckey.key, + kv.out(addr hc.vtable, addr hash[0]) + let res = ecdsaI31SignAsn1(impl, kv, addr hash[0], addr seckey.key, addr sig.buffer[0]) # Clear context with initial value kv.init(addr hc.vtable) @@ -974,20 +977,20 @@ proc verify*[T: byte|char](sig: EcSignature, message: openArray[T], ## Return ``true`` if message verification succeeded, ``false`` if ## verification failed. doAssert((not isNil(sig)) and (not isNil(pubkey))) - var hc: BrHashCompatContext + var hc: HashCompatContext var hash: array[32, byte] - var impl = brEcGetDefault() + var impl = ecGetDefault() if pubkey.key.curve in EcSupportedCurvesCint: var kv = addr sha256Vtable kv.init(addr hc.vtable) if len(message) > 0: - kv.update(addr hc.vtable, unsafeAddr message[0], len(message)) + kv.update(addr hc.vtable, unsafeAddr message[0], uint(len(message))) else: kv.update(addr hc.vtable, nil, 0) - kv.output(addr hc.vtable, addr hash[0]) - let res = brEcdsaVerifyAsn1(impl, addr hash[0], len(hash), - unsafeAddr pubkey.key, - addr sig.buffer[0], len(sig.buffer)) + kv.out(addr hc.vtable, addr hash[0]) + let res = ecdsaI31VrfyAsn1(impl, addr hash[0], uint(len(hash)), + unsafeAddr pubkey.key, + addr sig.buffer[0], uint(len(sig.buffer))) # Clear context with initial value kv.init(addr hc.vtable) result = (res == 1) diff --git a/vendor/nim-libp2p/libp2p/crypto/ed25519/constants.nim b/vendor/nim-libp2p/libp2p/crypto/ed25519/constants.nim index bc2248c54..bc77ea770 100644 --- a/vendor/nim-libp2p/libp2p/crypto/ed25519/constants.nim +++ b/vendor/nim-libp2p/libp2p/crypto/ed25519/constants.nim @@ -1,11 +1,11 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. ## This module implements ED25519. ## This is pure nim implementation of ED25519 ref10. diff --git a/vendor/nim-libp2p/libp2p/crypto/ed25519/ed25519.nim b/vendor/nim-libp2p/libp2p/crypto/ed25519/ed25519.nim index f9654b355..c906113a9 100644 --- a/vendor/nim-libp2p/libp2p/crypto/ed25519/ed25519.nim +++ b/vendor/nim-libp2p/libp2p/crypto/ed25519/ed25519.nim @@ -1,19 +1,23 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. ## This module implements ED25519. ## This code is a port of the public domain, "ref10" implementation of ed25519 ## from SUPERCOP. -{.push raises: Defect.} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} -import constants, bearssl +import bearssl/rand +import constants import nimcrypto/[hash, sha2] # We use `ncrutils` for constant-time hexadecimal encoding/decoding procedures. import nimcrypto/utils as ncrutils @@ -21,7 +25,7 @@ import stew/[results, ctops] export results # This workaround needed because of some bugs in Nim Static[T]. -export hash, sha2 +export hash, sha2, rand const EdPrivateKeySize* = 64 @@ -1644,14 +1648,14 @@ proc checkScalar*(scalar: openArray[byte]): uint32 = c = -1 result = NEQ(z, 0'u32) and LT0(c) -proc random*(t: typedesc[EdPrivateKey], rng: var BrHmacDrbgContext): EdPrivateKey = +proc random*(t: typedesc[EdPrivateKey], rng: var HmacDrbgContext): EdPrivateKey = ## Generate new random ED25519 private key using the given random number generator var point: GeP3 pk: array[EdPublicKeySize, byte] res: EdPrivateKey - brHmacDrbgGenerate(addr rng, addr res.data[0], 32) + hmacDrbgGenerate(rng, res.data.toOpenArray(0, 31)) var hh = sha512.digest(res.data.toOpenArray(0, 31)) hh.data[0] = hh.data[0] and 0xF8'u8 @@ -1663,14 +1667,14 @@ proc random*(t: typedesc[EdPrivateKey], rng: var BrHmacDrbgContext): EdPrivateKe res -proc random*(t: typedesc[EdKeyPair], rng: var BrHmacDrbgContext): EdKeyPair = +proc random*(t: typedesc[EdKeyPair], rng: var HmacDrbgContext): EdKeyPair = ## Generate new random ED25519 private and public keypair using OS specific ## CSPRNG. var point: GeP3 res: EdKeyPair - brHmacDrbgGenerate(addr rng, addr res.seckey.data[0], 32) + hmacDrbgGenerate(rng, res.seckey.data.toOpenArray(0, 31)) var hh = sha512.digest(res.seckey.data.toOpenArray(0, 31)) hh.data[0] = hh.data[0] and 0xF8'u8 diff --git a/vendor/nim-libp2p/libp2p/crypto/hkdf.nim b/vendor/nim-libp2p/libp2p/crypto/hkdf.nim index 55fffa83f..88ad17a8f 100644 --- a/vendor/nim-libp2p/libp2p/crypto/hkdf.nim +++ b/vendor/nim-libp2p/libp2p/crypto/hkdf.nim @@ -1,40 +1,36 @@ -## Nim-LibP2P -## Copyright (c) 2020 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. # https://tools.ietf.org/html/rfc5869 -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import nimcrypto -import bearssl +import bearssl/[kdf, rand, hash] -type - BearHKDFContext {.importc: "br_hkdf_context", header: "bearssl_kdf.h".} = object - HKDFResult*[len: static int] = array[len, byte] +type HkdfResult*[len: static int] = array[len, byte] -proc br_hkdf_init(ctx: ptr BearHKDFContext; hashClass: ptr HashClass; salt: pointer; len: csize_t) {.importc: "br_hkdf_init", header: "bearssl_kdf.h", raises: [].} -proc br_hkdf_inject(ctx: ptr BearHKDFContext; ikm: pointer; len: csize_t) {.importc: "br_hkdf_inject", header: "bearssl_kdf.h", raises: [].} -proc br_hkdf_flip(ctx: ptr BearHKDFContext) {.importc: "br_hkdf_flip", header: "bearssl_kdf.h", raises: [].} -proc br_hkdf_produce(ctx: ptr BearHKDFContext; info: pointer; infoLen: csize_t; output: pointer; outputLen: csize_t) {.importc: "br_hkdf_produce", header: "bearssl_kdf.h", raises: [].} - -proc hkdf*[T: sha256; len: static int](_: type[T]; salt, ikm, info: openArray[byte]; outputs: var openArray[HKDFResult[len]]) = +proc hkdf*[T: sha256; len: static int](_: type[T]; salt, ikm, info: openArray[byte]; outputs: var openArray[HkdfResult[len]]) = var - ctx: BearHKDFContext - br_hkdf_init( - addr ctx, addr sha256Vtable, + ctx: HkdfContext + hkdfInit( + ctx, addr sha256Vtable, if salt.len > 0: unsafeAddr salt[0] else: nil, csize_t(salt.len)) - br_hkdf_inject( - addr ctx, if ikm.len > 0: unsafeAddr ikm[0] else: nil, csize_t(ikm.len)) - br_hkdf_flip(addr ctx) + hkdfInject( + ctx, if ikm.len > 0: unsafeAddr ikm[0] else: nil, csize_t(ikm.len)) + hkdfFlip(ctx) for i in 0..outputs.high: - br_hkdf_produce( - addr ctx, + discard hkdfProduce( + ctx, if info.len > 0: unsafeAddr info[0] else: nil, csize_t(info.len), addr outputs[i][0], csize_t(outputs[i].len)) diff --git a/vendor/nim-libp2p/libp2p/crypto/minasn1.nim b/vendor/nim-libp2p/libp2p/crypto/minasn1.nim index 3bea03739..cb30b662d 100644 --- a/vendor/nim-libp2p/libp2p/crypto/minasn1.nim +++ b/vendor/nim-libp2p/libp2p/crypto/minasn1.nim @@ -1,15 +1,18 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. ## This module implements minimal ASN.1 encoding/decoding primitives. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import stew/[endians2, results, ctops] export results diff --git a/vendor/nim-libp2p/libp2p/crypto/rsa.nim b/vendor/nim-libp2p/libp2p/crypto/rsa.nim index 133936cd6..5fe82ee06 100644 --- a/vendor/nim-libp2p/libp2p/crypto/rsa.nim +++ b/vendor/nim-libp2p/libp2p/crypto/rsa.nim @@ -1,11 +1,11 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. ## This module implements constant-time RSA PKCS#1.5 DSA. ## @@ -13,8 +13,12 @@ ## BearSSL library ## Copyright(C) 2018 Thomas Pornin . -{.push raises: Defect.} -import bearssl +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} + +import bearssl/[rsa, rand, hash] import minasn1 import stew/[results, ctops] # We use `ncrutils` for constant-time hexadecimal encoding/decoding procedures. @@ -33,41 +37,41 @@ const ## Default RSA key size in bits. RsaOidSha1* = [ - 0x05'u8, 0x2B'u8, 0x0E'u8, 0x03'u8, 0x02'u8, 0x1A'u8 + byte 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A ] ## RSA PKCS#1.5 SHA-1 hash object identifier. RsaOidSha224* = [ - 0x09'u8, 0x60'u8, 0x86'u8, 0x48'u8, 0x01'u8, 0x65'u8, 0x03'u8, 0x04'u8, - 0x02'u8, 0x04'u8 + byte 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, + 0x02, 0x04 ] ## RSA PKCS#1.5 SHA-224 hash object identifier. RsaOidSha256* = [ - 0x09'u8, 0x60'u8, 0x86'u8, 0x48'u8, 0x01'u8, 0x65'u8, 0x03'u8, 0x04'u8, - 0x02'u8, 0x01'u8 + byte 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, + 0x02, 0x01 ] ## RSA PKCS#1.5 SHA-256 hash object identifier. RsaOidSha384* = [ - 0x09'u8, 0x60'u8, 0x86'u8, 0x48'u8, 0x01'u8, 0x65'u8, 0x03'u8, 0x04'u8, - 0x02'u8, 0x02'u8 + byte 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, + 0x02, 0x02 ] ## RSA PKCS#1.5 SHA-384 hash object identifier. RsaOidSha512* = [ - 0x09'u8, 0x60'u8, 0x86'u8, 0x48'u8, 0x01'u8, 0x65'u8, 0x03'u8, 0x04'u8, - 0x02'u8, 0x03'u8 + byte 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, + 0x02, 0x03 ] ## RSA PKCS#1.5 SHA-512 hash object identifier. type RsaPrivateKey* = ref object buffer*: seq[byte] - seck*: BrRsaPrivateKey - pubk*: BrRsaPublicKey - pexp*: ptr char - pexplen*: int + seck*: rsa.RsaPrivateKey + pubk*: rsa.RsaPublicKey + pexp*: ptr byte + pexplen*: uint RsaPublicKey* = ref object buffer*: seq[byte] - key*: BrRsaPublicKey + key*: rsa.RsaPublicKey RsaKeyPair* = RsaPrivateKey @@ -99,8 +103,8 @@ template getFinish(bs, os, ls: untyped): untyped = var eo = -1 if p >= s: let so = cast[int](p - s) - if so + ls <= len(bs): - eo = so + ls - 1 + if so + int(ls) <= len(bs): + eo = so + int(ls) - 1 eo template getArray*(bs, os, ls: untyped): untyped = @@ -109,12 +113,12 @@ template getArray*(bs, os, ls: untyped): untyped = template trimZeroes(b: seq[byte], pt, ptlen: untyped) = var length = ptlen for i in 0.. 0: - let length = key.seck.plen + key.seck.qlen + key.seck.dplen + - key.seck.dqlen + key.seck.iqlen + key.pubk.nlen + - key.pubk.elen + key.pexplen + let length = key.seck.plen.uint + key.seck.qlen.uint + key.seck.dplen.uint + + key.seck.dqlen.uint + key.seck.iqlen.uint + key.pubk.nlen.uint + + key.pubk.elen.uint + key.pexplen.uint result = new RsaPrivateKey result.buffer = newSeq[byte](length) - let po = 0 + let po: uint = 0 let qo = po + key.seck.plen let dpo = qo + key.seck.qlen let dqo = dpo + key.seck.dplen @@ -190,14 +194,14 @@ proc copy*[T: RsaPKI](key: T): T = copyMem(addr result.buffer[no], key.pubk.n, key.pubk.nlen) copyMem(addr result.buffer[eo], key.pubk.e, key.pubk.elen) copyMem(addr result.buffer[peo], key.pexp, key.pexplen) - result.seck.p = cast[ptr char](addr result.buffer[po]) - result.seck.q = cast[ptr char](addr result.buffer[qo]) - result.seck.dp = cast[ptr char](addr result.buffer[dpo]) - result.seck.dq = cast[ptr char](addr result.buffer[dqo]) - result.seck.iq = cast[ptr char](addr result.buffer[iqo]) - result.pubk.n = cast[ptr char](addr result.buffer[no]) - result.pubk.e = cast[ptr char](addr result.buffer[eo]) - result.pexp = cast[ptr char](addr result.buffer[peo]) + result.seck.p = addr result.buffer[po] + result.seck.q = addr result.buffer[qo] + result.seck.dp = addr result.buffer[dpo] + result.seck.dq = addr result.buffer[dqo] + result.seck.iq = addr result.buffer[iqo] + result.pubk.n = addr result.buffer[no] + result.pubk.e = addr result.buffer[eo] + result.pexp = addr result.buffer[peo] result.seck.plen = key.seck.plen result.seck.qlen = key.seck.qlen result.seck.dplen = key.seck.dplen @@ -231,8 +235,8 @@ proc getPublicKey*(key: RsaPrivateKey): RsaPublicKey = let length = key.pubk.nlen + key.pubk.elen result = new RsaPublicKey result.buffer = newSeq[byte](length) - result.key.n = cast[ptr char](addr result.buffer[0]) - result.key.e = cast[ptr char](addr result.buffer[key.pubk.nlen]) + result.key.n = addr result.buffer[0] + result.key.e = addr result.buffer[key.pubk.nlen] copyMem(addr result.buffer[0], cast[pointer](key.pubk.n), key.pubk.nlen) copyMem(addr result.buffer[key.pubk.nlen], cast[pointer](key.pubk.e), key.pubk.elen) @@ -472,22 +476,22 @@ proc init*(key: var RsaPrivateKey, data: openArray[byte]): Result[void, Asn1Erro len(rawdp) > 0 and len(rawdq) > 0 and len(rawiq) > 0: key = new RsaPrivateKey key.buffer = @data - key.pubk.n = cast[ptr char](addr key.buffer[rawn.offset]) - key.pubk.e = cast[ptr char](addr key.buffer[rawpube.offset]) - key.seck.p = cast[ptr char](addr key.buffer[rawp.offset]) - key.seck.q = cast[ptr char](addr key.buffer[rawq.offset]) - key.seck.dp = cast[ptr char](addr key.buffer[rawdp.offset]) - key.seck.dq = cast[ptr char](addr key.buffer[rawdq.offset]) - key.seck.iq = cast[ptr char](addr key.buffer[rawiq.offset]) - key.pexp = cast[ptr char](addr key.buffer[rawprie.offset]) - key.pubk.nlen = len(rawn) - key.pubk.elen = len(rawpube) - key.seck.plen = len(rawp) - key.seck.qlen = len(rawq) - key.seck.dplen = len(rawdp) - key.seck.dqlen = len(rawdq) - key.seck.iqlen = len(rawiq) - key.pexplen = len(rawprie) + key.pubk.n = addr key.buffer[rawn.offset] + key.pubk.e = addr key.buffer[rawpube.offset] + key.seck.p = addr key.buffer[rawp.offset] + key.seck.q = addr key.buffer[rawq.offset] + key.seck.dp = addr key.buffer[rawdp.offset] + key.seck.dq = addr key.buffer[rawdq.offset] + key.seck.iq = addr key.buffer[rawiq.offset] + key.pexp = addr key.buffer[rawprie.offset] + key.pubk.nlen = uint(len(rawn)) + key.pubk.elen = uint(len(rawpube)) + key.seck.plen = uint(len(rawp)) + key.seck.qlen = uint(len(rawq)) + key.seck.dplen = uint(len(rawdp)) + key.seck.dqlen = uint(len(rawdq)) + key.seck.iqlen = uint(len(rawiq)) + key.pexplen = uint(len(rawprie)) key.seck.nBitlen = cast[uint32](len(rawn) shl 3) ok() else: @@ -554,10 +558,10 @@ proc init*(key: var RsaPublicKey, data: openArray[byte]): Result[void, Asn1Error if len(rawn) >= (MinKeySize shr 3) and len(rawe) > 0: key = new RsaPublicKey key.buffer = @data - key.key.n = cast[ptr char](addr key.buffer[rawn.offset]) - key.key.e = cast[ptr char](addr key.buffer[rawe.offset]) - key.key.nlen = len(rawn) - key.key.elen = len(rawe) + key.key.n = addr key.buffer[rawn.offset] + key.key.e = addr key.buffer[rawe.offset] + key.key.nlen = uint(len(rawn)) + key.key.elen = uint(len(rawe)) ok() else: err(Asn1Error.Incorrect) @@ -749,22 +753,22 @@ proc sign*[T: byte|char](key: RsaPrivateKey, if isNil(key): return err(RsaKeyIncorrectError) - var hc: BrHashCompatContext + var hc: HashCompatContext var hash: array[32, byte] - let impl = BrRsaPkcs1SignGetDefault() + let impl = rsaPkcs1SignGetDefault() var res = new RsaSignature res.buffer = newSeq[byte]((key.seck.nBitlen + 7) shr 3) var kv = addr sha256Vtable kv.init(addr hc.vtable) if len(message) > 0: - kv.update(addr hc.vtable, unsafeAddr message[0], len(message)) + kv.update(addr hc.vtable, unsafeAddr message[0], uint(len(message))) else: kv.update(addr hc.vtable, nil, 0) - kv.output(addr hc.vtable, addr hash[0]) + kv.out(addr hc.vtable, addr hash[0]) var oid = RsaOidSha256 - let implRes = impl(cast[ptr char](addr oid[0]), - cast[ptr char](addr hash[0]), len(hash), - addr key.seck, cast[ptr char](addr res.buffer[0])) + let implRes = impl(addr oid[0], + addr hash[0], uint(len(hash)), + addr key.seck, addr res.buffer[0]) if implRes == 0: err(RsaSignatureError) else: @@ -779,20 +783,20 @@ proc verify*[T: byte|char](sig: RsaSignature, message: openArray[T], ## verification failed. doAssert((not isNil(sig)) and (not isNil(pubkey))) if len(sig.buffer) > 0: - var hc: BrHashCompatContext + var hc: HashCompatContext var hash: array[32, byte] var check: array[32, byte] - var impl = BrRsaPkcs1VrfyGetDefault() + var impl = rsaPkcs1VrfyGetDefault() var kv = addr sha256Vtable kv.init(addr hc.vtable) if len(message) > 0: - kv.update(addr hc.vtable, unsafeAddr message[0], len(message)) + kv.update(addr hc.vtable, unsafeAddr message[0], uint(len(message))) else: kv.update(addr hc.vtable, nil, 0) - kv.output(addr hc.vtable, addr hash[0]) + kv.out(addr hc.vtable, addr hash[0]) var oid = RsaOidSha256 - let res = impl(cast[ptr char](addr sig.buffer[0]), len(sig.buffer), - cast[ptr char](addr oid[0]), - len(check), addr pubkey.key, cast[ptr char](addr check[0])) + let res = impl(addr sig.buffer[0], uint(len(sig.buffer)), + addr oid[0], + uint(len(check)), addr pubkey.key, addr check[0]) if res == 1: result = equalMem(addr check[0], addr hash[0], len(hash)) diff --git a/vendor/nim-libp2p/libp2p/crypto/secp.nim b/vendor/nim-libp2p/libp2p/crypto/secp.nim index 9b483ef1d..20daa13ef 100644 --- a/vendor/nim-libp2p/libp2p/crypto/secp.nim +++ b/vendor/nim-libp2p/libp2p/crypto/secp.nim @@ -1,20 +1,24 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} +import bearssl/rand import - secp256k1, bearssl, + secp256k1, stew/[byteutils, results], nimcrypto/[hash, sha2] -export sha2, results +export sha2, results, rand const SkRawPrivateKeySize* = 256 div 8 @@ -34,17 +38,18 @@ type template pubkey*(v: SkKeyPair): SkPublicKey = SkPublicKey(secp256k1.SkKeyPair(v).pubkey) template seckey*(v: SkKeyPair): SkPrivateKey = SkPrivateKey(secp256k1.SkKeyPair(v).seckey) -proc random*(t: typedesc[SkPrivateKey], rng: var BrHmacDrbgContext): SkPrivateKey = - let rngPtr = unsafeAddr rng # doesn't escape +proc random*(t: typedesc[SkPrivateKey], rng: var HmacDrbgContext): SkPrivateKey = + #TODO is there a better way? + var rngPtr = addr rng proc callRng(data: var openArray[byte]) = - brHmacDrbgGenerate(rngPtr[], data) + hmacDrbgGenerate(rngPtr[], data) SkPrivateKey(SkSecretKey.random(callRng)) -proc random*(t: typedesc[SkKeyPair], rng: var BrHmacDrbgContext): SkKeyPair = - let rngPtr = unsafeAddr rng # doesn't escape +proc random*(t: typedesc[SkKeyPair], rng: var HmacDrbgContext): SkKeyPair = + let rngPtr = addr rng proc callRng(data: var openArray[byte]) = - brHmacDrbgGenerate(rngPtr[], data) + hmacDrbgGenerate(rngPtr[], data) SkKeyPair(secp256k1.SkKeyPair.random(callRng)) diff --git a/vendor/nim-libp2p/libp2p/daemon/daemonapi.nim b/vendor/nim-libp2p/libp2p/daemon/daemonapi.nim index c082a6070..4e802c434 100644 --- a/vendor/nim-libp2p/libp2p/daemon/daemonapi.nim +++ b/vendor/nim-libp2p/libp2p/daemon/daemonapi.nim @@ -1,13 +1,16 @@ -## Nim-LibP2P -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} ## This module implementes API for `go-libp2p-daemon`. import std/[os, osproc, strutils, tables, strtabs, sequtils] @@ -1022,7 +1025,7 @@ proc dhtGetSinglePeerId(pb: ProtoBuffer): PeerId if pb.getRequiredField(3, result).isErr(): raise newException(DaemonLocalError, "Missing field `value`!") -proc enterDhtMessage(pb: ProtoBuffer, rt: DHTResponseType): Protobuffer +proc enterDhtMessage(pb: ProtoBuffer, rt: DHTResponseType): ProtoBuffer {.inline, raises: [Defect, DaemonLocalError].} = var dhtResponse: seq[byte] if pb.getRequiredField(ResponseType.DHT.int, dhtResponse).isOk(): diff --git a/vendor/nim-libp2p/libp2p/daemon/transpool.nim b/vendor/nim-libp2p/libp2p/daemon/transpool.nim index ae7ddab61..c1c07c16d 100644 --- a/vendor/nim-libp2p/libp2p/daemon/transpool.nim +++ b/vendor/nim-libp2p/libp2p/daemon/transpool.nim @@ -1,13 +1,16 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} ## This module implements Pool of StreamTransport. import chronos diff --git a/vendor/nim-libp2p/libp2p/debugutils.nim b/vendor/nim-libp2p/libp2p/debugutils.nim index 20daacfbd..a384f9de6 100644 --- a/vendor/nim-libp2p/libp2p/debugutils.nim +++ b/vendor/nim-libp2p/libp2p/debugutils.nim @@ -1,11 +1,11 @@ -## Nim-LibP2P -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. ## To enable dump of all incoming and outgoing unencrypted messages you need ## to compile project with ``-d:libp2p_dump`` compile-time option. When this diff --git a/vendor/nim-libp2p/libp2p/dial.nim b/vendor/nim-libp2p/libp2p/dial.nim index d850a9da2..bb8d00cd2 100644 --- a/vendor/nim-libp2p/libp2p/dial.nim +++ b/vendor/nim-libp2p/libp2p/dial.nim @@ -1,13 +1,16 @@ -## Nim-LibP2P -## Copyright (c) 2021 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import chronos import peerid, @@ -28,6 +31,13 @@ method connect*( doAssert(false, "Not implemented!") +method connect*( + self: Dial, + addrs: seq[MultiAddress]): Future[PeerId] {.async, base.} = + ## Connects to a peer and retrieve its PeerId + + doAssert(false, "Not implemented!") + method dial*( self: Dial, peerId: PeerId, @@ -55,3 +65,9 @@ method addTransport*( self: Dial, transport: Transport) {.base.} = doAssert(false, "Not implemented!") + +method tryDial*( + self: Dial, + peerId: PeerId, + addrs: seq[MultiAddress]): Future[MultiAddress] {.async, base.} = + doAssert(false, "Not implemented!") diff --git a/vendor/nim-libp2p/libp2p/dialer.nim b/vendor/nim-libp2p/libp2p/dialer.nim index eb89164da..85c5b63d9 100644 --- a/vendor/nim-libp2p/libp2p/dialer.nim +++ b/vendor/nim-libp2p/libp2p/dialer.nim @@ -1,11 +1,11 @@ -## Nim-LibP2P -## Copyright (c) 2021 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. import std/[sugar, tables] @@ -21,6 +21,7 @@ import dial, stream/connection, transports/transport, nameresolving/nameresolver, + upgrademngrs/upgrade, errors export dial, errors @@ -46,9 +47,8 @@ type proc dialAndUpgrade( self: Dialer, - peerId: PeerId, - addrs: seq[MultiAddress], - forceDial: bool): + peerId: Opt[PeerId], + addrs: seq[MultiAddress]): Future[Connection] {.async.} = debug "Dialing peer", peerId @@ -65,20 +65,7 @@ proc dialAndUpgrade( trace "Dialing address", address = $a, peerId, hostname let dialed = try: libp2p_total_dial_attempts.inc() - # await a connection slot when the total - # connection count is equal to `maxConns` - # - # Need to copy to avoid "cannot be captured" errors in Nim-1.4.x. - let - transportCopy = transport - addressCopy = a - await self.connManager.trackOutgoingConn( - () => transportCopy.dial(hostname, addressCopy), - forceDial - ) - except TooManyConnectionsError as exc: - trace "Connection limit reached!" - raise exc + await transport.dial(hostname, a) except CancelledError as exc: debug "Dialing canceled", msg = exc.msg, peerId raise exc @@ -87,9 +74,6 @@ proc dialAndUpgrade( libp2p_failed_dials.inc() continue # Try the next address - # make sure to assign the peer to the connection - dialed.peerId = peerId - # also keep track of the connection's bottom unsafe transport direction # required by gossipsub scoring dialed.transportDir = Direction.Out @@ -97,10 +81,11 @@ proc dialAndUpgrade( libp2p_successful_dials.inc() let conn = try: - await transport.upgradeOutgoing(dialed) + await transport.upgradeOutgoing(dialed, peerId) except CatchableError as exc: # If we failed to establish the connection through one transport, # we won't succeeded through another - no use in trying again + # TODO we should try another address though await dialed.close() debug "Upgrade failed", msg = exc.msg, peerId if exc isnot CancelledError: @@ -113,20 +98,22 @@ proc dialAndUpgrade( proc internalConnect( self: Dialer, - peerId: PeerId, + peerId: Opt[PeerId], addrs: seq[MultiAddress], forceDial: bool): Future[Connection] {.async.} = - if self.localPeerId == peerId: + if Opt.some(self.localPeerId) == peerId: raise newException(CatchableError, "can't dial self!") # Ensure there's only one in-flight attempt per peer - let lock = self.dialLock.mgetOrPut(peerId, newAsyncLock()) + let lock = self.dialLock.mgetOrPut(peerId.get(default(PeerId)), newAsyncLock()) try: await lock.acquire() # Check if we have a connection already and try to reuse it - var conn = self.connManager.selectConn(peerId) + var conn = + if peerId.isSome: self.connManager.selectConn(peerId.get()) + else: nil if conn != nil: if conn.atEof or conn.closed: # This connection should already have been removed from the connection @@ -139,12 +126,18 @@ proc internalConnect( trace "Reusing existing connection", conn, direction = $conn.dir return conn - conn = await self.dialAndUpgrade(peerId, addrs, forceDial) + let slot = await self.connManager.getOutgoingSlot(forceDial) + conn = + try: + await self.dialAndUpgrade(peerId, addrs) + except CatchableError as exc: + slot.release() + raise exc + slot.trackConnection(conn) if isNil(conn): # None of the addresses connected raise newException(DialFailedError, "Unable to establish outgoing link") - # We already check for this in Connection manager - # but a disconnect could have happened right after + # A disconnect could have happened right after # we've added the connection so we check again # to prevent races due to that. if conn.closed() or conn.atEof(): @@ -171,7 +164,15 @@ method connect*( if self.connManager.connCount(peerId) > 0: return - discard await self.internalConnect(peerId, addrs, forceDial) + discard await self.internalConnect(Opt.some(peerId), addrs, forceDial) + +method connect*( + self: Dialer, + addrs: seq[MultiAddress], + ): Future[PeerId] {.async.} = + ## Connects to a peer and retrieve its PeerId + + return (await self.internalConnect(Opt.none(PeerId), addrs, false)).peerId proc negotiateStream( self: Dialer, @@ -185,6 +186,27 @@ proc negotiateStream( return conn +method tryDial*( + self: Dialer, + peerId: PeerId, + addrs: seq[MultiAddress]): Future[MultiAddress] {.async.} = + ## Create a protocol stream in order to check + ## if a connection is possible. + ## Doesn't use the Connection Manager to save it. + ## + + trace "Check if it can dial", peerId, addrs + try: + let conn = await self.dialAndUpgrade(Opt.some(peerId), addrs) + if conn.isNil(): + raise newException(DialFailedError, "No valid multiaddress") + await conn.close() + return conn.observedAddr + except CancelledError as exc: + raise exc + except CatchableError as exc: + raise newException(DialFailedError, exc.msg) + method dial*( self: Dialer, peerId: PeerId, @@ -223,7 +245,7 @@ method dial*( try: trace "Dialing (new)", peerId, protos - conn = await self.internalConnect(peerId, addrs, forceDial) + conn = await self.internalConnect(Opt.some(peerId), addrs, forceDial) trace "Opening stream", conn stream = await self.connManager.getStream(conn) diff --git a/vendor/nim-libp2p/libp2p/multiaddress.nim b/vendor/nim-libp2p/libp2p/multiaddress.nim index 7d7feedb3..9fd636c20 100644 --- a/vendor/nim-libp2p/libp2p/multiaddress.nim +++ b/vendor/nim-libp2p/libp2p/multiaddress.nim @@ -1,23 +1,27 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. ## This module implements MultiAddress. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} +{.push public.} import pkg/chronos import std/[nativesockets, hashes] import tables, strutils, sets, stew/shims/net import multicodec, multihash, multibase, transcoder, vbuffer, peerid, - protobuf/minprotobuf, errors + protobuf/minprotobuf, errors, utility import stew/[base58, base32, endians2, results] -export results, minprotobuf, vbuffer +export results, minprotobuf, vbuffer, utility type MAKind* = enum @@ -586,10 +590,28 @@ proc getPart(ma: MultiAddress, index: int): MaResult[MultiAddress] = inc(offset) ok(res) +proc getParts[U, V](ma: MultiAddress, slice: HSlice[U, V]): MaResult[MultiAddress] = + when slice.a is BackwardsIndex or slice.b is BackwardsIndex: + let maLength = ? len(ma) + template normalizeIndex(index): int = + when index is BackwardsIndex: maLength - int(index) + else: int(index) + let + indexStart = normalizeIndex(slice.a) + indexEnd = normalizeIndex(slice.b) + var res: MultiAddress + for i in indexStart..indexEnd: + ? res.append(? ma[i]) + ok(res) + proc `[]`*(ma: MultiAddress, i: int): MaResult[MultiAddress] {.inline.} = ## Returns part with index ``i`` of MultiAddress ``ma``. ma.getPart(i) +proc `[]`*(ma: MultiAddress, slice: HSlice): MaResult[MultiAddress] {.inline.} = + ## Returns parts with slice ``slice`` of MultiAddress ``ma``. + ma.getParts(slice) + iterator items*(ma: MultiAddress): MaResult[MultiAddress] = ## Iterates over all addresses inside of MultiAddress ``ma``. var header: uint64 @@ -626,6 +648,13 @@ iterator items*(ma: MultiAddress): MaResult[MultiAddress] = res.data.finish() yield ok(MaResult[MultiAddress], res) +proc len*(ma: MultiAddress): MaResult[int] = + var counter: int + for part in ma: + if part.isErr: return err(part.error) + counter.inc() + ok(counter) + proc contains*(ma: MultiAddress, codec: MultiCodec): MaResult[bool] {.inline.} = ## Returns ``true``, if address with MultiCodec ``codec`` present in ## MultiAddress ``ma``. diff --git a/vendor/nim-libp2p/libp2p/multibase.nim b/vendor/nim-libp2p/libp2p/multibase.nim index e2b875d31..61430f3b5 100644 --- a/vendor/nim-libp2p/libp2p/multibase.nim +++ b/vendor/nim-libp2p/libp2p/multibase.nim @@ -1,11 +1,11 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. ## This module implements MultiBase. ## @@ -13,7 +13,10 @@ ## 1. base32z ## -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import tables import stew/[base32, base58, base64, results] diff --git a/vendor/nim-libp2p/libp2p/multicodec.nim b/vendor/nim-libp2p/libp2p/multicodec.nim index e3fbe9d1f..0cfc4c558 100644 --- a/vendor/nim-libp2p/libp2p/multicodec.nim +++ b/vendor/nim-libp2p/libp2p/multicodec.nim @@ -1,15 +1,18 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not BE copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not BE copied, modified, or distributed except according to +# those terms. ## This module implements MultiCodec. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import tables, hashes import varint, vbuffer diff --git a/vendor/nim-libp2p/libp2p/multihash.nim b/vendor/nim-libp2p/libp2p/multihash.nim index bba81d9ce..f991b02ba 100644 --- a/vendor/nim-libp2p/libp2p/multihash.nim +++ b/vendor/nim-libp2p/libp2p/multihash.nim @@ -1,11 +1,11 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. ## This module implements MultiHash. ## Supported hashes are: @@ -21,7 +21,10 @@ ## 1. SKEIN ## 2. MURMUR -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import tables import nimcrypto/[sha, sha2, keccak, blake2, hash, utils] diff --git a/vendor/nim-libp2p/libp2p/multistream.nim b/vendor/nim-libp2p/libp2p/multistream.nim index 3070123d7..e2797a6a3 100644 --- a/vendor/nim-libp2p/libp2p/multistream.nim +++ b/vendor/nim-libp2p/libp2p/multistream.nim @@ -1,15 +1,18 @@ -## Nim-LibP2P -## Copyright (c) 2019 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} -import std/[strutils] +import std/[strutils, sequtils] import chronos, chronicles, stew/byteutils import stream/connection, protocols/protocol @@ -76,7 +79,7 @@ proc select*(m: MultistreamSelect, trace "reading first requested proto", conn if s == proto[0]: trace "successfully selected ", conn, proto = proto[0] - conn.tag = proto[0] + conn.protocol = proto[0] return proto[0] elif proto.len > 1: # Try to negotiate alternatives @@ -89,7 +92,7 @@ proc select*(m: MultistreamSelect, validateSuffix(s) if s == p: trace "selected protocol", conn, protocol = s - conn.tag = s + conn.protocol = s return s return "" else: @@ -167,7 +170,7 @@ proc handle*(m: MultistreamSelect, conn: Connection, active: bool = false) {.asy if (not isNil(h.match) and h.match(ms)) or h.protos.contains(ms): trace "found handler", conn, protocol = ms await conn.writeLp(ms & "\n") - conn.tag = ms + conn.protocol = ms await h.protocol.handler(conn, ms) return debug "no handlers", conn, protocol = ms @@ -209,3 +212,9 @@ proc addHandler*(m: MultistreamSelect, m.handlers.add(HandlerHolder(protos: @[codec], protocol: protocol, match: matcher)) + +proc start*(m: MultistreamSelect) {.async.} = + await allFutures(m.handlers.mapIt(it.protocol.start())) + +proc stop*(m: MultistreamSelect) {.async.} = + await allFutures(m.handlers.mapIt(it.protocol.stop())) diff --git a/vendor/nim-libp2p/libp2p/muxers/mplex/coder.nim b/vendor/nim-libp2p/libp2p/muxers/mplex/coder.nim index 3a8df9f5c..f2cce3fce 100644 --- a/vendor/nim-libp2p/libp2p/muxers/mplex/coder.nim +++ b/vendor/nim-libp2p/libp2p/muxers/mplex/coder.nim @@ -1,13 +1,16 @@ -## Nim-LibP2P -## Copyright (c) 2019 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import pkg/[chronos, nimcrypto/utils, chronicles, stew/byteutils] import ../../stream/connection, diff --git a/vendor/nim-libp2p/libp2p/muxers/mplex/lpchannel.nim b/vendor/nim-libp2p/libp2p/muxers/mplex/lpchannel.nim index 46f558049..54d0da5da 100644 --- a/vendor/nim-libp2p/libp2p/muxers/mplex/lpchannel.nim +++ b/vendor/nim-libp2p/libp2p/muxers/mplex/lpchannel.nim @@ -1,13 +1,16 @@ -## Nim-LibP2P -## Copyright (c) 2019 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/[oids, strformat] import pkg/[chronos, chronicles, metrics, nimcrypto/utils] @@ -78,11 +81,13 @@ proc open*(s: LPChannel) {.async, gcsafe.} = try: await s.conn.writeMsg(s.id, MessageType.New, s.name) s.isOpen = true + except CancelledError as exc: + raise exc except CatchableError as exc: await s.conn.close() raise exc -method closed*(s: LPChannel): bool {.raises: [Defect].} = +method closed*(s: LPChannel): bool = s.closedLocal proc closeUnderlying(s: LPChannel): Future[void] {.async.} = @@ -166,8 +171,8 @@ method readOnce*(s: LPChannel, try: let bytes = await procCall BufferStream(s).readOnce(pbytes, nbytes) when defined(libp2p_network_protocols_metrics): - if s.tag.len > 0: - libp2p_protocols_bytes.inc(bytes.int64, labelValues=[s.tag, "in"]) + if s.protocol.len > 0: + libp2p_protocols_bytes.inc(bytes.int64, labelValues=[s.protocol, "in"]) trace "readOnce", s, bytes if bytes == 0: @@ -217,10 +222,15 @@ proc completeWrite( await fut when defined(libp2p_network_protocol_metrics): - if s.tag.len > 0: - libp2p_protocols_bytes.inc(msgLen.int64, labelValues=[s.tag, "out"]) + if s.protocol.len > 0: + libp2p_protocols_bytes.inc(msgLen.int64, labelValues=[s.protocol, "out"]) s.activity = true + except CancelledError as exc: + # Chronos may still send the data + raise exc + except LPStreamClosedError as exc: + raise exc except CatchableError as exc: trace "exception in lpchannel write handler", s, msg = exc.msg await s.reset() @@ -247,6 +257,8 @@ method write*(s: LPChannel, msg: seq[byte]): Future[void] = s.completeWrite(fut, msg.len) +method getWrapped*(s: LPChannel): Connection = s.conn + proc init*( L: type LPChannel, id: uint64, diff --git a/vendor/nim-libp2p/libp2p/muxers/mplex/mplex.nim b/vendor/nim-libp2p/libp2p/muxers/mplex/mplex.nim index fc3a69e7d..90838120d 100644 --- a/vendor/nim-libp2p/libp2p/muxers/mplex/mplex.nim +++ b/vendor/nim-libp2p/libp2p/muxers/mplex/mplex.nim @@ -1,13 +1,16 @@ -## Nim-LibP2P -## Copyright (c) 2019 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import tables, sequtils, oids import chronos, chronicles, stew/byteutils, metrics @@ -34,7 +37,6 @@ when defined(libp2p_expensive_metrics): "mplex channels", labels = ["initiator", "peer"]) type - TooManyChannels* = object of MuxerError InvalidChannelIdError* = object of MuxerError Mplex* = ref object of Muxer diff --git a/vendor/nim-libp2p/libp2p/muxers/muxer.nim b/vendor/nim-libp2p/libp2p/muxers/muxer.nim index 670a5c777..69e57e131 100644 --- a/vendor/nim-libp2p/libp2p/muxers/muxer.nim +++ b/vendor/nim-libp2p/libp2p/muxers/muxer.nim @@ -1,13 +1,16 @@ -## Nim-LibP2P -## Copyright (c) 2019 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import chronos, chronicles import ../protocols/protocol, @@ -22,6 +25,7 @@ const type MuxerError* = object of LPError + TooManyChannels* = object of MuxerError StreamHandler* = proc(conn: Connection): Future[void] {.gcsafe, raises: [Defect].} MuxerHandler* = proc(muxer: Muxer): Future[void] {.gcsafe, raises: [Defect].} diff --git a/vendor/nim-libp2p/libp2p/muxers/yamux/yamux.nim b/vendor/nim-libp2p/libp2p/muxers/yamux/yamux.nim new file mode 100644 index 000000000..83deb1009 --- /dev/null +++ b/vendor/nim-libp2p/libp2p/muxers/yamux/yamux.nim @@ -0,0 +1,509 @@ +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. + +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} + +import sequtils, std/[tables] +import chronos, chronicles, metrics, stew/[endians2, byteutils, objects] +import ../muxer, + ../../stream/connection + +export muxer + +logScope: + topics = "libp2p yamux" + +const + YamuxCodec* = "/yamux/1.0.0" + YamuxVersion = 0.uint8 + DefaultWindowSize = 256000 + MaxChannelCount = 200 + +when defined(libp2p_yamux_metrics): + declareGauge(libp2p_yamux_channels, "yamux channels", labels = ["initiator", "peer"]) + declareHistogram libp2p_yamux_send_queue, "message send queue length (in byte)", + buckets = [0.0, 100.0, 250.0, 1000.0, 2000.0, 1600.0, 6400.0, 25600.0, 256000.0] + declareHistogram libp2p_yamux_recv_queue, "message recv queue length (in byte)", + buckets = [0.0, 100.0, 250.0, 1000.0, 2000.0, 1600.0, 6400.0, 25600.0, 256000.0] + +type + YamuxError* = object of CatchableError + + MsgType = enum + Data = 0x0 + WindowUpdate = 0x1 + Ping = 0x2 + GoAway = 0x3 + + MsgFlags {.size: 2.} = enum + Syn + Ack + Fin + Rst + + GoAwayStatus = enum + NormalTermination = 0x0, + ProtocolError = 0x1, + InternalError = 0x2, + + YamuxHeader = object + version: uint8 + msgType: MsgType + flags: set[MsgFlags] + streamId: uint32 + length: uint32 + +proc readHeader(conn: LPStream): Future[YamuxHeader] {.async, gcsafe.} = + var buffer: array[12, byte] + await conn.readExactly(addr buffer[0], 12) + + result.version = buffer[0] + let flags = fromBytesBE(uint16, buffer[2..3]) + if not result.msgType.checkedEnumAssign(buffer[1]) or flags notin 0'u16..15'u16: + raise newException(YamuxError, "Wrong header") + result.flags = cast[set[MsgFlags]](flags) + result.streamId = fromBytesBE(uint32, buffer[4..7]) + result.length = fromBytesBE(uint32, buffer[8..11]) + return result + +proc `$`(header: YamuxHeader): string = + result = "{" & $header.msgType & ", " + result &= "{" & header.flags.foldl(if a != "": a & ", " & $b else: $b, "") & "}, " + result &= "streamId: " & $header.streamId & ", " + result &= "length: " & $header.length & "}" + +proc encode(header: YamuxHeader): array[12, byte] = + result[0] = header.version + result[1] = uint8(header.msgType) + result[2..3] = toBytesBE(cast[uint16](header.flags)) + result[4..7] = toBytesBE(header.streamId) + result[8..11] = toBytesBE(header.length) + +proc write(conn: LPStream, header: YamuxHeader): Future[void] {.gcsafe.} = + trace "write directly on stream", h = $header + var buffer = header.encode() + return conn.write(@buffer) + +proc ping(T: type[YamuxHeader], flag: MsgFlags, pingData: uint32): T = + T( + version: YamuxVersion, + msgType: MsgType.Ping, + flags: {flag}, + length: pingData + ) + +proc goAway(T: type[YamuxHeader], status: GoAwayStatus): T = + T( + version: YamuxVersion, + msgType: MsgType.GoAway, + length: uint32(status) + ) + +proc data( + T: type[YamuxHeader], + streamId: uint32, + length: uint32 = 0, + flags: set[MsgFlags] = {}, + ): T = + T( + version: YamuxVersion, + msgType: MsgType.Data, + length: length, + flags: flags, + streamId: streamId + ) + +proc windowUpdate( + T: type[YamuxHeader], + streamId: uint32, + delta: uint32, + flags: set[MsgFlags] = {}, + ): T = + T( + version: YamuxVersion, + msgType: MsgType.WindowUpdate, + length: delta, + flags: flags, + streamId: streamId + ) + +type + ToSend = tuple + data: seq[byte] + sent: int + fut: Future[void] + YamuxChannel* = ref object of Connection + id: uint32 + recvWindow: int + sendWindow: int + maxRecvWindow: int + conn: Connection + isSrc: bool + opened: bool + isSending: bool + sendQueue: seq[ToSend] + recvQueue: seq[byte] + isReset: bool + closedRemotely: Future[void] + closedLocally: bool + receivedData: AsyncEvent + returnedEof: bool + +proc `$`(channel: YamuxChannel): string = + result = if channel.conn.dir == Out: "=> " else: "<= " + result &= $channel.id + var s: seq[string] = @[] + if channel.closedRemotely.done(): + s.add("ClosedRemotely") + if channel.closedLocally: + s.add("ClosedLocally") + if channel.isReset: + s.add("Reset") + if s.len > 0: + result &= " {" & s.foldl(if a != "": a & ", " & b else: b, "") & "}" + +proc sendQueueBytes(channel: YamuxChannel, limit: bool = false): int = + for (elem, sent, _) in channel.sendQueue: + result.inc(min(elem.len - sent, if limit: channel.maxRecvWindow div 3 else: elem.len - sent)) + +proc actuallyClose(channel: YamuxChannel) {.async.} = + if channel.closedLocally and channel.sendQueue.len == 0 and + channel.closedRemotely.done(): + await procCall Connection(channel).closeImpl() + +proc remoteClosed(channel: YamuxChannel) {.async.} = + if not channel.closedRemotely.done(): + channel.closedRemotely.complete() + await channel.actuallyClose() + +method closeImpl*(channel: YamuxChannel) {.async, gcsafe.} = + if not channel.closedLocally: + channel.closedLocally = true + + if channel.isReset == false and channel.sendQueue.len == 0: + await channel.conn.write(YamuxHeader.data(channel.id, 0, {Fin})) + await channel.actuallyClose() + +proc reset(channel: YamuxChannel, isLocal: bool = false) {.async.} = + if not channel.isReset: + trace "Reset channel" + channel.isReset = true + for (d, s, fut) in channel.sendQueue: + fut.fail(newLPStreamEOFError()) + channel.sendQueue = @[] + channel.recvQueue = @[] + channel.sendWindow = 0 + if not channel.closedLocally: + if isLocal: + try: await channel.conn.write(YamuxHeader.data(channel.id, 0, {Rst})) + except LPStreamEOFError as exc: discard + except LPStreamClosedError as exc: discard + await channel.close() + if not channel.closedRemotely.done(): + await channel.remoteClosed() + channel.receivedData.fire() + if not isLocal: + # If we reset locally, we want to flush up to a maximum of recvWindow + # bytes. We use the recvWindow in the proc cleanupChann. + channel.recvWindow = 0 + +proc updateRecvWindow(channel: YamuxChannel) {.async.} = + let inWindow = channel.recvWindow + channel.recvQueue.len + if inWindow > channel.maxRecvWindow div 2: + return + + let delta = channel.maxRecvWindow - inWindow + channel.recvWindow.inc(delta) + await channel.conn.write(YamuxHeader.windowUpdate( + channel.id, + delta.uint32 + )) + trace "increasing the recvWindow", delta + +method readOnce*( + channel: YamuxChannel, + pbytes: pointer, + nbytes: int): + Future[int] {.async.} = + + if channel.returnedEof: raise newLPStreamEOFError() + if channel.recvQueue.len == 0: + channel.receivedData.clear() + await channel.closedRemotely or channel.receivedData.wait() + if channel.closedRemotely.done() and channel.recvQueue.len == 0: + channel.returnedEof = true + return 0 + + let toRead = min(channel.recvQueue.len, nbytes) + + var p = cast[ptr UncheckedArray[byte]](pbytes) + toOpenArray(p, 0, nbytes - 1)[0.. channel.maxRecvWindow: + debug "channel send queue too big, resetting", maxSendWindow=channel.maxRecvWindow, + currentQueueSize = channel.sendQueueBytes(true) + try: + await channel.reset(true) + except CatchableError as exc: + debug "failed to reset", msg=exc.msg + break + + let + bytesAvailable = channel.sendQueueBytes() + toSend = min(channel.sendWindow, bytesAvailable) + var + sendBuffer = newSeqUninitialized[byte](toSend + 12) + header = YamuxHeader.data(channel.id, toSend.uint32) + inBuffer = 0 + + if toSend >= bytesAvailable and channel.closedLocally: + trace "last buffer we'll sent on this channel", toSend, bytesAvailable + header.flags.incl({Fin}) + + sendBuffer[0..<12] = header.encode() + + var futures: seq[Future[void]] + while inBuffer < toSend: + let (data, sent, fut) = channel.sendQueue[0] + let bufferToSend = min(data.len - sent, toSend - inBuffer) + sendBuffer.toOpenArray(12, 12 + toSend - 1)[inBuffer..<(inBuffer+bufferToSend)] = + channel.sendQueue[0].data.toOpenArray(sent, sent + bufferToSend - 1) + channel.sendQueue[0].sent.inc(bufferToSend) + if channel.sendQueue[0].sent >= data.len: + futures.add(fut) + channel.sendQueue.delete(0) + inBuffer.inc(bufferToSend) + + trace "build send buffer", h = $header, msg=string.fromBytes(sendBuffer[12..^1]) + channel.sendWindow.dec(toSend) + try: await channel.conn.write(sendBuffer) + except CatchableError as exc: + for fut in futures.items(): + fut.fail(exc) + await channel.reset() + break + for fut in futures.items(): + fut.complete() + channel.activity = true + +method write*(channel: YamuxChannel, msg: seq[byte]): Future[void] = + result = newFuture[void]("Yamux Send") + if channel.closedLocally or channel.isReset: + result.fail(newLPStreamEOFError()) + return result + if msg.len == 0: + result.complete() + return result + channel.sendQueue.add((msg, 0, result)) + when defined(libp2p_yamux_metrics): + libp2p_yamux_recv_queue.observe(channel.sendQueueBytes().int64) + asyncSpawn channel.trySend() + +proc open*(channel: YamuxChannel) {.async, gcsafe.} = + if channel.opened: + trace "Try to open channel twice" + return + channel.opened = true + await channel.conn.write(YamuxHeader.data(channel.id, 0, {if channel.isSrc: Syn else: Ack})) + +type + Yamux* = ref object of Muxer + channels: Table[uint32, YamuxChannel] + flushed: Table[uint32, int] + currentId: uint32 + isClosed: bool + maxChannCount: int + +proc lenBySrc(m: Yamux, isSrc: bool): int = + for v in m.channels.values(): + if v.isSrc == isSrc: result += 1 + +proc cleanupChann(m: Yamux, channel: YamuxChannel) {.async.} = + await channel.join() + m.channels.del(channel.id) + when defined(libp2p_yamux_metrics): + libp2p_yamux_channels.set(m.lenBySrc(channel.isSrc).int64, [$channel.isSrc, $channel.peerId]) + if channel.isReset and channel.recvWindow > 0: + m.flushed[channel.id] = channel.recvWindow + +proc createStream(m: Yamux, id: uint32, isSrc: bool): YamuxChannel = + result = YamuxChannel( + id: id, + maxRecvWindow: DefaultWindowSize, + recvWindow: DefaultWindowSize, + sendWindow: DefaultWindowSize, + isSrc: isSrc, + conn: m.connection, + receivedData: newAsyncEvent(), + closedRemotely: newFuture[void]() + ) + result.objName = "YamuxStream" + result.dir = if isSrc: Direction.Out else: Direction.In + result.timeoutHandler = proc(): Future[void] {.gcsafe.} = + trace "Idle timeout expired, resetting YamuxChannel" + result.reset() + result.initStream() + result.peerId = m.connection.peerId + result.observedAddr = m.connection.observedAddr + result.transportDir = m.connection.transportDir + when defined(libp2p_agents_metrics): + result.shortAgent = m.connection.shortAgent + m.channels[id] = result + asyncSpawn m.cleanupChann(result) + trace "created channel", id, pid=m.connection.peerId + when defined(libp2p_yamux_metrics): + libp2p_yamux_channels.set(m.lenBySrc(isSrc).int64, [$isSrc, $result.peerId]) + +method close*(m: Yamux) {.async.} = + if m.isClosed == true: + trace "Already closed" + return + m.isClosed = true + + trace "Closing yamux" + for channel in m.channels.values: + await channel.reset() + await m.connection.write(YamuxHeader.goAway(NormalTermination)) + await m.connection.close() + trace "Closed yamux" + +proc handleStream(m: Yamux, channel: YamuxChannel) {.async.} = + ## call the muxer stream handler for this channel + ## + try: + await m.streamHandler(channel) + trace "finished handling stream" + doAssert(channel.isClosed, "connection not closed by handler!") + except CatchableError as exc: + trace "Exception in yamux stream handler", msg = exc.msg + await channel.reset() + +method handle*(m: Yamux) {.async, gcsafe.} = + trace "Starting yamux handler", pid=m.connection.peerId + try: + while not m.connection.atEof: + trace "waiting for header" + let header = await m.connection.readHeader() + trace "got message", h = $header + + case header.msgType: + of Ping: + if MsgFlags.Syn in header.flags: + await m.connection.write(YamuxHeader.ping(MsgFlags.Ack, header.length)) + of GoAway: + var status: GoAwayStatus + if status.checkedEnumAssign(header.length): trace "Received go away", status + else: trace "Received unexpected error go away" + break + of Data, WindowUpdate: + if MsgFlags.Syn in header.flags: + if header.streamId in m.channels: + debug "Trying to create an existing channel, skipping", id=header.streamId + else: + if header.streamId in m.flushed: + m.flushed.del(header.streamId) + if header.streamId mod 2 == m.currentId mod 2: + raise newException(YamuxError, "Peer used our reserved stream id") + let newStream = m.createStream(header.streamId, false) + if m.channels.len >= m.maxChannCount: + await newStream.reset() + continue + await newStream.open() + asyncSpawn m.handleStream(newStream) + elif header.streamId notin m.channels: + if header.streamId notin m.flushed: + raise newException(YamuxError, "Unknown stream ID: " & $header.streamId) + elif header.msgType == Data: + # Flush the data + m.flushed[header.streamId].dec(int(header.length)) + if m.flushed[header.streamId] < 0: + raise newException(YamuxError, "Peer exhausted the recvWindow after reset") + var buffer = newSeqUninitialized[byte](header.length) + await m.connection.readExactly(addr buffer[0], int(header.length)) + continue + + let channel = m.channels[header.streamId] + + if header.msgType == WindowUpdate: + channel.sendWindow += int(header.length) + await channel.trySend() + else: + if header.length.int > channel.recvWindow.int: + # check before allocating the buffer + raise newException(YamuxError, "Peer exhausted the recvWindow") + + if header.length > 0: + var buffer = newSeqUninitialized[byte](header.length) + await m.connection.readExactly(addr buffer[0], int(header.length)) + trace "Msg Rcv", msg=string.fromBytes(buffer) + await channel.gotDataFromRemote(buffer) + + if MsgFlags.Fin in header.flags: + trace "remote closed channel" + await channel.remoteClosed() + if MsgFlags.Rst in header.flags: + trace "remote reset channel" + await channel.reset() + except LPStreamEOFError as exc: + trace "Stream EOF", msg = exc.msg + except YamuxError as exc: + trace "Closing yamux connection", error=exc.msg + await m.connection.write(YamuxHeader.goAway(ProtocolError)) + finally: + await m.close() + trace "Stopped yamux handler" + +method newStream*( + m: Yamux, + name: string = "", + lazy: bool = false): Future[Connection] {.async, gcsafe.} = + + if m.channels.len > m.maxChannCount - 1: + raise newException(TooManyChannels, "max allowed channel count exceeded") + let stream = m.createStream(m.currentId, true) + m.currentId += 2 + if not lazy: + await stream.open() + return stream + +proc new*(T: type[Yamux], conn: Connection, maxChannCount: int = MaxChannelCount): T = + T( + connection: conn, + currentId: if conn.dir == Out: 1 else: 2, + maxChannCount: maxChannCount + ) diff --git a/vendor/nim-libp2p/libp2p/nameresolving/dnsresolver.nim b/vendor/nim-libp2p/libp2p/nameresolving/dnsresolver.nim index d224afc40..51be45624 100644 --- a/vendor/nim-libp2p/libp2p/nameresolving/dnsresolver.nim +++ b/vendor/nim-libp2p/libp2p/nameresolving/dnsresolver.nim @@ -1,13 +1,16 @@ -## Nim-LibP2P -## Copyright (c) 2021 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/[streams, strutils, sets, sequtils], diff --git a/vendor/nim-libp2p/libp2p/nameresolving/mockresolver.nim b/vendor/nim-libp2p/libp2p/nameresolving/mockresolver.nim index 9a5368f32..4d9a0617b 100644 --- a/vendor/nim-libp2p/libp2p/nameresolving/mockresolver.nim +++ b/vendor/nim-libp2p/libp2p/nameresolving/mockresolver.nim @@ -1,13 +1,16 @@ -## Nim-LibP2P -## Copyright (c) 2021 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/[streams, strutils, tables], diff --git a/vendor/nim-libp2p/libp2p/nameresolving/nameresolver.nim b/vendor/nim-libp2p/libp2p/nameresolving/nameresolver.nim index b8da3352a..0fdd6a029 100644 --- a/vendor/nim-libp2p/libp2p/nameresolving/nameresolver.nim +++ b/vendor/nim-libp2p/libp2p/nameresolving/nameresolver.nim @@ -1,13 +1,16 @@ -## Nim-LibP2P -## Copyright (c) 2021 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/[sugar, sets, sequtils, strutils] import diff --git a/vendor/nim-libp2p/libp2p/peerid.nim b/vendor/nim-libp2p/libp2p/peerid.nim index d7e578929..401fee96d 100644 --- a/vendor/nim-libp2p/libp2p/peerid.nim +++ b/vendor/nim-libp2p/libp2p/peerid.nim @@ -1,25 +1,30 @@ -## Nim-LibP2P -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. ## This module implementes API for libp2p peer. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} +{.push public.} import std/[hashes, strutils], stew/[base58, results], chronicles, nimcrypto/utils, + utility, ./crypto/crypto, ./multicodec, ./multihash, ./vbuffer, ./protobuf/minprotobuf -export results +export results, utility const maxInlineKeyLength* = 42 @@ -38,7 +43,7 @@ func shortLog*(pid: PeerId): string = var spid = $pid if len(spid) > 10: spid[3] = '*' - + when (NimMajor, NimMinor) > (1, 4): spid.delete(4 .. spid.high - 6) else: diff --git a/vendor/nim-libp2p/libp2p/peerinfo.nim b/vendor/nim-libp2p/libp2p/peerinfo.nim index ce953cc3b..59fbe74e7 100644 --- a/vendor/nim-libp2p/libp2p/peerinfo.nim +++ b/vendor/nim-libp2p/libp2p/peerinfo.nim @@ -1,17 +1,21 @@ -## Nim-LibP2P -## Copyright (c) 2019 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} +{.push public.} import std/[options, sequtils] import pkg/[chronos, chronicles, stew/results] -import peerid, multiaddress, crypto/crypto, routing_record, errors +import peerid, multiaddress, crypto/crypto, routing_record, errors, utility export peerid, multiaddress, crypto, routing_record, errors, results @@ -20,7 +24,7 @@ export peerid, multiaddress, crypto, routing_record, errors, results type PeerInfoError* = LPError - PeerInfo* = ref object + PeerInfo* {.public.} = ref object peerId*: PeerId addrs*: seq[MultiAddress] protocols*: seq[string] @@ -65,7 +69,7 @@ proc new*( except CatchableError: raise newException(PeerInfoError, "invalid private key") - let peerId = PeerID.init(key).tryGet() + let peerId = PeerId.init(key).tryGet() let peerInfo = PeerInfo( peerId: peerId, diff --git a/vendor/nim-libp2p/libp2p/peerstore.nim b/vendor/nim-libp2p/libp2p/peerstore.nim index b86145c95..88f2ec400 100644 --- a/vendor/nim-libp2p/libp2p/peerstore.nim +++ b/vendor/nim-libp2p/libp2p/peerstore.nim @@ -1,13 +1,31 @@ -## Nim-LibP2P -## Copyright (c) 2021 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +## Stores generic informations about peers. +runnableExamples: + # Will keep info of all connected peers + + # last 50 disconnected peers + let peerStore = PeerStore.new(capacity = 50) + + # Create a custom book type + type MoodBook = ref object of PeerBook[string] + + var somePeerId: PeerId + discard somePeerId.init("") + + peerStore[MoodBook][somePeerId] = "Happy" + doAssert peerStore[MoodBook][somePeerId] == "Happy" + +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/[tables, sets, options, macros], @@ -15,7 +33,8 @@ import ./protocols/identify, ./peerid, ./peerinfo, ./routing_record, - ./multiaddress + ./multiaddress, + utility type ################# @@ -23,7 +42,7 @@ type ################# PeerBookChangeHandler* = proc(peerId: PeerId) {.gcsafe, raises: [Defect].} - + ######### # Books # ######### @@ -33,29 +52,29 @@ type changeHandlers: seq[PeerBookChangeHandler] deletor: PeerBookChangeHandler - PeerBook*[T] = ref object of BasePeerBook + PeerBook*[T] {.public.} = ref object of BasePeerBook book*: Table[PeerId, T] SeqPeerBook*[T] = ref object of PeerBook[seq[T]] - - AddressBook* = ref object of SeqPeerBook[MultiAddress] - ProtoBook* = ref object of SeqPeerBook[string] - KeyBook* = ref object of PeerBook[PublicKey] - AgentBook* = ref object of PeerBook[string] - ProtoVersionBook* = ref object of PeerBook[string] - SPRBook* = ref object of PeerBook[Envelope] - + AddressBook* {.public.} = ref object of SeqPeerBook[MultiAddress] + ProtoBook* {.public.} = ref object of SeqPeerBook[string] + KeyBook* {.public.} = ref object of PeerBook[PublicKey] + + AgentBook* {.public.} = ref object of PeerBook[string] + ProtoVersionBook* {.public.} = ref object of PeerBook[string] + SPRBook* {.public.} = ref object of PeerBook[Envelope] + #################### # Peer store types # #################### - PeerStore* = ref object + PeerStore* {.public.} = ref object books: Table[string, BasePeerBook] capacity*: int toClean*: seq[PeerId] - -proc new*(T: type PeerStore, capacity = 1000): PeerStore = + +proc new*(T: type PeerStore, capacity = 1000): PeerStore {.public.} = T(capacity: capacity) ######################### @@ -63,16 +82,15 @@ proc new*(T: type PeerStore, capacity = 1000): PeerStore = ######################### proc `[]`*[T](peerBook: PeerBook[T], - peerId: PeerId): T = - ## Get all the known metadata of a provided peer. + peerId: PeerId): T {.public.} = + ## Get all known metadata of a provided peer, or default(T) if missing peerBook.book.getOrDefault(peerId) proc `[]=`*[T](peerBook: PeerBook[T], peerId: PeerId, - entry: T) = - ## Set metadata for a given peerId. This will replace any - ## previously stored metadata. - + entry: T) {.public.} = + ## Set metadata for a given peerId. + peerBook.book[peerId] = entry # Notify clients @@ -80,9 +98,9 @@ proc `[]=`*[T](peerBook: PeerBook[T], handler(peerId) proc del*[T](peerBook: PeerBook[T], - peerId: PeerId): bool = - ## Delete the provided peer from the book. - + peerId: PeerId): bool {.public.} = + ## Delete the provided peer from the book. Returns whether the peer was in the book + if peerId notin peerBook.book: return false else: @@ -92,15 +110,16 @@ proc del*[T](peerBook: PeerBook[T], handler(peerId) return true -proc contains*[T](peerBook: PeerBook[T], peerId: PeerId): bool = +proc contains*[T](peerBook: PeerBook[T], peerId: PeerId): bool {.public.} = peerId in peerBook.book -proc addHandler*[T](peerBook: PeerBook[T], handler: PeerBookChangeHandler) = +proc addHandler*[T](peerBook: PeerBook[T], handler: PeerBookChangeHandler) {.public.} = + ## Adds a callback that will be called everytime the book changes peerBook.changeHandlers.add(handler) -proc len*[T](peerBook: PeerBook[T]): int = peerBook.book.len +proc len*[T](peerBook: PeerBook[T]): int {.public.} = peerBook.book.len -################## +################## # Peer Store API # ################## macro getTypeName(t: type): untyped = @@ -108,7 +127,8 @@ macro getTypeName(t: type): untyped = let typ = getTypeImpl(t)[1] newLit(repr(typ.owner()) & "." & repr(typ)) -proc `[]`*[T](p: PeerStore, typ: type[T]): T = +proc `[]`*[T](p: PeerStore, typ: type[T]): T {.public.} = + ## Get a book from the PeerStore (ex: peerStore[AddressBook]) let name = getTypeName(T) result = T(p.books.getOrDefault(name)) if result.isNil: @@ -121,7 +141,7 @@ proc `[]`*[T](p: PeerStore, typ: type[T]): T = return result proc del*(peerStore: PeerStore, - peerId: PeerId) = + peerId: PeerId) {.public.} = ## Delete the provided peer from every book. for _, book in peerStore.books: book.deletor(peerId) diff --git a/vendor/nim-libp2p/libp2p/protobuf/minprotobuf.nim b/vendor/nim-libp2p/libp2p/protobuf/minprotobuf.nim index 919c0839b..e1e36bd61 100644 --- a/vendor/nim-libp2p/libp2p/protobuf/minprotobuf.nim +++ b/vendor/nim-libp2p/libp2p/protobuf/minprotobuf.nim @@ -1,18 +1,23 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. ## This module implements minimal Google's ProtoBuf primitives. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} -import ../varint, stew/[endians2, results] -export results +import ../varint, ../utility, stew/[endians2, results] +export results, utility + +{.push public.} const MaxMessageSize* = 1'u shl 22 diff --git a/vendor/nim-libp2p/libp2p/protocols/autonat.nim b/vendor/nim-libp2p/libp2p/protocols/autonat.nim new file mode 100644 index 000000000..bdee79990 --- /dev/null +++ b/vendor/nim-libp2p/libp2p/protocols/autonat.nim @@ -0,0 +1,301 @@ +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. + +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} + +import std/[options, sets, sequtils] +import chronos, chronicles, stew/objects +import ./protocol, + ../switch, + ../multiaddress, + ../multicodec, + ../peerid, + ../utils/semaphore, + ../errors + +logScope: + topics = "libp2p autonat" + +const + AutonatCodec* = "/libp2p/autonat/1.0.0" + AddressLimit = 8 + +type + AutonatError* = object of LPError + + MsgType* = enum + Dial = 0 + DialResponse = 1 + + ResponseStatus* = enum + Ok = 0 + DialError = 100 + DialRefused = 101 + BadRequest = 200 + InternalError = 300 + + AutonatPeerInfo* = object + id: Option[PeerId] + addrs: seq[MultiAddress] + + AutonatDial* = object + peerInfo: Option[AutonatPeerInfo] + + AutonatDialResponse* = object + status*: ResponseStatus + text*: Option[string] + ma*: Option[MultiAddress] + + AutonatMsg = object + msgType: MsgType + dial: Option[AutonatDial] + response: Option[AutonatDialResponse] + +proc encode*(msg: AutonatMsg): ProtoBuffer = + result = initProtoBuffer() + result.write(1, msg.msgType.uint) + if msg.dial.isSome(): + var dial = initProtoBuffer() + if msg.dial.get().peerInfo.isSome(): + var bufferPeerInfo = initProtoBuffer() + let peerInfo = msg.dial.get().peerInfo.get() + if peerInfo.id.isSome(): + bufferPeerInfo.write(1, peerInfo.id.get()) + for ma in peerInfo.addrs: + bufferPeerInfo.write(2, ma.data.buffer) + bufferPeerInfo.finish() + dial.write(1, bufferPeerInfo.buffer) + dial.finish() + result.write(2, dial.buffer) + if msg.response.isSome(): + var bufferResponse = initProtoBuffer() + let response = msg.response.get() + bufferResponse.write(1, response.status.uint) + if response.text.isSome(): + bufferResponse.write(2, response.text.get()) + if response.ma.isSome(): + bufferResponse.write(3, response.ma.get()) + bufferResponse.finish() + result.write(3, bufferResponse.buffer) + result.finish() + +proc encode*(d: AutonatDial): ProtoBuffer = + result = initProtoBuffer() + result.write(1, MsgType.Dial.uint) + var dial = initProtoBuffer() + if d.peerInfo.isSome(): + var bufferPeerInfo = initProtoBuffer() + let peerInfo = d.peerInfo.get() + if peerInfo.id.isSome(): + bufferPeerInfo.write(1, peerInfo.id.get()) + for ma in peerInfo.addrs: + bufferPeerInfo.write(2, ma.data.buffer) + bufferPeerInfo.finish() + dial.write(1, bufferPeerInfo.buffer) + dial.finish() + result.write(2, dial.buffer) + result.finish() + +proc encode*(r: AutonatDialResponse): ProtoBuffer = + result = initProtoBuffer() + result.write(1, MsgType.DialResponse.uint) + var bufferResponse = initProtoBuffer() + bufferResponse.write(1, r.status.uint) + if r.text.isSome(): + bufferResponse.write(2, r.text.get()) + if r.ma.isSome(): + bufferResponse.write(3, r.ma.get()) + bufferResponse.finish() + result.write(3, bufferResponse.buffer) + result.finish() + +proc decode(_: typedesc[AutonatMsg], buf: seq[byte]): Option[AutonatMsg] = + var + msgTypeOrd: uint32 + pbDial: ProtoBuffer + pbResponse: ProtoBuffer + msg: AutonatMsg + + let + pb = initProtoBuffer(buf) + r1 = pb.getField(1, msgTypeOrd) + r2 = pb.getField(2, pbDial) + r3 = pb.getField(3, pbResponse) + if r1.isErr() or r2.isErr() or r3.isErr(): return none(AutonatMsg) + + if r1.get() and not checkedEnumAssign(msg.msgType, msgTypeOrd): + return none(AutonatMsg) + if r2.get(): + var + pbPeerInfo: ProtoBuffer + dial: AutonatDial + let + r4 = pbDial.getField(1, pbPeerInfo) + if r4.isErr(): return none(AutonatMsg) + + var peerInfo: AutonatPeerInfo + if r4.get(): + var pid: PeerId + let + r5 = pbPeerInfo.getField(1, pid) + r6 = pbPeerInfo.getRepeatedField(2, peerInfo.addrs) + if r5.isErr() or r6.isErr(): return none(AutonatMsg) + if r5.get(): peerInfo.id = some(pid) + dial.peerInfo = some(peerInfo) + msg.dial = some(dial) + + if r3.get(): + var + statusOrd: uint + text: string + ma: MultiAddress + response: AutonatDialResponse + + let + r4 = pbResponse.getField(1, statusOrd) + r5 = pbResponse.getField(2, text) + r6 = pbResponse.getField(3, ma) + + if r4.isErr() or r5.isErr() or r6.isErr() or + (r4.get() and not checkedEnumAssign(response.status, statusOrd)): + return none(AutonatMsg) + if r5.get(): response.text = some(text) + if r6.get(): response.ma = some(ma) + msg.response = some(response) + + return some(msg) + +proc sendDial(conn: Connection, pid: PeerId, addrs: seq[MultiAddress]) {.async.} = + let pb = AutonatDial(peerInfo: some(AutonatPeerInfo( + id: some(pid), + addrs: addrs + ))).encode() + await conn.writeLp(pb.buffer) + +proc sendResponseError(conn: Connection, status: ResponseStatus, text: string = "") {.async.} = + let pb = AutonatDialResponse( + status: status, + text: if text == "": none(string) else: some(text), + ma: none(MultiAddress) + ).encode() + await conn.writeLp(pb.buffer) + +proc sendResponseOk(conn: Connection, ma: MultiAddress) {.async.} = + let pb = AutonatDialResponse( + status: ResponseStatus.Ok, + text: some("Ok"), + ma: some(ma) + ).encode() + await conn.writeLp(pb.buffer) + +type + Autonat* = ref object of LPProtocol + sem: AsyncSemaphore + switch*: Switch + +proc dialMe*(a: Autonat, pid: PeerId, ma: MultiAddress|seq[MultiAddress]): + Future[MultiAddress] {.async.} = + let addrs = when ma is MultiAddress: @[ma] else: ma + let conn = await a.switch.dial(pid, addrs, AutonatCodec) + defer: await conn.close() + await conn.sendDial(a.switch.peerInfo.peerId, a.switch.peerInfo.addrs) + let msgOpt = AutonatMsg.decode(await conn.readLp(1024)) + if msgOpt.isNone() or + msgOpt.get().msgType != DialResponse or + msgOpt.get().response.isNone(): + raise newException(AutonatError, "Unexpected response") + let response = msgOpt.get().response.get() + if response.status != ResponseStatus.Ok: + raise newException(AutonatError, "Bad status " & + $response.status & " " & + response.text.get("")) + if response.ma.isNone(): + raise newException(AutonatError, "Missing address") + return response.ma.get() + +proc tryDial(a: Autonat, conn: Connection, addrs: seq[MultiAddress]) {.async.} = + try: + await a.sem.acquire() + let ma = await a.switch.dialer.tryDial(conn.peerId, addrs) + await conn.sendResponseOk(ma) + except CancelledError as exc: + raise exc + except CatchableError as exc: + await conn.sendResponseError(DialError, exc.msg) + finally: + a.sem.release() + +proc handleDial(a: Autonat, conn: Connection, msg: AutonatMsg): Future[void] = + if msg.dial.isNone() or msg.dial.get().peerInfo.isNone(): + return conn.sendResponseError(BadRequest, "Missing Peer Info") + let peerInfo = msg.dial.get().peerInfo.get() + if peerInfo.id.isSome() and peerInfo.id.get() != conn.peerId: + return conn.sendResponseError(BadRequest, "PeerId mismatch") + + var isRelayed = conn.observedAddr.contains(multiCodec("p2p-circuit")) + if isRelayed.isErr() or isRelayed.get(): + return conn.sendResponseError(DialRefused, "Refused to dial a relayed observed address") + let hostIp = conn.observedAddr[0] + if hostIp.isErr() or not IP.match(hostIp.get()): + trace "wrong observed address", address=conn.observedAddr + return conn.sendResponseError(InternalError, "Expected an IP address") + var addrs = initHashSet[MultiAddress]() + addrs.incl(conn.observedAddr) + for ma in peerInfo.addrs: + isRelayed = ma.contains(multiCodec("p2p-circuit")) + if isRelayed.isErr() or isRelayed.get(): + continue + let maFirst = ma[0] + if maFirst.isErr() or not IP.match(maFirst.get()): + continue + + try: + addrs.incl( + if maFirst.get() == hostIp.get(): + ma + else: + let maEnd = ma[1..^1] + if maEnd.isErr(): continue + hostIp.get() & maEnd.get() + ) + except LPError as exc: + continue + if len(addrs) >= AddressLimit: + break + + if len(addrs) == 0: + return conn.sendResponseError(DialRefused, "No dialable address") + return a.tryDial(conn, toSeq(addrs)) + +proc new*(T: typedesc[Autonat], switch: Switch, semSize: int = 1): T = + let autonat = T(switch: switch, sem: newAsyncSemaphore(semSize)) + autonat.init() + autonat + +method init*(a: Autonat) = + proc handleStream(conn: Connection, proto: string) {.async, gcsafe.} = + try: + let msgOpt = AutonatMsg.decode(await conn.readLp(1024)) + if msgOpt.isNone() or msgOpt.get().msgType != MsgType.Dial: + raise newException(AutonatError, "Received malformed message") + let msg = msgOpt.get() + await a.handleDial(conn, msg) + except CancelledError as exc: + raise exc + except CatchableError as exc: + trace "exception in autonat handler", exc = exc.msg, conn + finally: + trace "exiting autonat handler", conn + await conn.close() + + a.handler = handleStream + a.codec = AutonatCodec diff --git a/vendor/nim-libp2p/libp2p/protocols/identify.nim b/vendor/nim-libp2p/libp2p/protocols/identify.nim index 8e5cfcd3f..975126ff8 100644 --- a/vendor/nim-libp2p/libp2p/protocols/identify.nim +++ b/vendor/nim-libp2p/libp2p/protocols/identify.nim @@ -1,13 +1,19 @@ -## Nim-LibP2P -## Copyright (c) 2019 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +## `Identify `_ and +## `Push Identify `_ implementation + +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/[sequtils, options, strutils, sugar] import chronos, chronicles @@ -36,7 +42,7 @@ type IdentityInvalidMsgError* = object of IdentifyError IdentifyNoPubKeyError* = object of IdentifyError - IdentifyInfo* = object + IdentifyInfo* {.public.} = object pubkey*: Option[PublicKey] peerId*: PeerId addrs*: seq[MultiAddress] @@ -54,7 +60,7 @@ type peer: PeerId, newInfo: IdentifyInfo): Future[void] - {.gcsafe, raises: [Defect].} + {.gcsafe, raises: [Defect], public.} IdentifyPush* = ref object of LPProtocol identifyHandler: IdentifyPushHandler @@ -203,7 +209,9 @@ proc identify*(p: Identify, else: raise newException(IdentityInvalidMsgError, "No pubkey in identify") -proc new*(T: typedesc[IdentifyPush], handler: IdentifyPushHandler = nil): T = +proc new*(T: typedesc[IdentifyPush], handler: IdentifyPushHandler = nil): T {.public.} = + ## Create a IdentifyPush protocol. `handler` will be called every time + ## a peer sends us new `PeerInfo` let identifypush = T(identifyHandler: handler) identifypush.init() identifypush @@ -240,6 +248,7 @@ proc init*(p: IdentifyPush) = p.handler = handle p.codec = IdentifyPushCodec -proc push*(p: IdentifyPush, peerInfo: PeerInfo, conn: Connection) {.async.} = +proc push*(p: IdentifyPush, peerInfo: PeerInfo, conn: Connection) {.async, public.} = + ## Send new `peerInfo`s to a connection var pb = encodeMsg(peerInfo, conn.observedAddr, true) await conn.writeLp(pb.buffer) diff --git a/vendor/nim-libp2p/libp2p/protocols/ping.nim b/vendor/nim-libp2p/libp2p/protocols/ping.nim index c07b2a0d0..9c31c8935 100644 --- a/vendor/nim-libp2p/libp2p/protocols/ping.nim +++ b/vendor/nim-libp2p/libp2p/protocols/ping.nim @@ -1,15 +1,21 @@ -## Nim-LibP2P -## Copyright (c) 2021 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +## `Ping `_ protocol implementation -import chronos, chronicles, bearssl +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} + +import chronos, chronicles +import bearssl/[rand, hash] import ../protobuf/minprotobuf, ../peerinfo, ../stream/connection, @@ -17,8 +23,11 @@ import ../protobuf/minprotobuf, ../crypto/crypto, ../multiaddress, ../protocols/protocol, + ../utility, ../errors +export chronicles, rand, connection + logScope: topics = "libp2p ping" @@ -28,18 +37,18 @@ const type PingError* = object of LPError - WrongPingAckError* = object of LPError + WrongPingAckError* = object of PingError - PingHandler* = proc ( + PingHandler* {.public.} = proc ( peer: PeerId): Future[void] {.gcsafe, raises: [Defect].} Ping* = ref object of LPProtocol pingHandler*: PingHandler - rng: ref BrHmacDrbgContext + rng: ref HmacDrbgContext -proc new*(T: typedesc[Ping], handler: PingHandler = nil, rng: ref BrHmacDrbgContext = newRng()): T = +proc new*(T: typedesc[Ping], handler: PingHandler = nil, rng: ref HmacDrbgContext = newRng()): T {.public.} = let ping = Ping(pinghandler: handler, rng: rng) ping.init() ping @@ -65,10 +74,8 @@ method init*(p: Ping) = proc ping*( p: Ping, conn: Connection, - ): Future[Duration] {.async, gcsafe.} = - ## Sends ping to `conn` - ## Returns the delay - ## + ): Future[Duration] {.async, gcsafe, public.} = + ## Sends ping to `conn`, returns the delay trace "initiating ping", conn @@ -76,7 +83,7 @@ proc ping*( randomBuf: array[PingSize, byte] resultBuf: array[PingSize, byte] - p.rng[].brHmacDrbgGenerate(randomBuf) + hmacDrbgGenerate(p.rng[], randomBuf) let startTime = Moment.now() diff --git a/vendor/nim-libp2p/libp2p/protocols/protocol.nim b/vendor/nim-libp2p/libp2p/protocols/protocol.nim index aa734f46a..ee3c39a62 100644 --- a/vendor/nim-libp2p/libp2p/protocols/protocol.nim +++ b/vendor/nim-libp2p/libp2p/protocols/protocol.nim @@ -1,13 +1,16 @@ -## Nim-LibP2P -## Copyright (c) 2019 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import chronos import ../stream/connection @@ -22,8 +25,12 @@ type LPProtocol* = ref object of RootObj codecs*: seq[string] handler*: LPProtoHandler ## this handler gets invoked by the protocol negotiator + started*: bool method init*(p: LPProtocol) {.base, gcsafe.} = discard +method start*(p: LPProtocol) {.async, base.} = p.started = true +method stop*(p: LPProtocol) {.async, base.} = p.started = false + func codec*(p: LPProtocol): string = assert(p.codecs.len > 0, "Codecs sequence was empty!") diff --git a/vendor/nim-libp2p/libp2p/protocols/pubsub.nim b/vendor/nim-libp2p/libp2p/protocols/pubsub.nim index c094c682a..ade55b248 100644 --- a/vendor/nim-libp2p/libp2p/protocols/pubsub.nim +++ b/vendor/nim-libp2p/libp2p/protocols/pubsub.nim @@ -1,3 +1,8 @@ import ./pubsub/[pubsub, floodsub, gossipsub] +## Home of PubSub & it's implementations: +## | **pubsub**: base interface for pubsub implementations +## | **floodsub**: simple flood-based publishing +## | **gossipsub**: more sophisticated gossip based publishing + export pubsub, floodsub, gossipsub diff --git a/vendor/nim-libp2p/libp2p/protocols/pubsub/errors.nim b/vendor/nim-libp2p/libp2p/protocols/pubsub/errors.nim index cfb2ccc6d..5c4880455 100644 --- a/vendor/nim-libp2p/libp2p/protocols/pubsub/errors.nim +++ b/vendor/nim-libp2p/libp2p/protocols/pubsub/errors.nim @@ -1,6 +1,8 @@ # this module will be further extended in PR # https://github.com/status-im/nim-libp2p/pull/107/ +import ../../utility + type - ValidationResult* {.pure.} = enum + ValidationResult* {.pure, public.} = enum Accept, Reject, Ignore diff --git a/vendor/nim-libp2p/libp2p/protocols/pubsub/floodsub.nim b/vendor/nim-libp2p/libp2p/protocols/pubsub/floodsub.nim index 7637439a1..0bbf09399 100644 --- a/vendor/nim-libp2p/libp2p/protocols/pubsub/floodsub.nim +++ b/vendor/nim-libp2p/libp2p/protocols/pubsub/floodsub.nim @@ -1,16 +1,19 @@ -## Nim-LibP2P -## Copyright (c) 2019 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/[sequtils, sets, hashes, tables] -import chronos, chronicles, metrics, bearssl +import chronos, chronicles, metrics import ./pubsub, ./pubsubpeer, ./timedcache, @@ -22,31 +25,33 @@ import ./pubsub, ../../peerinfo, ../../utility +## Simple flood-based publishing. + logScope: topics = "libp2p floodsub" const FloodSubCodec* = "/floodsub/1.0.0" type - FloodSub* = ref object of PubSub + FloodSub* {.public.} = ref object of PubSub floodsub*: PeerTable # topic to remote peer map - seen*: TimedCache[MessageID] # message id:s already seen on the network + seen*: TimedCache[MessageId] # message id:s already seen on the network seenSalt*: seq[byte] -proc hasSeen*(f: FloodSub, msgId: MessageID): bool = +proc hasSeen*(f: FloodSub, msgId: MessageId): bool = f.seenSalt & msgId in f.seen -proc addSeen*(f: FloodSub, msgId: MessageID): bool = +proc addSeen*(f: FloodSub, msgId: MessageId): bool = # Salting the seen hash helps avoid attacks against the hash function used # in the nim hash table # Return true if the message has already been seen f.seen.put(f.seenSalt & msgId) -proc firstSeen*(f: FloodSub, msgId: MessageID): Moment = +proc firstSeen*(f: FloodSub, msgId: MessageId): Moment = f.seen.addedAt(f.seenSalt & msgId) proc handleSubscribe*(f: FloodSub, - peer: PubsubPeer, + peer: PubSubPeer, topic: string, subscribe: bool) = logScope: @@ -137,7 +142,7 @@ method rpcHandler*(f: FloodSub, discard var toSendPeers = initHashSet[PubSubPeer]() - for t in msg.topicIDs: # for every topic in the message + for t in msg.topicIds: # for every topic in the message if t notin f.topics: continue f.floodsub.withValue(t, peers): toSendPeers.incl(peers[]) @@ -187,21 +192,17 @@ method publish*(f: FloodSub, debug "No peers for topic, skipping publish", topic return 0 - inc f.msgSeqno let msg = if f.anonymize: Message.init(none(PeerInfo), data, topic, none(uint64), false) else: + inc f.msgSeqno Message.init(some(f.peerInfo), data, topic, some(f.msgSeqno), f.sign) - msgIdResult = f.msgIdProvider(msg) - - if msgIdResult.isErr: - trace "Error generating message id, skipping publish", - error = msgIdResult.error - return 0 - - let msgId = msgIdResult.get + msgId = f.msgIdProvider(msg).valueOr: + trace "Error generating message id, skipping publish", + error = error + return 0 trace "Created new message", msg = shortLog(msg), peers = peers.len, topic, msgId @@ -224,8 +225,8 @@ method publish*(f: FloodSub, method initPubSub*(f: FloodSub) {.raises: [Defect, InitializationError].} = procCall PubSub(f).initPubSub() - f.seen = TimedCache[MessageID].init(2.minutes) + f.seen = TimedCache[MessageId].init(2.minutes) f.seenSalt = newSeqUninitialized[byte](sizeof(Hash)) - brHmacDrbgGenerate(f.rng[], f.seenSalt) + hmacDrbgGenerate(f.rng[], f.seenSalt) f.init() diff --git a/vendor/nim-libp2p/libp2p/protocols/pubsub/gossipsub.nim b/vendor/nim-libp2p/libp2p/protocols/pubsub/gossipsub.nim index 5f94f2f65..fb1873c8c 100644 --- a/vendor/nim-libp2p/libp2p/protocols/pubsub/gossipsub.nim +++ b/vendor/nim-libp2p/libp2p/protocols/pubsub/gossipsub.nim @@ -1,13 +1,18 @@ -## Nim-LibP2P -## Copyright (c) 2019 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +## Gossip based publishing + +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/[tables, sets, options, sequtils] import chronos, chronicles, metrics @@ -156,7 +161,7 @@ method onNewPeer(g: GossipSub, peer: PubSubPeer) = peer.iWantBudget = IWantPeerBudget peer.iHaveBudget = IHavePeerBudget -method onPubSubPeerEvent*(p: GossipSub, peer: PubsubPeer, event: PubSubPeerEvent) {.gcsafe.} = +method onPubSubPeerEvent*(p: GossipSub, peer: PubSubPeer, event: PubSubPeerEvent) {.gcsafe.} = case event.kind of PubSubPeerEventKind.Connected: discard @@ -259,7 +264,7 @@ proc handleControl(g: GossipSub, peer: PubSubPeer, control: ControlMessage) = var respControl: ControlMessage let iwant = g.handleIHave(peer, control.ihave) - if iwant.messageIDs.len > 0: + if iwant.messageIds.len > 0: respControl.iwant.add(iwant) respControl.prune.add(g.handleGraft(peer, control.graft)) let messages = g.handleIWant(peer, control.iwant) @@ -271,7 +276,7 @@ proc handleControl(g: GossipSub, peer: PubSubPeer, control: ControlMessage) = # iwant and prunes from here, also messages for smsg in messages: - for topic in smsg.topicIDs: + for topic in smsg.topicIds: if g.knownTopics.contains(topic): libp2p_pubsub_broadcast_messages.inc(labelValues = [topic]) else: @@ -280,8 +285,8 @@ proc handleControl(g: GossipSub, peer: PubSubPeer, control: ControlMessage) = libp2p_pubsub_broadcast_iwant.inc(respControl.iwant.len.int64) for prune in respControl.prune: - if g.knownTopics.contains(prune.topicID): - libp2p_pubsub_broadcast_prune.inc(labelValues = [prune.topicID]) + if g.knownTopics.contains(prune.topicId): + libp2p_pubsub_broadcast_prune.inc(labelValues = [prune.topicId]) else: libp2p_pubsub_broadcast_prune.inc(labelValues = ["generic"]) @@ -305,7 +310,7 @@ proc validateAndRelay(g: GossipSub, of ValidationResult.Reject: debug "Dropping message after validation, reason: reject", msgId = shortLog(msgId), peer - g.punishInvalidMessage(peer, msg.topicIDs) + g.punishInvalidMessage(peer, msg.topicIds) return of ValidationResult.Ignore: debug "Dropping message after validation, reason: ignore", @@ -317,10 +322,10 @@ proc validateAndRelay(g: GossipSub, # store in cache only after validation g.mcache.put(msgId, msg) - g.rewardDelivered(peer, msg.topicIDs, true) + g.rewardDelivered(peer, msg.topicIds, true) var toSendPeers = HashSet[PubSubPeer]() - for t in msg.topicIDs: # for every topic in the message + for t in msg.topicIds: # for every topic in the message if t notin g.topics: continue @@ -336,7 +341,7 @@ proc validateAndRelay(g: GossipSub, # also have to be careful to only include validated messages g.broadcast(toSendPeers, RPCMsg(messages: @[msg])) trace "forwared message to peers", peers = toSendPeers.len, msgId, peer - for topic in msg.topicIDs: + for topic in msg.topicIds: if topic notin g.topics: continue if g.knownTopics.contains(topic): @@ -390,7 +395,7 @@ method rpcHandler*(g: GossipSub, if not alreadyReceived: let delay = Moment.now() - g.firstSeen(msgId) - g.rewardDelivered(peer, msg.topicIDs, false, delay) + g.rewardDelivered(peer, msg.topicIds, false, delay) libp2p_gossipsub_duplicate.inc() @@ -400,7 +405,7 @@ method rpcHandler*(g: GossipSub, libp2p_gossipsub_received.inc() # avoid processing messages we are not interested in - if msg.topicIDs.allIt(it notin g.topics): + if msg.topicIds.allIt(it notin g.topics): debug "Dropping message of topic without subscription", msgId = shortLog(msgId), peer continue @@ -408,14 +413,14 @@ method rpcHandler*(g: GossipSub, # always validate if signature is present or required debug "Dropping message due to failed signature verification", msgId = shortLog(msgId), peer - g.punishInvalidMessage(peer, msg.topicIDs) + g.punishInvalidMessage(peer, msg.topicIds) continue if msg.seqno.len > 0 and msg.seqno.len != 8: # if we have seqno should be 8 bytes long debug "Dropping message due to invalid seqno length", msgId = shortLog(msgId), peer - g.punishInvalidMessage(peer, msg.topicIDs) + g.punishInvalidMessage(peer, msg.topicIds) continue # g.anonymize needs no evaluation when receiving messages @@ -430,6 +435,13 @@ method rpcHandler*(g: GossipSub, if rpcMsg.control.isSome(): g.handleControl(peer, rpcMsg.control.unsafeGet()) + # Now, check subscription to update the meshes if required + for i in 0.. g.parameters.d: fanoutPeers.setLen(g.parameters.d - peers.len) - + for fanPeer in fanoutPeers: peers.incl(fanPeer) if peers.len > g.parameters.d: break @@ -520,29 +532,25 @@ method publish*(g: GossipSub, if peers.len == 0: let topicPeers = g.gossipsub.getOrDefault(topic).toSeq() - notice "No peers for topic, skipping publish", peersOnTopic = topicPeers.len, - connectedPeers = topicPeers.filterIt(it.connected).len, - topic + debug "No peers for topic, skipping publish", peersOnTopic = topicPeers.len, + connectedPeers = topicPeers.filterIt(it.connected).len, + topic # skipping topic as our metrics finds that heavy libp2p_gossipsub_failed_publish.inc() return 0 - inc g.msgSeqno let msg = if g.anonymize: Message.init(none(PeerInfo), data, topic, none(uint64), false) else: + inc g.msgSeqno Message.init(some(g.peerInfo), data, topic, some(g.msgSeqno), g.sign) - msgIdResult = g.msgIdProvider(msg) - - if msgIdResult.isErr: - trace "Error generating message id, skipping publish", - error = msgIdResult.error - libp2p_gossipsub_failed_publish.inc() - return 0 - - let msgId = msgIdResult.get + msgId = g.msgIdProvider(msg).valueOr: + trace "Error generating message id, skipping publish", + error = error + libp2p_gossipsub_failed_publish.inc() + return 0 logScope: msgId = shortLog(msgId) @@ -566,22 +574,28 @@ method publish*(g: GossipSub, return peers.len +proc maintainDirectPeer(g: GossipSub, id: PeerId, addrs: seq[MultiAddress]) {.async.} = + let peer = g.peers.getOrDefault(id) + if isNil(peer): + trace "Attempting to dial a direct peer", peer = id + try: + await g.switch.connect(id, addrs) + # populate the peer after it's connected + discard g.getOrCreatePeer(id, g.codecs) + except CancelledError as exc: + trace "Direct peer dial canceled" + raise exc + except CatchableError as exc: + debug "Direct peer error dialing", msg = exc.msg + +proc addDirectPeer*(g: GossipSub, id: PeerId, addrs: seq[MultiAddress]) {.async.} = + g.parameters.directPeers[id] = addrs + await g.maintainDirectPeer(id, addrs) + proc maintainDirectPeers(g: GossipSub) {.async.} = heartbeat "GossipSub DirectPeers", 1.minutes: for id, addrs in g.parameters.directPeers: - let peer = g.peers.getOrDefault(id) - if isNil(peer): - trace "Attempting to dial a direct peer", peer = id - try: - # dial, internally connection will be stored - let _ = await g.switch.dial(id, addrs, g.codecs) - # populate the peer after it's connected - discard g.getOrCreatePeer(id, g.codecs) - except CancelledError as exc: - trace "Direct peer dial canceled" - raise exc - except CatchableError as exc: - debug "Direct peer error dialing", msg = exc.msg + await g.addDirectPeer(id, addrs) method start*(g: GossipSub) {.async.} = trace "gossipsub start" @@ -593,9 +607,11 @@ method start*(g: GossipSub) {.async.} = g.heartbeatFut = g.heartbeat() g.scoringHeartbeatFut = g.scoringHeartbeat() g.directPeersLoop = g.maintainDirectPeers() + g.started = true method stop*(g: GossipSub) {.async.} = trace "gossipsub stop" + g.started = false if g.heartbeatFut.isNil: warn "Stopping gossipsub without starting it" return @@ -618,7 +634,7 @@ method initPubSub*(g: GossipSub) raise newException(InitializationError, $validationRes.error) # init the floodsub stuff here, we customize timedcache in gossip! - g.seen = TimedCache[MessageID].init(g.parameters.seenTTL) + g.seen = TimedCache[MessageId].init(g.parameters.seenTTL) # init gossip stuff g.mcache = MCache.init(g.parameters.historyGossip, g.parameters.historyLength) diff --git a/vendor/nim-libp2p/libp2p/protocols/pubsub/gossipsub/behavior.nim b/vendor/nim-libp2p/libp2p/protocols/pubsub/gossipsub/behavior.nim index eda2e8cf9..b3b1f4cad 100644 --- a/vendor/nim-libp2p/libp2p/protocols/pubsub/gossipsub/behavior.nim +++ b/vendor/nim-libp2p/libp2p/protocols/pubsub/gossipsub/behavior.nim @@ -1,13 +1,16 @@ -## Nim-LibP2P -## Copyright (c) 2021 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/[tables, sequtils, sets, algorithm] import chronos, chronicles, metrics @@ -102,7 +105,7 @@ proc handleGraft*(g: GossipSub, grafts: seq[ControlGraft]): seq[ControlPrune] = # {.raises: [Defect].} TODO chronicles exception on windows var prunes: seq[ControlPrune] for graft in grafts: - let topic = graft.topicID + let topic = graft.topicId trace "peer grafted topic", peer, topic # It is an error to GRAFT on a explicit peer @@ -188,7 +191,7 @@ proc getPeers(prune: ControlPrune, peer: PubSubPeer): seq[(PeerId, Option[PeerRe trace "peer sent invalid SPR", peer, error=signedRecord.error none(PeerRecord) else: - if record.peerID != signedRecord.get().data.peerId: + if record.peerId != signedRecord.get().data.peerId: trace "peer sent envelope with wrong public key", peer none(PeerRecord) else: @@ -201,7 +204,7 @@ proc getPeers(prune: ControlPrune, peer: PubSubPeer): seq[(PeerId, Option[PeerRe proc handlePrune*(g: GossipSub, peer: PubSubPeer, prunes: seq[ControlPrune]) {.raises: [Defect].} = for prune in prunes: - let topic = prune.topicID + let topic = prune.topicId trace "peer pruned topic", peer, topic @@ -246,21 +249,21 @@ proc handleIHave*(g: GossipSub, let deIhaves = ihaves.deduplicate() for ihave in deIhaves: trace "peer sent ihave", - peer, topic = ihave.topicID, msgs = ihave.messageIDs - if ihave.topicID in g.mesh: + peer, topic = ihave.topicId, msgs = ihave.messageIds + if ihave.topicId in g.mesh: # also avoid duplicates here! - let deIhavesMsgs = ihave.messageIDs.deduplicate() + let deIhavesMsgs = ihave.messageIds.deduplicate() for msgId in deIhavesMsgs: if not g.hasSeen(msgId): if peer.iHaveBudget > 0: - res.messageIDs.add(msgId) + res.messageIds.add(msgId) dec peer.iHaveBudget trace "requested message via ihave", messageID=msgId else: break # shuffling res.messageIDs before sending it out to increase the likelihood # of getting an answer if the peer truncates the list due to internal size restrictions. - g.rng.shuffle(res.messageIDs) + g.rng.shuffle(res.messageIds) return res proc handleIWant*(g: GossipSub, @@ -274,7 +277,7 @@ proc handleIWant*(g: GossipSub, else: let deIwants = iwants.deduplicate() for iwant in deIwants: - let deIwantsMsgs = iwant.messageIDs.deduplicate() + let deIwantsMsgs = iwant.messageIds.deduplicate() for mid in deIwantsMsgs: trace "peer sent iwant", peer, messageID = mid let msg = g.mcache.get(mid) @@ -323,7 +326,7 @@ proc rebalanceMesh*(g: GossipSub, topic: string, metrics: ptr MeshMetrics = nil) candidates: seq[PubSubPeer] currentMesh = addr defaultMesh g.mesh.withValue(topic, v): currentMesh = v - g.gossipSub.withValue(topic, peerList): + g.gossipsub.withValue(topic, peerList): for it in peerList[]: if it.connected and @@ -361,7 +364,7 @@ proc rebalanceMesh*(g: GossipSub, topic: string, metrics: ptr MeshMetrics = nil) candidates: seq[PubSubPeer] currentMesh = addr defaultMesh g.mesh.withValue(topic, v): currentMesh = v - g.gossipSub.withValue(topic, peerList): + g.gossipsub.withValue(topic, peerList): for it in peerList[]: if it.connected and @@ -466,7 +469,7 @@ proc rebalanceMesh*(g: GossipSub, topic: string, metrics: ptr MeshMetrics = nil) avail: seq[PubSubPeer] currentMesh = addr defaultMesh g.mesh.withValue(topic, v): currentMesh = v - g.gossipSub.withValue(topic, peerList): + g.gossipsub.withValue(topic, peerList): for it in peerList[]: if # avoid negative score peers @@ -611,7 +614,7 @@ proc getGossipPeers*(g: GossipSub): Table[PubSubPeer, ControlMessage] {.raises: allPeers.setLen(target) for peer in allPeers: - control.mGetOrPut(peer, ControlMessage()).ihave.add(ihave) + control.mgetOrPut(peer, ControlMessage()).ihave.add(ihave) libp2p_gossipsub_cache_window_size.set(cacheWindowSize.int64) @@ -667,8 +670,8 @@ proc onHeartbeat(g: GossipSub) {.raises: [Defect].} = for peer, control in peers: # only ihave from here for ihave in control.ihave: - if g.knownTopics.contains(ihave.topicID): - libp2p_pubsub_broadcast_ihave.inc(labelValues = [ihave.topicID]) + if g.knownTopics.contains(ihave.topicId): + libp2p_pubsub_broadcast_ihave.inc(labelValues = [ihave.topicId]) else: libp2p_pubsub_broadcast_ihave.inc(labelValues = ["generic"]) g.send(peer, RPCMsg(control: some(control))) diff --git a/vendor/nim-libp2p/libp2p/protocols/pubsub/gossipsub/scoring.nim b/vendor/nim-libp2p/libp2p/protocols/pubsub/gossipsub/scoring.nim index 872ad0b6b..801134d2f 100644 --- a/vendor/nim-libp2p/libp2p/protocols/pubsub/gossipsub/scoring.nim +++ b/vendor/nim-libp2p/libp2p/protocols/pubsub/gossipsub/scoring.nim @@ -1,13 +1,16 @@ -## Nim-LibP2P -## Copyright (c) 2021 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/[tables, sets, options] import chronos, chronicles, metrics @@ -101,7 +104,6 @@ proc disconnectPeer(g: GossipSub, peer: PubSubPeer) {.async.} = except CatchableError as exc: # Never cancelled trace "Failed to close connection", peer, error = exc.name, msg = exc.msg -{.push raises: [Defect].} proc updateScores*(g: GossipSub) = # avoid async ## https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.1.md#the-score-function diff --git a/vendor/nim-libp2p/libp2p/protocols/pubsub/gossipsub/types.nim b/vendor/nim-libp2p/libp2p/protocols/pubsub/gossipsub/types.nim index 11279eacf..5142aef9c 100644 --- a/vendor/nim-libp2p/libp2p/protocols/pubsub/gossipsub/types.nim +++ b/vendor/nim-libp2p/libp2p/protocols/pubsub/gossipsub/types.nim @@ -1,13 +1,16 @@ -## Nim-LibP2P -## Copyright (c) 2021 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import chronos import std/[tables, sets] @@ -141,7 +144,7 @@ type enablePX*: bool BackoffTable* = Table[string, Table[PeerId, Moment]] - ValidationSeenTable* = Table[MessageID, HashSet[PubSubPeer]] + ValidationSeenTable* = Table[MessageId, HashSet[PubSubPeer]] RoutingRecordsPair* = tuple[id: PeerId, record: Option[PeerRecord]] RoutingRecordsHandler* = diff --git a/vendor/nim-libp2p/libp2p/protocols/pubsub/mcache.nim b/vendor/nim-libp2p/libp2p/protocols/pubsub/mcache.nim index 821fcea85..edb5fe4ad 100644 --- a/vendor/nim-libp2p/libp2p/protocols/pubsub/mcache.nim +++ b/vendor/nim-libp2p/libp2p/protocols/pubsub/mcache.nim @@ -1,13 +1,16 @@ -## Nim-LibP2P -## Copyright (c) 2019 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/[sets, tables, options] import rpc/[messages] @@ -16,36 +19,36 @@ export sets, tables, messages, options type CacheEntry* = object - mid*: MessageID - topicIDs*: seq[string] + mid*: MessageId + topicIds*: seq[string] MCache* = object of RootObj - msgs*: Table[MessageID, Message] + msgs*: Table[MessageId, Message] history*: seq[seq[CacheEntry]] windowSize*: Natural -func get*(c: MCache, mid: MessageID): Option[Message] = +func get*(c: MCache, mid: MessageId): Option[Message] = if mid in c.msgs: try: some(c.msgs[mid]) except KeyError: raiseAssert "checked" else: none(Message) -func contains*(c: MCache, mid: MessageID): bool = +func contains*(c: MCache, mid: MessageId): bool = mid in c.msgs -func put*(c: var MCache, msgId: MessageID, msg: Message) = +func put*(c: var MCache, msgId: MessageId, msg: Message) = if not c.msgs.hasKeyOrPut(msgId, msg): # Only add cache entry if the message was not already in the cache - c.history[0].add(CacheEntry(mid: msgId, topicIDs: msg.topicIDs)) + c.history[0].add(CacheEntry(mid: msgId, topicIds: msg.topicIds)) -func window*(c: MCache, topic: string): HashSet[MessageID] = +func window*(c: MCache, topic: string): HashSet[MessageId] = let len = min(c.windowSize, c.history.len) for i in 0..`_ to a topic, +## `publish<#publish.e%2CPubSub%2Cstring%2Cseq%5Bbyte%5D>`_ something on it, +## and eventually `unsubscribe<#unsubscribe%2CPubSub%2Cstring%2CTopicHandler>`_ from it. + +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/[tables, sequtils, sets, strutils] -import chronos, chronicles, metrics, bearssl +import chronos, chronicles, metrics import ./errors as pubsub_errors, ./pubsubpeer, ./rpc/[message, messages, protobuf], @@ -75,37 +84,40 @@ declarePublicCounter(libp2p_pubsub_received_prune, "pubsub broadcast prune", lab type InitializationError* = object of LPError - TopicHandler* = proc(topic: string, + TopicHandler* {.public.} = proc(topic: string, data: seq[byte]): Future[void] {.gcsafe, raises: [Defect].} - ValidatorHandler* = proc(topic: string, + ValidatorHandler* {.public.} = proc(topic: string, message: Message): Future[ValidationResult] {.gcsafe, raises: [Defect].} TopicPair* = tuple[topic: string, handler: TopicHandler] - MsgIdProvider* = - proc(m: Message): Result[MessageID, ValidationResult] {.noSideEffect, raises: [Defect], gcsafe.} + MsgIdProvider* {.public.} = + proc(m: Message): Result[MessageId, ValidationResult] {.noSideEffect, raises: [Defect], gcsafe.} - SubscriptionValidator* = + SubscriptionValidator* {.public.} = proc(topic: string): bool {.raises: [Defect], gcsafe.} + ## Every time a peer send us a subscription (even to an unknown topic), + ## we have to store it, which may be an attack vector. + ## This callback can be used to reject topic we're not interested in - PubSub* = ref object of LPProtocol + PubSub* {.public.} = ref object of LPProtocol switch*: Switch # the switch used to dial/connect to peers peerInfo*: PeerInfo # this peer's info topics*: Table[string, seq[TopicHandler]] # the topics that _we_ are interested in - peers*: Table[PeerId, PubSubPeer] ##\ - ## Peers that we are interested to gossip with (but not necessarily - ## yet connected to) - triggerSelf*: bool # trigger own local handler on publish - verifySignature*: bool # enable signature verification - sign*: bool # enable message signing + peers*: Table[PeerId, PubSubPeer] #\ + # Peers that we are interested to gossip with (but not necessarily + # yet connected to) + triggerSelf*: bool ## trigger own local handler on publish + verifySignature*: bool ## enable signature verification + sign*: bool ## enable message signing validators*: Table[string, HashSet[ValidatorHandler]] observers: ref seq[PubSubObserver] # ref as in smart_ptr - msgIdProvider*: MsgIdProvider # Turn message into message id (not nil) + msgIdProvider*: MsgIdProvider ## Turn message into message id (not nil) msgSeqno*: uint64 - anonymize*: bool # if we omit fromPeer and seqno from RPC messages we send + anonymize*: bool ## if we omit fromPeer and seqno from RPC messages we send subscriptionValidator*: SubscriptionValidator # callback used to validate subscriptions - topicsHigh*: int # the maximum number of topics a peer is allowed to subscribe to + topicsHigh*: int ## the maximum number of topics a peer is allowed to subscribe to maxMessageSize*: int ##\ ## the maximum raw message size we'll globally allow ## for finer tuning, check message size on topic validator @@ -114,7 +126,7 @@ type ## lead to issues, from descoring to connection drops ## ## defaults to 1mB - rng*: ref BrHmacDrbgContext + rng*: ref HmacDrbgContext knownTopics*: HashSet[string] @@ -154,7 +166,7 @@ proc broadcast*( libp2p_pubsub_broadcast_unsubscriptions.inc(npeers, labelValues = ["generic"]) for smsg in msg.messages: - for topic in smsg.topicIDs: + for topic in smsg.topicIds: if p.knownTopics.contains(topic): libp2p_pubsub_broadcast_messages.inc(npeers, labelValues = [topic]) else: @@ -165,18 +177,18 @@ proc broadcast*( let control = msg.control.get() for ihave in control.ihave: - if p.knownTopics.contains(ihave.topicID): - libp2p_pubsub_broadcast_ihave.inc(npeers, labelValues = [ihave.topicID]) + if p.knownTopics.contains(ihave.topicId): + libp2p_pubsub_broadcast_ihave.inc(npeers, labelValues = [ihave.topicId]) else: libp2p_pubsub_broadcast_ihave.inc(npeers, labelValues = ["generic"]) for graft in control.graft: - if p.knownTopics.contains(graft.topicID): - libp2p_pubsub_broadcast_graft.inc(npeers, labelValues = [graft.topicID]) + if p.knownTopics.contains(graft.topicId): + libp2p_pubsub_broadcast_graft.inc(npeers, labelValues = [graft.topicId]) else: libp2p_pubsub_broadcast_graft.inc(npeers, labelValues = ["generic"]) for prune in control.prune: - if p.knownTopics.contains(prune.topicID): - libp2p_pubsub_broadcast_prune.inc(npeers, labelValues = [prune.topicID]) + if p.knownTopics.contains(prune.topicId): + libp2p_pubsub_broadcast_prune.inc(npeers, labelValues = [prune.topicId]) else: libp2p_pubsub_broadcast_prune.inc(npeers, labelValues = ["generic"]) @@ -227,8 +239,8 @@ proc updateMetrics*(p: PubSub, rpcMsg: RPCMsg) = for i in 0.. 0 and m.fromPeer.data.len > 0: let mid = byteutils.toHex(m.seqno) & $m.fromPeer ok mid.toBytes() diff --git a/vendor/nim-libp2p/libp2p/protocols/pubsub/rpc/messages.nim b/vendor/nim-libp2p/libp2p/protocols/pubsub/rpc/messages.nim index 1ebbf959b..b12f45316 100644 --- a/vendor/nim-libp2p/libp2p/protocols/pubsub/rpc/messages.nim +++ b/vendor/nim-libp2p/libp2p/protocols/pubsub/rpc/messages.nim @@ -1,13 +1,16 @@ -## Nim-LibP2P -## Copyright (c) 2019 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import options, sequtils import "../../.."/[ @@ -27,13 +30,13 @@ type subscribe*: bool topic*: string - MessageID* = seq[byte] + MessageId* = seq[byte] Message* = object fromPeer*: PeerId data*: seq[byte] seqno*: seq[byte] - topicIDs*: seq[string] + topicIds*: seq[string] signature*: seq[byte] key*: seq[byte] @@ -44,17 +47,17 @@ type prune*: seq[ControlPrune] ControlIHave* = object - topicID*: string - messageIDs*: seq[MessageID] + topicId*: string + messageIds*: seq[MessageId] ControlIWant* = object - messageIDs*: seq[MessageID] + messageIds*: seq[MessageId] ControlGraft* = object - topicID*: string + topicId*: string ControlPrune* = object - topicID*: string + topicId*: string peers*: seq[PeerInfoMsg] backoff*: uint64 @@ -70,23 +73,23 @@ func withSubs*( func shortLog*(s: ControlIHave): auto = ( - topicID: s.topicID.shortLog, - messageIDs: mapIt(s.messageIDs, it.shortLog) + topicId: s.topicId.shortLog, + messageIds: mapIt(s.messageIds, it.shortLog) ) func shortLog*(s: ControlIWant): auto = ( - messageIDs: mapIt(s.messageIDs, it.shortLog) + messageIds: mapIt(s.messageIds, it.shortLog) ) func shortLog*(s: ControlGraft): auto = ( - topicID: s.topicID.shortLog + topicId: s.topicId.shortLog ) func shortLog*(s: ControlPrune): auto = ( - topicID: s.topicID.shortLog + topicId: s.topicId.shortLog ) func shortLog*(c: ControlMessage): auto = @@ -102,7 +105,7 @@ func shortLog*(msg: Message): auto = fromPeer: msg.fromPeer.shortLog, data: msg.data.shortLog, seqno: msg.seqno.shortLog, - topicIDs: $msg.topicIDs, + topicIds: $msg.topicIds, signature: msg.signature.shortLog, key: msg.key.shortLog ) diff --git a/vendor/nim-libp2p/libp2p/protocols/pubsub/rpc/protobuf.nim b/vendor/nim-libp2p/libp2p/protocols/pubsub/rpc/protobuf.nim index 28b71a919..1b4cd2268 100644 --- a/vendor/nim-libp2p/libp2p/protocols/pubsub/rpc/protobuf.nim +++ b/vendor/nim-libp2p/libp2p/protocols/pubsub/rpc/protobuf.nim @@ -1,13 +1,16 @@ -## Nim-LibP2P -## Copyright (c) 2019 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import options import stew/assign2 @@ -17,7 +20,6 @@ import messages, ../../../utility, ../../../protobuf/minprotobuf -{.push raises: [Defect].} logScope: topics = "pubsubprotobuf" @@ -30,7 +32,7 @@ when defined(libp2p_protobuf_metrics): proc write*(pb: var ProtoBuffer, field: int, graft: ControlGraft) = var ipb = initProtoBuffer() - ipb.write(1, graft.topicID) + ipb.write(1, graft.topicId) ipb.finish() pb.write(field, ipb) @@ -46,7 +48,7 @@ proc write*(pb: var ProtoBuffer, field: int, infoMsg: PeerInfoMsg) = proc write*(pb: var ProtoBuffer, field: int, prune: ControlPrune) = var ipb = initProtoBuffer() - ipb.write(1, prune.topicID) + ipb.write(1, prune.topicId) for peer in prune.peers: ipb.write(2, peer) ipb.write(3, prune.backoff) @@ -58,8 +60,8 @@ proc write*(pb: var ProtoBuffer, field: int, prune: ControlPrune) = proc write*(pb: var ProtoBuffer, field: int, ihave: ControlIHave) = var ipb = initProtoBuffer() - ipb.write(1, ihave.topicID) - for mid in ihave.messageIDs: + ipb.write(1, ihave.topicId) + for mid in ihave.messageIds: ipb.write(2, mid) ipb.finish() pb.write(field, ipb) @@ -69,7 +71,7 @@ proc write*(pb: var ProtoBuffer, field: int, ihave: ControlIHave) = proc write*(pb: var ProtoBuffer, field: int, iwant: ControlIWant) = var ipb = initProtoBuffer() - for mid in iwant.messageIDs: + for mid in iwant.messageIds: ipb.write(1, mid) if len(ipb.buffer) > 0: ipb.finish() @@ -109,7 +111,7 @@ proc encodeMessage*(msg: Message, anonymize: bool): seq[byte] = pb.write(2, msg.data) if len(msg.seqno) > 0 and not anonymize: pb.write(3, msg.seqno) - for topic in msg.topicIDs: + for topic in msg.topicIds: pb.write(4, topic) if len(msg.signature) > 0 and not anonymize: pb.write(5, msg.signature) @@ -182,8 +184,8 @@ proc decodeIHave*(pb: ProtoBuffer): ProtoResult[ControlIHave] {. trace "decodeIHave: read topicId", topic_id = control.topicId else: trace "decodeIHave: topicId is missing" - if ? pb.getRepeatedField(2, control.messageIDs): - trace "decodeIHave: read messageIDs", message_ids = control.messageIDs + if ? pb.getRepeatedField(2, control.messageIds): + trace "decodeIHave: read messageIDs", message_ids = control.messageIds else: trace "decodeIHave: no messageIDs" ok(control) @@ -194,8 +196,8 @@ proc decodeIWant*(pb: ProtoBuffer): ProtoResult[ControlIWant] {.inline.} = trace "decodeIWant: decoding message" var control = ControlIWant() - if ? pb.getRepeatedField(1, control.messageIDs): - trace "decodeIWant: read messageIDs", message_ids = control.messageIDs + if ? pb.getRepeatedField(1, control.messageIds): + trace "decodeIWant: read messageIDs", message_ids = control.messageIds else: trace "decodeIWant: no messageIDs" ok(control) @@ -281,8 +283,8 @@ proc decodeMessage*(pb: ProtoBuffer): ProtoResult[Message] {.inline.} = trace "decodeMessage: read seqno", seqno = msg.seqno else: trace "decodeMessage: seqno is missing" - if ? pb.getRepeatedField(4, msg.topicIDs): - trace "decodeMessage: read topics", topic_ids = msg.topicIDs + if ? pb.getRepeatedField(4, msg.topicIds): + trace "decodeMessage: read topics", topic_ids = msg.topicIds else: trace "decodeMessage: topics are missing" if ? pb.getField(5, msg.signature): diff --git a/vendor/nim-libp2p/libp2p/protocols/pubsub/timedcache.nim b/vendor/nim-libp2p/libp2p/protocols/pubsub/timedcache.nim index ad47846fa..83bb08c63 100644 --- a/vendor/nim-libp2p/libp2p/protocols/pubsub/timedcache.nim +++ b/vendor/nim-libp2p/libp2p/protocols/pubsub/timedcache.nim @@ -1,13 +1,16 @@ -## Nim-LibP2P -## Copyright (c) 2019 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/[tables] diff --git a/vendor/nim-libp2p/libp2p/protocols/relay.nim b/vendor/nim-libp2p/libp2p/protocols/relay.nim deleted file mode 100644 index acc042b13..000000000 --- a/vendor/nim-libp2p/libp2p/protocols/relay.nim +++ /dev/null @@ -1,488 +0,0 @@ -## Nim-LibP2P -## Copyright (c) 2022 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. - -{.push raises: [Defect].} - -import options -import sequtils, strutils, tables -import chronos, chronicles - -import ../peerinfo, - ../switch, - ../multiaddress, - ../stream/connection, - ../protocols/protocol, - ../transports/transport, - ../utility, - ../errors - -const - RelayCodec* = "/libp2p/circuit/relay/0.1.0" - MsgSize* = 4096 - MaxCircuit* = 1024 - MaxCircuitPerPeer* = 64 - -logScope: - topics = "libp2p relay" - -type - RelayType* = enum - Hop = 1 - Stop = 2 - Status = 3 - CanHop = 4 - RelayStatus* = enum - Success = 100 - HopSrcAddrTooLong = 220 - HopDstAddrTooLong = 221 - HopSrcMultiaddrInvalid = 250 - HopDstMultiaddrInvalid = 251 - HopNoConnToDst = 260 - HopCantDialDst = 261 - HopCantOpenDstStream = 262 - HopCantSpeakRelay = 270 - HopCantRelayToSelf = 280 - StopSrcAddrTooLong = 320 - StopDstAddrTooLong = 321 - StopSrcMultiaddrInvalid = 350 - StopDstMultiaddrInvalid = 351 - StopRelayRefused = 390 - MalformedMessage = 400 - - RelayError* = object of LPError - - RelayPeer* = object - peerId*: PeerID - addrs*: seq[MultiAddress] - - AddConn* = proc(conn: Connection): Future[void] {.gcsafe, raises: [Defect].} - - RelayMessage* = object - msgType*: Option[RelayType] - srcPeer*: Option[RelayPeer] - dstPeer*: Option[RelayPeer] - status*: Option[RelayStatus] - - Relay* = ref object of LPProtocol - switch*: Switch - peerId: PeerID - dialer: Dial - canHop: bool - streamCount: int - hopCount: CountTable[PeerId] - - addConn: AddConn - - maxCircuit*: int - maxCircuitPerPeer*: int - msgSize*: int - -proc encodeMsg*(msg: RelayMessage): ProtoBuffer = - result = initProtoBuffer() - - if isSome(msg.msgType): - result.write(1, msg.msgType.get().ord.uint) - if isSome(msg.srcPeer): - var peer = initProtoBuffer() - peer.write(1, msg.srcPeer.get().peerId) - for ma in msg.srcPeer.get().addrs: - peer.write(2, ma.data.buffer) - peer.finish() - result.write(2, peer.buffer) - if isSome(msg.dstPeer): - var peer = initProtoBuffer() - peer.write(1, msg.dstPeer.get().peerId) - for ma in msg.dstPeer.get().addrs: - peer.write(2, ma.data.buffer) - peer.finish() - result.write(3, peer.buffer) - if isSome(msg.status): - result.write(4, msg.status.get().ord.uint) - - result.finish() - -proc decodeMsg*(buf: seq[byte]): Option[RelayMessage] = - var - rMsg: RelayMessage - msgTypeOrd: uint32 - src: RelayPeer - dst: RelayPeer - statusOrd: uint32 - pbSrc: ProtoBuffer - pbDst: ProtoBuffer - - let - pb = initProtoBuffer(buf) - r1 = pb.getField(1, msgTypeOrd) - r2 = pb.getField(2, pbSrc) - r3 = pb.getField(3, pbDst) - r4 = pb.getField(4, statusOrd) - - if r1.isErr() or r2.isErr() or r3.isErr() or r4.isErr(): - return none(RelayMessage) - - if r2.get() and - (pbSrc.getField(1, src.peerId).isErr() or - pbSrc.getRepeatedField(2, src.addrs).isErr()): - return none(RelayMessage) - - if r3.get() and - (pbDst.getField(1, dst.peerId).isErr() or - pbDst.getRepeatedField(2, dst.addrs).isErr()): - return none(RelayMessage) - - if r1.get(): rMsg.msgType = some(RelayType(msgTypeOrd)) - if r2.get(): rMsg.srcPeer = some(src) - if r3.get(): rMsg.dstPeer = some(dst) - if r4.get(): rMsg.status = some(RelayStatus(statusOrd)) - some(rMsg) - -proc sendStatus*(conn: Connection, code: RelayStatus) {.async, gcsafe.} = - trace "send status", status = $code & "(" & $ord(code) & ")" - let - msg = RelayMessage( - msgType: some(RelayType.Status), - status: some(code)) - pb = encodeMsg(msg) - - await conn.writeLp(pb.buffer) - -proc handleHopStream(r: Relay, conn: Connection, msg: RelayMessage) {.async, gcsafe.} = - r.streamCount.inc() - defer: - r.streamCount.dec() - - if r.streamCount > r.maxCircuit: - trace "refusing connection; too many active circuit" - await sendStatus(conn, RelayStatus.HopCantSpeakRelay) - return - - proc checkMsg(): Result[RelayMessage, RelayStatus] = - if not r.canHop: - return err(RelayStatus.HopCantSpeakRelay) - if msg.srcPeer.isNone: - return err(RelayStatus.HopSrcMultiaddrInvalid) - let src = msg.srcPeer.get() - if src.peerId != conn.peerId: - return err(RelayStatus.HopSrcMultiaddrInvalid) - if msg.dstPeer.isNone: - return err(RelayStatus.HopDstMultiaddrInvalid) - let dst = msg.dstPeer.get() - if dst.peerId == r.switch.peerInfo.peerId: - return err(RelayStatus.HopCantRelayToSelf) - if not r.switch.isConnected(dst.peerId): - trace "relay not connected to dst", dst - return err(RelayStatus.HopNoConnToDst) - ok(msg) - - let check = checkMsg() - if check.isErr: - await sendStatus(conn, check.error()) - return - let - src = msg.srcPeer.get() - dst = msg.dstPeer.get() - - # TODO: if r.acl # access control list - # and not r.acl.AllowHop(src.peerId, dst.peerId) - # sendStatus(conn, RelayStatus.HopCantSpeakRelay) - - r.hopCount.inc(src.peerId) - r.hopCount.inc(dst.peerId) - defer: - r.hopCount.inc(src.peerId, -1) - r.hopCount.inc(dst.peerId, -1) - - if r.hopCount[src.peerId] > r.maxCircuitPerPeer: - trace "refusing connection; too many connection from src", src, dst - await sendStatus(conn, RelayStatus.HopCantSpeakRelay) - return - - if r.hopCount[dst.peerId] > r.maxCircuitPerPeer: - trace "refusing connection; too many connection to dst", src, dst - await sendStatus(conn, RelayStatus.HopCantSpeakRelay) - return - - let connDst = try: - await r.switch.dial(dst.peerId, @[RelayCodec]) - except CancelledError as exc: - raise exc - except CatchableError as exc: - trace "error opening relay stream", dst, exc=exc.msg - await sendStatus(conn, RelayStatus.HopCantDialDst) - return - defer: - await connDst.close() - - let msgToSend = RelayMessage( - msgType: some(RelayType.Stop), - srcPeer: some(src), - dstPeer: some(dst), - status: none(RelayStatus)) - - let msgRcvFromDstOpt = try: - await connDst.writeLp(encodeMsg(msgToSend).buffer) - decodeMsg(await connDst.readLp(r.msgSize)) - except CancelledError as exc: - raise exc - except CatchableError as exc: - trace "error writing stop handshake or reading stop response", exc=exc.msg - await sendStatus(conn, RelayStatus.HopCantOpenDstStream) - return - - if msgRcvFromDstOpt.isNone: - trace "error reading stop response", msg = msgRcvFromDstOpt - await sendStatus(conn, RelayStatus.HopCantOpenDstStream) - return - - let msgRcvFromDst = msgRcvFromDstOpt.get() - if msgRcvFromDst.msgType.isNone or msgRcvFromDst.msgType.get() != RelayType.Status: - trace "unexcepted relay stop response", msgType = msgRcvFromDst.msgType - await sendStatus(conn, RelayStatus.HopCantOpenDstStream) - return - - if msgRcvFromDst.status.isNone or msgRcvFromDst.status.get() != RelayStatus.Success: - trace "relay stop failure", status=msgRcvFromDst.status - await sendStatus(conn, RelayStatus.HopCantOpenDstStream) - return - - await sendStatus(conn, RelayStatus.Success) - - trace "relaying connection", src, dst - - proc bridge(conn: Connection, connDst: Connection) {.async.} = - const bufferSize = 4096 - var - bufSrcToDst: array[bufferSize, byte] - bufDstToSrc: array[bufferSize, byte] - futSrc = conn.readOnce(addr bufSrcToDst[0], bufSrcToDst.high + 1) - futDst = connDst.readOnce(addr bufDstToSrc[0], bufDstToSrc.high + 1) - bytesSendFromSrcToDst = 0 - bytesSendFromDstToSrc = 0 - bufRead: int - - while not conn.closed() and not connDst.closed(): - try: - await futSrc or futDst - if futSrc.finished(): - bufRead = await futSrc - bytesSendFromSrcToDst.inc(bufRead) - await connDst.write(@bufSrcToDst[0..= 3: - result = CircuitRelay.match(sma[^2].get()) and - P2PPattern.match(sma[^1].get()) - trace "Handles return", ma, result - -proc new*(T: typedesc[RelayTransport], relay: Relay, upgrader: Upgrade): T = - result = T(relay: relay, upgrader: upgrader) - result.running = true - result.queue = newAsyncQueue[Connection](0) diff --git a/vendor/nim-libp2p/libp2p/protocols/relay/client.nim b/vendor/nim-libp2p/libp2p/protocols/relay/client.nim new file mode 100644 index 000000000..8f03881ae --- /dev/null +++ b/vendor/nim-libp2p/libp2p/protocols/relay/client.nim @@ -0,0 +1,294 @@ +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. + +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} + +import times, options + +import chronos, chronicles + +import ./relay, + ./messages, + ./rconn, + ./utils, + ../../peerinfo, + ../../switch, + ../../multiaddress, + ../../stream/connection + + +logScope: + topics = "libp2p relay relay-client" + +const RelayClientMsgSize = 4096 + +type + RelayClientError* = object of LPError + ReservationError* = object of RelayClientError + RelayV1DialError* = object of RelayClientError + RelayV2DialError* = object of RelayClientError + RelayClientAddConn* = proc(conn: Connection, + duration: uint32, + data: uint64): Future[void] {.gcsafe, raises: [Defect].} + RelayClient* = ref object of Relay + onNewConnection*: RelayClientAddConn + canHop: bool + + Rsvp* = object + expire*: uint64 # required, Unix expiration time (UTC) + addrs*: seq[MultiAddress] # relay address for reserving peer + voucher*: Option[Voucher] # optional, reservation voucher + limitDuration*: uint32 # seconds + limitData*: uint64 # bytes + +proc sendStopError(conn: Connection, code: StatusV2) {.async.} = + trace "send stop status", status = $code & " (" & $ord(code) & ")" + let msg = StopMessage(msgType: StopMessageType.Status, status: some(code)) + await conn.writeLp(encode(msg).buffer) + +proc handleRelayedConnect(cl: RelayClient, conn: Connection, msg: StopMessage) {.async.} = + if msg.peer.isNone(): + await sendStopError(conn, MalformedMessage) + return + let + # TODO: check the go version to see in which way this could fail + # it's unclear in the spec + src = msg.peer.get() + limitDuration = msg.limit.duration + limitData = msg.limit.data + msg = StopMessage( + msgType: StopMessageType.Status, + status: some(Ok)) + pb = encode(msg) + + trace "incoming relay connection", src + + if cl.onNewConnection == nil: + await sendStopError(conn, StatusV2.ConnectionFailed) + await conn.close() + return + await conn.writeLp(pb.buffer) + # This sound redundant but the callback could, in theory, be set to nil during + # conn.writeLp so it's safer to double check + if cl.onNewConnection != nil: await cl.onNewConnection(conn, limitDuration, limitData) + else: await conn.close() + +proc reserve*(cl: RelayClient, + peerId: PeerId, + addrs: seq[MultiAddress] = @[]): Future[Rsvp] {.async.} = + let conn = await cl.switch.dial(peerId, addrs, RelayV2HopCodec) + defer: await conn.close() + let + pb = encode(HopMessage(msgType: HopMessageType.Reserve)) + msg = try: + await conn.writeLp(pb.buffer) + HopMessage.decode(await conn.readLp(RelayClientMsgSize)).get() + except CancelledError as exc: + raise exc + except CatchableError as exc: + trace "error writing or reading reservation message", exc=exc.msg + raise newException(ReservationError, exc.msg) + + if msg.msgType != HopMessageType.Status: + raise newException(ReservationError, "Unexpected relay response type") + if msg.status.get(UnexpectedMessage) != Ok: + raise newException(ReservationError, "Reservation failed") + if msg.reservation.isNone(): + raise newException(ReservationError, "Missing reservation information") + + let reservation = msg.reservation.get() + if reservation.expire > int64.high().uint64 or + now().utc > reservation.expire.int64.fromUnix.utc: + raise newException(ReservationError, "Bad expiration date") + result.expire = reservation.expire + result.addrs = reservation.addrs + + if reservation.svoucher.isSome(): + let svoucher = SignedVoucher.decode(reservation.svoucher.get()) + if svoucher.isErr() or svoucher.get().data.relayPeerId != peerId: + raise newException(ReservationError, "Invalid voucher") + result.voucher = some(svoucher.get().data) + + result.limitDuration = msg.limit.duration + result.limitData = msg.limit.data + +proc dialPeerV1*( + cl: RelayClient, + conn: Connection, + dstPeerId: PeerId, + dstAddrs: seq[MultiAddress]): Future[Connection] {.async.} = + var + msg = RelayMessage( + msgType: some(RelayType.Hop), + srcPeer: some(RelayPeer(peerId: cl.switch.peerInfo.peerId, addrs: cl.switch.peerInfo.addrs)), + dstPeer: some(RelayPeer(peerId: dstPeerId, addrs: dstAddrs))) + pb = encode(msg) + + trace "Dial peer", msgSend=msg + + try: + await conn.writeLp(pb.buffer) + except CancelledError as exc: + raise exc + except CatchableError as exc: + trace "error writing hop request", exc=exc.msg + raise exc + + let msgRcvFromRelayOpt = try: + RelayMessage.decode(await conn.readLp(RelayClientMsgSize)) + except CancelledError as exc: + raise exc + except CatchableError as exc: + trace "error reading stop response", exc=exc.msg + await sendStatus(conn, StatusV1.HopCantOpenDstStream) + raise exc + + try: + if msgRcvFromRelayOpt.isNone: + raise newException(RelayV1DialError, "Hop can't open destination stream") + let msgRcvFromRelay = msgRcvFromRelayOpt.get() + if msgRcvFromRelay.msgType.isNone or msgRcvFromRelay.msgType.get() != RelayType.Status: + raise newException(RelayV1DialError, "Hop can't open destination stream: wrong message type") + if msgRcvFromRelay.status.isNone or msgRcvFromRelay.status.get() != StatusV1.Success: + raise newException(RelayV1DialError, "Hop can't open destination stream: status failed") + except RelayV1DialError as exc: + await sendStatus(conn, StatusV1.HopCantOpenDstStream) + raise exc + result = conn + +proc dialPeerV2*( + cl: RelayClient, + conn: RelayConnection, + dstPeerId: PeerId, + dstAddrs: seq[MultiAddress]): Future[Connection] {.async.} = + let + p = Peer(peerId: dstPeerId, addrs: dstAddrs) + pb = encode(HopMessage(msgType: HopMessageType.Connect, peer: some(p))) + + trace "Dial peer", p + + let msgRcvFromRelay = try: + await conn.writeLp(pb.buffer) + HopMessage.decode(await conn.readLp(RelayClientMsgSize)).get() + except CancelledError as exc: + raise exc + except CatchableError as exc: + trace "error reading stop response", exc=exc.msg + raise newException(RelayV2DialError, exc.msg) + + if msgRcvFromRelay.msgType != HopMessageType.Status: + raise newException(RelayV2DialError, "Unexpected stop response") + if msgRcvFromRelay.status.get(UnexpectedMessage) != Ok: + trace "Relay stop failed", msg = msgRcvFromRelay.status.get() + raise newException(RelayV2DialError, "Relay stop failure") + conn.limitDuration = msgRcvFromRelay.limit.duration + conn.limitData = msgRcvFromRelay.limit.data + return conn + +proc handleStopStreamV2(cl: RelayClient, conn: Connection) {.async, gcsafe.} = + let msgOpt = StopMessage.decode(await conn.readLp(RelayClientMsgSize)) + if msgOpt.isNone(): + await sendHopStatus(conn, MalformedMessage) + return + trace "client circuit relay v2 handle stream", msg = msgOpt.get() + let msg = msgOpt.get() + + if msg.msgType == StopMessageType.Connect: + await cl.handleRelayedConnect(conn, msg) + else: + trace "Unexpected client / relayv2 handshake", msgType=msg.msgType + await sendStopError(conn, MalformedMessage) + +proc handleStop(cl: RelayClient, conn: Connection, msg: RelayMessage) {.async, gcsafe.} = + if msg.srcPeer.isNone: + await sendStatus(conn, StatusV1.StopSrcMultiaddrInvalid) + return + let src = msg.srcPeer.get() + + if msg.dstPeer.isNone: + await sendStatus(conn, StatusV1.StopDstMultiaddrInvalid) + return + + let dst = msg.dstPeer.get() + if dst.peerId != cl.switch.peerInfo.peerId: + await sendStatus(conn, StatusV1.StopDstMultiaddrInvalid) + return + + trace "get a relay connection", src, conn + + if cl.onNewConnection == nil: + await sendStatus(conn, StatusV1.StopRelayRefused) + await conn.close() + return + await sendStatus(conn, StatusV1.Success) + # This sound redundant but the callback could, in theory, be set to nil during + # sendStatus(Success) so it's safer to double check + if cl.onNewConnection != nil: await cl.onNewConnection(conn, 0, 0) + else: await conn.close() + +proc handleStreamV1(cl: RelayClient, conn: Connection) {.async, gcsafe.} = + let msgOpt = RelayMessage.decode(await conn.readLp(RelayClientMsgSize)) + if msgOpt.isNone: + await sendStatus(conn, StatusV1.MalformedMessage) + return + trace "client circuit relay v1 handle stream", msg = msgOpt.get() + let msg = msgOpt.get() + case msg.msgType.get: + of RelayType.Hop: + if cl.canHop: await cl.handleHop(conn, msg) + else: await sendStatus(conn, StatusV1.HopCantSpeakRelay) + of RelayType.Stop: await cl.handleStop(conn, msg) + of RelayType.CanHop: + if cl.canHop: await sendStatus(conn, StatusV1.Success) + else: await sendStatus(conn, StatusV1.HopCantSpeakRelay) + else: + trace "Unexpected relay handshake", msgType=msg.msgType + await sendStatus(conn, StatusV1.MalformedMessage) + +proc new*(T: typedesc[RelayClient], canHop: bool = false, + reservationTTL: times.Duration = DefaultReservationTTL, + limitDuration: uint32 = DefaultLimitDuration, + limitData: uint64 = DefaultLimitData, + heartbeatSleepTime: uint32 = DefaultHeartbeatSleepTime, + maxCircuit: int = MaxCircuit, + maxCircuitPerPeer: int = MaxCircuitPerPeer, + msgSize: int = RelayClientMsgSize, + circuitRelayV1: bool = false): T = + + let cl = T(canHop: canHop, + reservationTTL: reservationTTL, + limit: Limit(duration: limitDuration, data: limitData), + heartbeatSleepTime: heartbeatSleepTime, + maxCircuit: maxCircuit, + maxCircuitPerPeer: maxCircuitPerPeer, + msgSize: msgSize, + isCircuitRelayV1: circuitRelayV1) + proc handleStream(conn: Connection, proto: string) {.async, gcsafe.} = + try: + case proto: + of RelayV1Codec: await cl.handleStreamV1(conn) + of RelayV2StopCodec: await cl.handleStopStreamV2(conn) + of RelayV2HopCodec: await cl.handleHopStreamV2(conn) + except CancelledError as exc: + raise exc + except CatchableError as exc: + trace "exception in client handler", exc = exc.msg, conn + finally: + trace "exiting client handler", conn + await conn.close() + + cl.handler = handleStream + cl.codecs = if cl.canHop: + @[RelayV1Codec, RelayV2HopCodec, RelayV2StopCodec] + else: + @[RelayV1Codec, RelayV2StopCodec] + cl diff --git a/vendor/nim-libp2p/libp2p/protocols/relay/messages.nim b/vendor/nim-libp2p/libp2p/protocols/relay/messages.nim new file mode 100644 index 000000000..62e2aaa0f --- /dev/null +++ b/vendor/nim-libp2p/libp2p/protocols/relay/messages.nim @@ -0,0 +1,370 @@ +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. + +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} + +import options, macros, sequtils +import stew/objects +import ../../peerinfo, + ../../signed_envelope + +# Circuit Relay V1 Message + +type + RelayType* {.pure.} = enum + Hop = 1 + Stop = 2 + Status = 3 + CanHop = 4 + + StatusV1* {.pure.} = enum + Success = 100 + HopSrcAddrTooLong = 220 + HopDstAddrTooLong = 221 + HopSrcMultiaddrInvalid = 250 + HopDstMultiaddrInvalid = 251 + HopNoConnToDst = 260 + HopCantDialDst = 261 + HopCantOpenDstStream = 262 + HopCantSpeakRelay = 270 + HopCantRelayToSelf = 280 + StopSrcAddrTooLong = 320 + StopDstAddrTooLong = 321 + StopSrcMultiaddrInvalid = 350 + StopDstMultiaddrInvalid = 351 + StopRelayRefused = 390 + MalformedMessage = 400 + + RelayPeer* = object + peerId*: PeerId + addrs*: seq[MultiAddress] + + RelayMessage* = object + msgType*: Option[RelayType] + srcPeer*: Option[RelayPeer] + dstPeer*: Option[RelayPeer] + status*: Option[StatusV1] + +proc encode*(msg: RelayMessage): ProtoBuffer = + result = initProtoBuffer() + + if isSome(msg.msgType): + result.write(1, msg.msgType.get().ord.uint) + if isSome(msg.srcPeer): + var peer = initProtoBuffer() + peer.write(1, msg.srcPeer.get().peerId) + for ma in msg.srcPeer.get().addrs: + peer.write(2, ma.data.buffer) + peer.finish() + result.write(2, peer.buffer) + if isSome(msg.dstPeer): + var peer = initProtoBuffer() + peer.write(1, msg.dstPeer.get().peerId) + for ma in msg.dstPeer.get().addrs: + peer.write(2, ma.data.buffer) + peer.finish() + result.write(3, peer.buffer) + if isSome(msg.status): + result.write(4, msg.status.get().ord.uint) + + result.finish() + +proc decode*(_: typedesc[RelayMessage], buf: seq[byte]): Option[RelayMessage] = + var + rMsg: RelayMessage + msgTypeOrd: uint32 + src: RelayPeer + dst: RelayPeer + statusOrd: uint32 + pbSrc: ProtoBuffer + pbDst: ProtoBuffer + + let + pb = initProtoBuffer(buf) + r1 = pb.getField(1, msgTypeOrd) + r2 = pb.getField(2, pbSrc) + r3 = pb.getField(3, pbDst) + r4 = pb.getField(4, statusOrd) + + if r1.isErr() or r2.isErr() or r3.isErr() or r4.isErr(): + return none(RelayMessage) + + if r2.get() and + (pbSrc.getField(1, src.peerId).isErr() or + pbSrc.getRepeatedField(2, src.addrs).isErr()): + return none(RelayMessage) + + if r3.get() and + (pbDst.getField(1, dst.peerId).isErr() or + pbDst.getRepeatedField(2, dst.addrs).isErr()): + return none(RelayMessage) + + if r1.get(): + if msgTypeOrd.int notin RelayType: + return none(RelayMessage) + rMsg.msgType = some(RelayType(msgTypeOrd)) + if r2.get(): rMsg.srcPeer = some(src) + if r3.get(): rMsg.dstPeer = some(dst) + if r4.get(): + if statusOrd.int notin StatusV1: + return none(RelayMessage) + rMsg.status = some(StatusV1(statusOrd)) + some(rMsg) + +# Voucher + +type + Voucher* = object + relayPeerId*: PeerId # peer ID of the relay + reservingPeerId*: PeerId # peer ID of the reserving peer + expiration*: uint64 # UNIX UTC expiration time for the reservation + +proc decode*(_: typedesc[Voucher], buf: seq[byte]): Result[Voucher, ProtoError] = + let pb = initProtoBuffer(buf) + var v = Voucher() + + ? pb.getRequiredField(1, v.relayPeerId) + ? pb.getRequiredField(2, v.reservingPeerId) + ? pb.getRequiredField(3, v.expiration) + + ok(v) + +proc encode*(v: Voucher): seq[byte] = + var pb = initProtoBuffer() + + pb.write(1, v.relayPeerId) + pb.write(2, v.reservingPeerId) + pb.write(3, v.expiration) + + pb.finish() + pb.buffer + +proc init*(T: typedesc[Voucher], + relayPeerId: PeerId, + reservingPeerId: PeerId, + expiration: uint64): T = + T( + relayPeerId = relayPeerId, + reservingPeerId = reservingPeerId, + expiration: expiration + ) + +type SignedVoucher* = SignedPayload[Voucher] + +proc payloadDomain*(_: typedesc[Voucher]): string = "libp2p-relay-rsvp" +proc payloadType*(_: typedesc[Voucher]): seq[byte] = @[ (byte)0x03, (byte)0x02 ] + +proc checkValid*(spr: SignedVoucher): Result[void, EnvelopeError] = + if not spr.data.relayPeerId.match(spr.envelope.publicKey): + err(EnvelopeInvalidSignature) + else: + ok() + +# Circuit Relay V2 Hop Message + +type + Peer* = object + peerId*: PeerId + addrs*: seq[MultiAddress] + Reservation* = object + expire*: uint64 # required, Unix expiration time (UTC) + addrs*: seq[MultiAddress] # relay address for reserving peer + svoucher*: Option[seq[byte]] # optional, reservation voucher + Limit* = object + duration*: uint32 # seconds + data*: uint64 # bytes + + StatusV2* = enum + Ok = 100 + ReservationRefused = 200 + ResourceLimitExceeded = 201 + PermissionDenied = 202 + ConnectionFailed = 203 + NoReservation = 204 + MalformedMessage = 400 + UnexpectedMessage = 401 + HopMessageType* {.pure.} = enum + Reserve = 0 + Connect = 1 + Status = 2 + HopMessage* = object + msgType*: HopMessageType + peer*: Option[Peer] + reservation*: Option[Reservation] + limit*: Limit + status*: Option[StatusV2] + +proc encode*(msg: HopMessage): ProtoBuffer = + var pb = initProtoBuffer() + + pb.write(1, msg.msgType.ord.uint) + if msg.peer.isSome(): + var ppb = initProtoBuffer() + ppb.write(1, msg.peer.get().peerId) + for ma in msg.peer.get().addrs: + ppb.write(2, ma.data.buffer) + ppb.finish() + pb.write(2, ppb.buffer) + if msg.reservation.isSome(): + let rsrv = msg.reservation.get() + var rpb = initProtoBuffer() + rpb.write(1, rsrv.expire) + for ma in rsrv.addrs: + rpb.write(2, ma.data.buffer) + if rsrv.svoucher.isSome(): + rpb.write(3, rsrv.svoucher.get()) + rpb.finish() + pb.write(3, rpb.buffer) + if msg.limit.duration > 0 or msg.limit.data > 0: + var lpb = initProtoBuffer() + if msg.limit.duration > 0: lpb.write(1, msg.limit.duration) + if msg.limit.data > 0: lpb.write(2, msg.limit.data) + lpb.finish() + pb.write(4, lpb.buffer) + if msg.status.isSome(): + pb.write(5, msg.status.get().ord.uint) + + pb.finish() + pb + +proc decode*(_: typedesc[HopMessage], buf: seq[byte]): Option[HopMessage] = + var + msg: HopMessage + msgTypeOrd: uint32 + pbPeer: ProtoBuffer + pbReservation: ProtoBuffer + pbLimit: ProtoBuffer + statusOrd: uint32 + peer: Peer + reservation: Reservation + limit: Limit + res: bool + + let + pb = initProtoBuffer(buf) + r1 = pb.getRequiredField(1, msgTypeOrd) + r2 = pb.getField(2, pbPeer) + r3 = pb.getField(3, pbReservation) + r4 = pb.getField(4, pbLimit) + r5 = pb.getField(5, statusOrd) + + if r1.isErr() or r2.isErr() or r3.isErr() or r4.isErr() or r5.isErr(): + return none(HopMessage) + + if r2.get() and + (pbPeer.getRequiredField(1, peer.peerId).isErr() or + pbPeer.getRepeatedField(2, peer.addrs).isErr()): + return none(HopMessage) + + if r3.get(): + var svoucher: seq[byte] + let rSVoucher = pbReservation.getField(3, svoucher) + if pbReservation.getRequiredField(1, reservation.expire).isErr() or + pbReservation.getRepeatedField(2, reservation.addrs).isErr() or + rSVoucher.isErr(): + return none(HopMessage) + if rSVoucher.get(): reservation.svoucher = some(svoucher) + + if r4.get() and + (pbLimit.getField(1, limit.duration).isErr() or + pbLimit.getField(2, limit.data).isErr()): + return none(HopMessage) + + if not checkedEnumAssign(msg.msgType, msgTypeOrd): + return none(HopMessage) + if r2.get(): msg.peer = some(peer) + if r3.get(): msg.reservation = some(reservation) + if r4.get(): msg.limit = limit + if r5.get(): + if statusOrd.int notin StatusV2: + return none(HopMessage) + msg.status = some(StatusV2(statusOrd)) + some(msg) + +# Circuit Relay V2 Stop Message + +type + StopMessageType* {.pure.} = enum + Connect = 0 + Status = 1 + StopMessage* = object + msgType*: StopMessageType + peer*: Option[Peer] + limit*: Limit + status*: Option[StatusV2] + + +proc encode*(msg: StopMessage): ProtoBuffer = + var pb = initProtoBuffer() + + pb.write(1, msg.msgType.ord.uint) + if msg.peer.isSome(): + var ppb = initProtoBuffer() + ppb.write(1, msg.peer.get().peerId) + for ma in msg.peer.get().addrs: + ppb.write(2, ma.data.buffer) + ppb.finish() + pb.write(2, ppb.buffer) + if msg.limit.duration > 0 or msg.limit.data > 0: + var lpb = initProtoBuffer() + if msg.limit.duration > 0: lpb.write(1, msg.limit.duration) + if msg.limit.data > 0: lpb.write(2, msg.limit.data) + lpb.finish() + pb.write(3, lpb.buffer) + if msg.status.isSome(): + pb.write(4, msg.status.get().ord.uint) + + pb.finish() + pb + +proc decode*(_: typedesc[StopMessage], buf: seq[byte]): Option[StopMessage] = + var + msg: StopMessage + msgTypeOrd: uint32 + pbPeer: ProtoBuffer + pbLimit: ProtoBuffer + statusOrd: uint32 + peer: Peer + limit: Limit + rVoucher: ProtoResult[bool] + res: bool + + let + pb = initProtoBuffer(buf) + r1 = pb.getRequiredField(1, msgTypeOrd) + r2 = pb.getField(2, pbPeer) + r3 = pb.getField(3, pbLimit) + r4 = pb.getField(4, statusOrd) + + if r1.isErr() or r2.isErr() or r3.isErr() or r4.isErr(): + return none(StopMessage) + + if r2.get() and + (pbPeer.getRequiredField(1, peer.peerId).isErr() or + pbPeer.getRepeatedField(2, peer.addrs).isErr()): + return none(StopMessage) + + if r3.get() and + (pbLimit.getField(1, limit.duration).isErr() or + pbLimit.getField(2, limit.data).isErr()): + return none(StopMessage) + + if msgTypeOrd.int notin StopMessageType.low.ord .. StopMessageType.high.ord: + return none(StopMessage) + msg.msgType = StopMessageType(msgTypeOrd) + if r2.get(): msg.peer = some(peer) + if r3.get(): msg.limit = limit + if r4.get(): + if statusOrd.int notin StatusV2: + return none(StopMessage) + msg.status = some(StatusV2(statusOrd)) + some(msg) diff --git a/vendor/nim-libp2p/libp2p/protocols/relay/rconn.nim b/vendor/nim-libp2p/libp2p/protocols/relay/rconn.nim new file mode 100644 index 000000000..44dbb1445 --- /dev/null +++ b/vendor/nim-libp2p/libp2p/protocols/relay/rconn.nim @@ -0,0 +1,61 @@ +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. + +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} + +import chronos + +import ../../stream/connection + +type + RelayConnection* = ref object of Connection + conn*: Connection + limitDuration*: uint32 + limitData*: uint64 + dataSent*: uint64 + +method readOnce*( + self: RelayConnection, + pbytes: pointer, + nbytes: int): Future[int] {.async.} = + self.activity = true + return await self.conn.readOnce(pbytes, nbytes) + +method write*(self: RelayConnection, msg: seq[byte]): Future[void] {.async.} = + self.dataSent.inc(msg.len) + if self.limitData != 0 and self.dataSent > self.limitData: + await self.close() + return + self.activity = true + await self.conn.write(msg) + +method closeImpl*(self: RelayConnection): Future[void] {.async.} = + await self.conn.close() + await procCall Connection(self).closeImpl() + +method getWrapped*(self: RelayConnection): Connection = self.conn + +proc new*( + T: typedesc[RelayConnection], + conn: Connection, + limitDuration: uint32, + limitData: uint64): T = + let rc = T(conn: conn, limitDuration: limitDuration, limitData: limitData) + rc.initStream() + if limitDuration > 0: + proc checkDurationConnection() {.async.} = + let sleep = sleepAsync(limitDuration.seconds()) + await sleep or conn.join() + if sleep.finished: await conn.close() + else: sleep.cancel() + asyncSpawn checkDurationConnection() + return rc diff --git a/vendor/nim-libp2p/libp2p/protocols/relay/relay.nim b/vendor/nim-libp2p/libp2p/protocols/relay/relay.nim new file mode 100644 index 000000000..10288eb34 --- /dev/null +++ b/vendor/nim-libp2p/libp2p/protocols/relay/relay.nim @@ -0,0 +1,386 @@ +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. + +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} + +import options, sequtils, tables, sugar + +import chronos, chronicles + +import ./messages, + ./rconn, + ./utils, + ../../peerinfo, + ../../switch, + ../../multiaddress, + ../../multicodec, + ../../stream/connection, + ../../protocols/protocol, + ../../transports/transport, + ../../errors, + ../../utils/heartbeat, + ../../signed_envelope + +# TODO: +# * Eventually replace std/times by chronos/timer. Currently chronos/timer +# doesn't offer the possibility to get a datetime in UNIX UTC +# * Eventually add an access control list in the handleReserve, handleConnect +# and handleHop +# * Better reservation management ie find a way to re-reserve when the end is nigh + +import std/times +export chronicles + +const + RelayMsgSize* = 4096 + DefaultReservationTTL* = initDuration(hours = 1) + DefaultLimitDuration* = 120 + DefaultLimitData* = 1 shl 17 + DefaultHeartbeatSleepTime* = 1 + MaxCircuit* = 128 + MaxCircuitPerPeer* = 16 + +logScope: + topics = "libp2p relay" + +type + RelayV2Error* = object of LPError + SendStopError = object of RelayV2Error + +# Relay Side + +type + Relay* = ref object of LPProtocol + switch*: Switch + peerCount: CountTable[PeerId] + + # number of reservation (relayv2) + number of connection (relayv1) + maxCircuit*: int + + maxCircuitPerPeer*: int + msgSize*: int + # RelayV1 + isCircuitRelayV1*: bool + streamCount: int + # RelayV2 + rsvp: Table[PeerId, DateTime] + reservationLoop: Future[void] + reservationTTL*: times.Duration + heartbeatSleepTime*: uint32 + limit*: Limit + +# Relay V2 + +proc createReserveResponse( + r: Relay, + pid: PeerId, + expire: DateTime): Result[HopMessage, CryptoError] = + let + expireUnix = expire.toTime.toUnix.uint64 + v = Voucher(relayPeerId: r.switch.peerInfo.peerId, + reservingPeerId: pid, + expiration: expireUnix) + sv = ? SignedVoucher.init(r.switch.peerInfo.privateKey, v) + ma = ? MultiAddress.init("/p2p/" & $r.switch.peerInfo.peerId).orErr(CryptoError.KeyError) + rsrv = Reservation(expire: expireUnix, + addrs: r.switch.peerInfo.addrs.mapIt( + ? it.concat(ma).orErr(CryptoError.KeyError)), + svoucher: some(? sv.encode)) + msg = HopMessage(msgType: HopMessageType.Status, + reservation: some(rsrv), + limit: r.limit, + status: some(Ok)) + return ok(msg) + +proc isRelayed(conn: Connection): bool = + var wrappedConn = conn + while not isNil(wrappedConn): + if wrappedConn of RelayConnection: + return true + wrappedConn = wrappedConn.getWrapped() + return false + +proc handleReserve(r: Relay, conn: Connection) {.async, gcsafe.} = + if conn.isRelayed(): + trace "reservation attempt over relay connection", pid = conn.peerId + await sendHopStatus(conn, PermissionDenied) + return + + if r.peerCount[conn.peerId] + r.rsvp.len() >= r.maxCircuit: + trace "Too many reservations", pid = conn.peerId + await sendHopStatus(conn, ReservationRefused) + return + let + pid = conn.peerId + expire = now().utc + r.reservationTTL + msg = r.createReserveResponse(pid, expire) + + trace "reserving relay slot for", pid + if msg.isErr(): + trace "error signing the voucher", error = error(msg), pid + return + r.rsvp[pid] = expire + await conn.writeLp(encode(msg.get()).buffer) + +proc handleConnect(r: Relay, + connSrc: Connection, + msg: HopMessage) {.async, gcsafe.} = + if connSrc.isRelayed(): + trace "connection attempt over relay connection" + await sendHopStatus(connSrc, PermissionDenied) + return + if msg.peer.isNone(): + await sendHopStatus(connSrc, MalformedMessage) + return + + let + src = connSrc.peerId + dst = msg.peer.get().peerId + if dst notin r.rsvp: + trace "refusing connection, no reservation", src, dst + await sendHopStatus(connSrc, NoReservation) + return + + r.peerCount.inc(src) + r.peerCount.inc(dst) + defer: + r.peerCount.inc(src, -1) + r.peerCount.inc(dst, -1) + + if r.peerCount[src] > r.maxCircuitPerPeer or + r.peerCount[dst] > r.maxCircuitPerPeer: + trace "too many connections", src = r.peerCount[src], + dst = r.peerCount[dst], + max = r.maxCircuitPerPeer + await sendHopStatus(connSrc, ResourceLimitExceeded) + return + + let connDst = try: + await r.switch.dial(dst, RelayV2StopCodec) + except CancelledError as exc: + raise exc + except CatchableError as exc: + trace "error opening relay stream", dst, exc=exc.msg + await sendHopStatus(connSrc, ConnectionFailed) + return + defer: + await connDst.close() + + proc sendStopMsg() {.async.} = + let stopMsg = StopMessage(msgType: StopMessageType.Connect, + peer: some(Peer(peerId: src, addrs: @[])), + limit: r.limit) + await connDst.writeLp(encode(stopMsg).buffer) + let msg = StopMessage.decode(await connDst.readLp(r.msgSize)).get() + if msg.msgType != StopMessageType.Status: + raise newException(SendStopError, "Unexpected stop response, not a status message") + if msg.status.get(UnexpectedMessage) != Ok: + raise newException(SendStopError, "Relay stop failure") + await connSrc.writeLp(encode(HopMessage(msgType: HopMessageType.Status, + status: some(Ok))).buffer) + try: + await sendStopMsg() + except CancelledError as exc: + raise exc + except CatchableError as exc: + trace "error sending stop message", msg = exc.msg + await sendHopStatus(connSrc, ConnectionFailed) + return + + trace "relaying connection", src, dst + let + rconnSrc = RelayConnection.new(connSrc, r.limit.duration, r.limit.data) + rconnDst = RelayConnection.new(connDst, r.limit.duration, r.limit.data) + defer: + await rconnSrc.close() + await rconnDst.close() + await bridge(rconnSrc, rconnDst) + +proc handleHopStreamV2*(r: Relay, conn: Connection) {.async, gcsafe.} = + let msgOpt = HopMessage.decode(await conn.readLp(r.msgSize)) + if msgOpt.isNone(): + await sendHopStatus(conn, MalformedMessage) + return + trace "relayv2 handle stream", msg = msgOpt.get() + let msg = msgOpt.get() + case msg.msgType: + of HopMessageType.Reserve: await r.handleReserve(conn) + of HopMessageType.Connect: await r.handleConnect(conn, msg) + else: + trace "Unexpected relayv2 handshake", msgType=msg.msgType + await sendHopStatus(conn, MalformedMessage) + +# Relay V1 + +proc handleHop*(r: Relay, connSrc: Connection, msg: RelayMessage) {.async, gcsafe.} = + r.streamCount.inc() + defer: r.streamCount.dec() + if r.streamCount + r.rsvp.len() >= r.maxCircuit: + trace "refusing connection; too many active circuit", streamCount = r.streamCount, rsvp = r.rsvp.len() + await sendStatus(connSrc, StatusV1.HopCantSpeakRelay) + return + + proc checkMsg(): Result[RelayMessage, StatusV1] = + if msg.srcPeer.isNone: + return err(StatusV1.HopSrcMultiaddrInvalid) + let src = msg.srcPeer.get() + if src.peerId != connSrc.peerId: + return err(StatusV1.HopSrcMultiaddrInvalid) + if msg.dstPeer.isNone: + return err(StatusV1.HopDstMultiaddrInvalid) + let dst = msg.dstPeer.get() + if dst.peerId == r.switch.peerInfo.peerId: + return err(StatusV1.HopCantRelayToSelf) + if not r.switch.isConnected(dst.peerId): + trace "relay not connected to dst", dst + return err(StatusV1.HopNoConnToDst) + ok(msg) + let check = checkMsg() + if check.isErr: + await sendStatus(connSrc, check.error()) + return + + let + src = msg.srcPeer.get() + dst = msg.dstPeer.get() + if r.peerCount[src.peerId] >= r.maxCircuitPerPeer or + r.peerCount[dst.peerId] >= r.maxCircuitPerPeer: + trace "refusing connection; too many connection from src or to dst", src, dst + await sendStatus(connSrc, StatusV1.HopCantSpeakRelay) + return + r.peerCount.inc(src.peerId) + r.peerCount.inc(dst.peerId) + defer: + r.peerCount.inc(src.peerId, -1) + r.peerCount.inc(dst.peerId, -1) + + let connDst = try: + await r.switch.dial(dst.peerId, RelayV1Codec) + except CancelledError as exc: + raise exc + except CatchableError as exc: + trace "error opening relay stream", dst, exc=exc.msg + await sendStatus(connSrc, StatusV1.HopCantDialDst) + return + defer: + await connDst.close() + + let msgToSend = RelayMessage( + msgType: some(RelayType.Stop), + srcPeer: some(src), + dstPeer: some(dst)) + + let msgRcvFromDstOpt = try: + await connDst.writeLp(encode(msgToSend).buffer) + RelayMessage.decode(await connDst.readLp(r.msgSize)) + except CancelledError as exc: + raise exc + except CatchableError as exc: + trace "error writing stop handshake or reading stop response", exc=exc.msg + await sendStatus(connSrc, StatusV1.HopCantOpenDstStream) + return + + if msgRcvFromDstOpt.isNone: + trace "error reading stop response", msg = msgRcvFromDstOpt + await sendStatus(connSrc, StatusV1.HopCantOpenDstStream) + return + + let msgRcvFromDst = msgRcvFromDstOpt.get() + if msgRcvFromDst.msgType.get(RelayType.Stop) != RelayType.Status or + msgRcvFromDst.status.get(StatusV1.StopRelayRefused) != StatusV1.Success: + trace "unexcepted relay stop response", msgRcvFromDst + await sendStatus(connSrc, StatusV1.HopCantOpenDstStream) + return + + await sendStatus(connSrc, StatusV1.Success) + trace "relaying connection", src, dst + await bridge(connSrc, connDst) + +proc handleStreamV1(r: Relay, conn: Connection) {.async, gcsafe.} = + let msgOpt = RelayMessage.decode(await conn.readLp(r.msgSize)) + if msgOpt.isNone: + await sendStatus(conn, StatusV1.MalformedMessage) + return + trace "relay handle stream", msg = msgOpt.get() + let msg = msgOpt.get() + case msg.msgType.get: + of RelayType.Hop: await r.handleHop(conn, msg) + of RelayType.Stop: await sendStatus(conn, StatusV1.StopRelayRefused) + of RelayType.CanHop: await sendStatus(conn, StatusV1.Success) + else: + trace "Unexpected relay handshake", msgType=msg.msgType + await sendStatus(conn, StatusV1.MalformedMessage) + +proc setup*(r: Relay, switch: Switch) = + r.switch = switch + r.switch.addPeerEventHandler( + proc (peerId: PeerId, event: PeerEvent) {.async.} = + r.rsvp.del(peerId), + Left) + +proc new*(T: typedesc[Relay], + reservationTTL: times.Duration = DefaultReservationTTL, + limitDuration: uint32 = DefaultLimitDuration, + limitData: uint64 = DefaultLimitData, + heartbeatSleepTime: uint32 = DefaultHeartbeatSleepTime, + maxCircuit: int = MaxCircuit, + maxCircuitPerPeer: int = MaxCircuitPerPeer, + msgSize: int = RelayMsgSize, + circuitRelayV1: bool = false): T = + + let r = T(reservationTTL: reservationTTL, + limit: Limit(duration: limitDuration, data: limitData), + heartbeatSleepTime: heartbeatSleepTime, + maxCircuit: maxCircuit, + maxCircuitPerPeer: maxCircuitPerPeer, + msgSize: msgSize, + isCircuitRelayV1: circuitRelayV1) + + proc handleStream(conn: Connection, proto: string) {.async, gcsafe.} = + try: + case proto: + of RelayV2HopCodec: await r.handleHopStreamV2(conn) + of RelayV1Codec: await r.handleStreamV1(conn) + except CancelledError as exc: + raise exc + except CatchableError as exc: + debug "exception in relayv2 handler", exc = exc.msg, conn + finally: + trace "exiting relayv2 handler", conn + await conn.close() + + r.codecs = if r.isCircuitRelayV1: @[RelayV1Codec] + else: @[RelayV2HopCodec, RelayV1Codec] + r.handler = handleStream + r + +proc deletesReservation(r: Relay) {.async.} = + heartbeat "Reservation timeout", r.heartbeatSleepTime.seconds(): + let n = now().utc + for k in toSeq(r.rsvp.keys): + if n > r.rsvp[k]: + r.rsvp.del(k) + +method start*(r: Relay) {.async.} = + if not r.reservationLoop.isNil: + warn "Starting relay twice" + return + r.reservationLoop = r.deletesReservation() + r.started = true + +method stop*(r: Relay) {.async.} = + if r.reservationLoop.isNil: + warn "Stopping relay without starting it" + return + r.started = false + r.reservationLoop.cancel() + r.reservationLoop = nil diff --git a/vendor/nim-libp2p/libp2p/protocols/relay/rtransport.nim b/vendor/nim-libp2p/libp2p/protocols/relay/rtransport.nim new file mode 100644 index 000000000..d84f43355 --- /dev/null +++ b/vendor/nim-libp2p/libp2p/protocols/relay/rtransport.nim @@ -0,0 +1,109 @@ +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. + +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} + +import sequtils, strutils + +import chronos, chronicles + +import ./client, + ./rconn, + ./utils, + ../../switch, + ../../stream/connection, + ../../transports/transport + +logScope: + topics = "libp2p relay relay-transport" + +type + RelayTransport* = ref object of Transport + client*: RelayClient + queue: AsyncQueue[Connection] + selfRunning: bool + +method start*(self: RelayTransport, ma: seq[MultiAddress]) {.async.} = + if self.selfRunning: + trace "Relay transport already running" + return + + self.client.onNewConnection = proc( + conn: Connection, + duration: uint32 = 0, + data: uint64 = 0) {.async, gcsafe, raises: [Defect].} = + await self.queue.addLast(RelayConnection.new(conn, duration, data)) + await conn.join() + self.selfRunning = true + await procCall Transport(self).start(ma) + trace "Starting Relay transport" + +method stop*(self: RelayTransport) {.async, gcsafe.} = + self.running = false + self.selfRunning = false + self.client.onNewConnection = nil + while not self.queue.empty(): + await self.queue.popFirstNoWait().close() + +method accept*(self: RelayTransport): Future[Connection] {.async, gcsafe.} = + result = await self.queue.popFirst() + +proc dial*(self: RelayTransport, ma: MultiAddress): Future[Connection] {.async, gcsafe.} = + let + sma = toSeq(ma.items()) + relayAddrs = sma[0..sma.len-4].mapIt(it.tryGet()).foldl(a & b) + var + relayPeerId: PeerId + dstPeerId: PeerId + if not relayPeerId.init(($(sma[^3].get())).split('/')[2]): + raise newException(RelayV2DialError, "Relay doesn't exist") + if not dstPeerId.init(($(sma[^1].get())).split('/')[2]): + raise newException(RelayV2DialError, "Destination doesn't exist") + trace "Dial", relayPeerId, dstPeerId + + let conn = await self.client.switch.dial( + relayPeerId, + @[ relayAddrs ], + @[ RelayV2HopCodec, RelayV1Codec ]) + conn.dir = Direction.Out + var rc: RelayConnection + try: + case conn.protocol: + of RelayV1Codec: + return await self.client.dialPeerV1(conn, dstPeerId, @[]) + of RelayV2HopCodec: + rc = RelayConnection.new(conn, 0, 0) + return await self.client.dialPeerV2(rc, dstPeerId, @[]) + except CancelledError as exc: + raise exc + except CatchableError as exc: + if not rc.isNil: await rc.close() + raise exc + +method dial*( + self: RelayTransport, + hostname: string, + address: MultiAddress): Future[Connection] {.async, gcsafe.} = + result = await self.dial(address) + +method handles*(self: RelayTransport, ma: MultiAddress): bool {.gcsafe} = + if ma.protocols.isOk(): + let sma = toSeq(ma.items()) + if sma.len >= 3: + result = CircuitRelay.match(sma[^2].get()) and + P2PPattern.match(sma[^1].get()) + trace "Handles return", ma, result + +proc new*(T: typedesc[RelayTransport], cl: RelayClient, upgrader: Upgrade): T = + result = T(client: cl, upgrader: upgrader) + result.running = true + result.queue = newAsyncQueue[Connection](0) diff --git a/vendor/nim-libp2p/libp2p/protocols/relay/utils.nim b/vendor/nim-libp2p/libp2p/protocols/relay/utils.nim new file mode 100644 index 000000000..efa9744ba --- /dev/null +++ b/vendor/nim-libp2p/libp2p/protocols/relay/utils.nim @@ -0,0 +1,87 @@ +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. + +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} + +import options + +import chronos, chronicles + +import ./messages, + ../../stream/connection + +logScope: + topics = "libp2p relay relay-utils" + +const + RelayV1Codec* = "/libp2p/circuit/relay/0.1.0" + RelayV2HopCodec* = "/libp2p/circuit/relay/0.2.0/hop" + RelayV2StopCodec* = "/libp2p/circuit/relay/0.2.0/stop" + +proc sendStatus*(conn: Connection, code: StatusV1) {.async, gcsafe.} = + trace "send relay/v1 status", status = $code & "(" & $ord(code) & ")" + let + msg = RelayMessage(msgType: some(RelayType.Status), status: some(code)) + pb = encode(msg) + await conn.writeLp(pb.buffer) + +proc sendHopStatus*(conn: Connection, code: StatusV2) {.async, gcsafe.} = + trace "send hop relay/v2 status", status = $code & "(" & $ord(code) & ")" + let + msg = HopMessage(msgType: HopMessageType.Status, status: some(code)) + pb = encode(msg) + await conn.writeLp(pb.buffer) + +proc sendStopStatus*(conn: Connection, code: StatusV2) {.async.} = + trace "send stop relay/v2 status", status = $code & " (" & $ord(code) & ")" + let + msg = StopMessage(msgType: StopMessageType.Status, status: some(code)) + pb = encode(msg) + await conn.writeLp(pb.buffer) + +proc bridge*(connSrc: Connection, connDst: Connection) {.async.} = + const bufferSize = 4096 + var + bufSrcToDst: array[bufferSize, byte] + bufDstToSrc: array[bufferSize, byte] + futSrc = connSrc.readOnce(addr bufSrcToDst[0], bufSrcToDst.high + 1) + futDst = connDst.readOnce(addr bufDstToSrc[0], bufDstToSrc.high + 1) + bytesSendFromSrcToDst = 0 + bytesSendFromDstToSrc = 0 + bufRead: int + + try: + while not connSrc.closed() and not connDst.closed(): + await futSrc or futDst + if futSrc.finished(): + bufRead = await futSrc + bytesSendFromSrcToDst.inc(bufRead) + await connDst.write(@bufSrcToDst[0.. transport.accept() - ) + let slot = await s.connManager.getIncomingSlot() + conn = + try: + await transport.accept() + except CatchableError as exc: + slot.release() + raise exc + slot.trackConnection(conn) if isNil(conn): # A nil connection means that we might have hit a # file-handle limit (or another non-fatal error), @@ -213,9 +259,13 @@ proc accept(s: Switch, transport: Transport) {.async.} = # noraises await conn.close() return -proc stop*(s: Switch) {.async.} = +proc stop*(s: Switch) {.async, public.} = + ## Stop listening on every transport, and + ## close every active connections + trace "Stopping switch" + s.started = false # close and cleanup all connections await s.connManager.close() @@ -239,9 +289,13 @@ proc stop*(s: Switch) {.async.} = if not a.finished: a.cancel() + await s.ms.stop() + trace "Switch stopped" -proc start*(s: Switch) {.async, gcsafe.} = +proc start*(s: Switch) {.async, gcsafe, public.} = + ## Start listening on every transport + trace "starting switch for peer", peerInfo = s.peerInfo var startFuts: seq[Future[void]] for t in s.transports: @@ -272,18 +326,21 @@ proc start*(s: Switch) {.async, gcsafe.} = s.peerInfo.update() + await s.ms.start() + + s.started = true + debug "Started libp2p node", peer = s.peerInfo proc newSwitch*(peerInfo: PeerInfo, transports: seq[Transport], identity: Identify, - muxers: Table[string, MuxerProvider], secureManagers: openArray[Secure] = [], connManager: ConnManager, ms: MultistreamSelect, nameResolver: NameResolver = nil, peerStore = PeerStore.new()): Switch - {.raises: [Defect, LPError].} = + {.raises: [Defect, LPError], public.} = if secureManagers.len == 0: raise newException(LPError, "Provide at least one secure manager") diff --git a/vendor/nim-libp2p/libp2p/transcoder.nim b/vendor/nim-libp2p/libp2p/transcoder.nim index c9f35cc5c..926029f92 100644 --- a/vendor/nim-libp2p/libp2p/transcoder.nim +++ b/vendor/nim-libp2p/libp2p/transcoder.nim @@ -1,11 +1,11 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. ## This module implements transcoder interface. import vbuffer diff --git a/vendor/nim-libp2p/libp2p/transports/tcptransport.nim b/vendor/nim-libp2p/libp2p/transports/tcptransport.nim index 4238c08bc..24f63f6af 100644 --- a/vendor/nim-libp2p/libp2p/transports/tcptransport.nim +++ b/vendor/nim-libp2p/libp2p/transports/tcptransport.nim @@ -1,13 +1,18 @@ -## Nim-LibP2P -## Copyright (c) 2019 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +## TCP transport implementation + +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/[oids, sequtils] import chronos, chronicles @@ -20,7 +25,8 @@ import transport, ../multiaddress, ../stream/connection, ../stream/chronosstream, - ../upgrademngrs/upgrade + ../upgrademngrs/upgrade, + ../utility logScope: topics = "libp2p tcptransport" @@ -118,13 +124,12 @@ proc connHandler*(self: TcpTransport, proc new*( T: typedesc[TcpTransport], flags: set[ServerFlags] = {}, - upgrade: Upgrade): T = + upgrade: Upgrade): T {.public.} = let transport = T( flags: flags, upgrader: upgrade) - inc getTcpTransportTracker().opened return transport method start*( @@ -139,6 +144,7 @@ method start*( await procCall Transport(self).start(addrs) trace "Starting TCP transport" + inc getTcpTransportTracker().opened for i, ma in addrs: if not self.handles(ma): @@ -162,16 +168,19 @@ method start*( method stop*(self: TcpTransport) {.async, gcsafe.} = ## stop the transport ## - try: trace "Stopping TCP transport" - await procCall Transport(self).stop() # call base checkFutures( await allFinished( self.clients[Direction.In].mapIt(it.closeWait()) & self.clients[Direction.Out].mapIt(it.closeWait()))) + if not self.running: + warn "TCP transport already stopped" + return + + await procCall Transport(self).stop() # call base var toWait: seq[Future[void]] for fut in self.acceptFuts: if not fut.finished: diff --git a/vendor/nim-libp2p/libp2p/transports/transport.nim b/vendor/nim-libp2p/libp2p/transports/transport.nim index 01bbf8c6c..12d1a0803 100644 --- a/vendor/nim-libp2p/libp2p/transports/transport.nim +++ b/vendor/nim-libp2p/libp2p/transports/transport.nim @@ -1,14 +1,17 @@ -## Nim-LibP2P -## Copyright (c) 2019 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. ## -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import sequtils import chronos, chronicles @@ -84,12 +87,13 @@ method upgradeIncoming*( method upgradeOutgoing*( self: Transport, - conn: Connection): Future[Connection] {.base, gcsafe.} = + conn: Connection, + peerId: Opt[PeerId]): Future[Connection] {.base, gcsafe.} = ## base upgrade method that the transport uses to perform ## transport specific upgrades ## - self.upgrader.upgradeOutgoing(conn) + self.upgrader.upgradeOutgoing(conn, peerId) method handles*( self: Transport, diff --git a/vendor/nim-libp2p/libp2p/transports/wstransport.nim b/vendor/nim-libp2p/libp2p/transports/wstransport.nim index 581e61f31..50eb7c333 100644 --- a/vendor/nim-libp2p/libp2p/transports/wstransport.nim +++ b/vendor/nim-libp2p/libp2p/transports/wstransport.nim @@ -1,13 +1,18 @@ -## Nim-LibP2P -## Copyright (c) 2021 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +## WebSocket & WebSocket Secure transport implementation + +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/[sequtils] import chronos, chronicles @@ -18,6 +23,7 @@ import transport, ../multistream, ../connmanager, ../multiaddress, + ../utility, ../stream/connection, ../upgrademngrs/upgrade, websock/websock @@ -84,6 +90,8 @@ method closeImpl*(s: WsStream): Future[void] {.async.} = await s.session.close() await procCall Connection(s).closeImpl() +method getWrapped*(s: WsStream): Connection = nil + type WsTransport* = ref object of Transport httpservers: seq[HttpServer] @@ -313,7 +321,8 @@ proc new*( flags: set[ServerFlags] = {}, factories: openArray[ExtFactory] = [], rng: Rng = nil, - handshakeTimeout = DefaultHeadersTimeout): T = + handshakeTimeout = DefaultHeadersTimeout): T {.public.} = + ## Creates a secure WebSocket transport T( upgrader: upgrade, @@ -331,7 +340,8 @@ proc new*( flags: set[ServerFlags] = {}, factories: openArray[ExtFactory] = [], rng: Rng = nil, - handshakeTimeout = DefaultHeadersTimeout): T = + handshakeTimeout = DefaultHeadersTimeout): T {.public.} = + ## Creates a clear-text WebSocket transport T.new( upgrade = upgrade, diff --git a/vendor/nim-libp2p/libp2p/upgrademngrs/muxedupgrade.nim b/vendor/nim-libp2p/libp2p/upgrademngrs/muxedupgrade.nim index b8cb909a3..030508c10 100644 --- a/vendor/nim-libp2p/libp2p/upgrademngrs/muxedupgrade.nim +++ b/vendor/nim-libp2p/libp2p/upgrademngrs/muxedupgrade.nim @@ -1,13 +1,16 @@ -## Nim-LibP2P -## Copyright (c) 2021 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/[tables, sequtils] import pkg/[chronos, chronicles, metrics] @@ -22,9 +25,14 @@ logScope: type MuxedUpgrade* = ref object of Upgrade - muxers*: Table[string, MuxerProvider] + muxers*: seq[MuxerProvider] streamHandler*: StreamHandler +proc getMuxerByCodec(self: MuxedUpgrade, muxerName: string): MuxerProvider = + for m in self.muxers: + if muxerName in m.codecs: + return m + proc identify*( self: MuxedUpgrade, muxer: Muxer) {.async, gcsafe.} = @@ -50,7 +58,7 @@ proc mux*( warn "no muxers registered, skipping upgrade flow", conn return - let muxerName = await self.ms.select(conn, toSeq(self.muxers.keys())) + let muxerName = await self.ms.select(conn, self.muxers.mapIt(it.codec)) if muxerName.len == 0 or muxerName == "na": debug "no muxer available, early exit", conn return @@ -58,7 +66,7 @@ proc mux*( trace "Found a muxer", conn, muxerName # create new muxer for connection - let muxer = self.muxers[muxerName].newMuxer(conn) + let muxer = self.getMuxerByCodec(muxerName).newMuxer(conn) # install stream handler muxer.streamHandler = self.streamHandler @@ -80,10 +88,11 @@ proc mux*( method upgradeOutgoing*( self: MuxedUpgrade, - conn: Connection): Future[Connection] {.async, gcsafe.} = + conn: Connection, + peerId: Opt[PeerId]): Future[Connection] {.async, gcsafe.} = trace "Upgrading outgoing connection", conn - let sconn = await self.secure(conn) # secure the connection + let sconn = await self.secure(conn, peerId) # secure the connection if isNil(sconn): raise newException(UpgradeFailedError, "unable to secure connection, stopping upgrade") @@ -121,13 +130,13 @@ method upgradeIncoming*( var cconn = conn try: - var sconn = await secure.secure(cconn, false) + var sconn = await secure.secure(cconn, false, Opt.none(PeerId)) if isNil(sconn): return cconn = sconn # add the muxer - for muxer in self.muxers.values: + for muxer in self.muxers: ms.addHandler(muxer.codecs, muxer) # handle subsequent secure requests @@ -197,7 +206,7 @@ proc muxerHandler( proc new*( T: type MuxedUpgrade, identity: Identify, - muxers: Table[string, MuxerProvider], + muxers: seq[MuxerProvider], secureManagers: openArray[Secure] = [], connManager: ConnManager, ms: MultistreamSelect): T = diff --git a/vendor/nim-libp2p/libp2p/upgrademngrs/upgrade.nim b/vendor/nim-libp2p/libp2p/upgrademngrs/upgrade.nim index d0dfc1df2..c5733e658 100644 --- a/vendor/nim-libp2p/libp2p/upgrademngrs/upgrade.nim +++ b/vendor/nim-libp2p/libp2p/upgrademngrs/upgrade.nim @@ -1,13 +1,16 @@ -## Nim-LibP2P -## Copyright (c) 2021 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import std/[options, sequtils, strutils] import pkg/[chronos, chronicles, metrics] @@ -44,12 +47,14 @@ method upgradeIncoming*( method upgradeOutgoing*( self: Upgrade, - conn: Connection): Future[Connection] {.base.} = + conn: Connection, + peerId: Opt[PeerId]): Future[Connection] {.base.} = doAssert(false, "Not implemented!") proc secure*( self: Upgrade, - conn: Connection): Future[Connection] {.async, gcsafe.} = + conn: Connection, + peerId: Opt[PeerId]): Future[Connection] {.async, gcsafe.} = if self.secureManagers.len <= 0: raise newException(UpgradeFailedError, "No secure managers registered!") @@ -64,7 +69,7 @@ proc secure*( # let's avoid duplicating checks but detect if it fails to do it properly doAssert(secureProtocol.len > 0) - return await secureProtocol[0].secure(conn, true) + return await secureProtocol[0].secure(conn, true, peerId) proc identify*( self: Upgrade, diff --git a/vendor/nim-libp2p/libp2p/utility.nim b/vendor/nim-libp2p/libp2p/utility.nim index 4ee3d3da3..dd499b5bb 100644 --- a/vendor/nim-libp2p/libp2p/utility.nim +++ b/vendor/nim-libp2p/libp2p/utility.nim @@ -1,16 +1,21 @@ -## Nim-LibP2P -## Copyright (c) 2020 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import stew/byteutils +template public* {.pragma.} + const ShortDumpMax = 12 diff --git a/vendor/nim-libp2p/libp2p/utils/heartbeat.nim b/vendor/nim-libp2p/libp2p/utils/heartbeat.nim index 3fad818a0..6756b1625 100644 --- a/vendor/nim-libp2p/libp2p/utils/heartbeat.nim +++ b/vendor/nim-libp2p/libp2p/utils/heartbeat.nim @@ -7,7 +7,10 @@ # This file may not be copied, modified, or distributed except according to # those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import sequtils import chronos, chronicles diff --git a/vendor/nim-libp2p/libp2p/utils/semaphore.nim b/vendor/nim-libp2p/libp2p/utils/semaphore.nim index e396f2711..12f4a4daf 100644 --- a/vendor/nim-libp2p/libp2p/utils/semaphore.nim +++ b/vendor/nim-libp2p/libp2p/utils/semaphore.nim @@ -1,13 +1,16 @@ -## Nim-Libp2p -## Copyright (c) 2020 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import sequtils import chronos, chronicles diff --git a/vendor/nim-libp2p/libp2p/varint.nim b/vendor/nim-libp2p/libp2p/varint.nim index 2662cc3e0..e881a317a 100644 --- a/vendor/nim-libp2p/libp2p/varint.nim +++ b/vendor/nim-libp2p/libp2p/varint.nim @@ -1,11 +1,11 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. ## This module implements Variable Integer `VARINT`. ## This module supports two variants of variable integer @@ -16,7 +16,10 @@ ## maximum size of encoded value is 9 octets (bytes). ## https://github.com/multiformats/unsigned-varint -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import stew/[byteutils, leb128, results] export leb128, results diff --git a/vendor/nim-libp2p/libp2p/vbuffer.nim b/vendor/nim-libp2p/libp2p/vbuffer.nim index f19c62289..7a834ad23 100644 --- a/vendor/nim-libp2p/libp2p/vbuffer.nim +++ b/vendor/nim-libp2p/libp2p/vbuffer.nim @@ -1,15 +1,18 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. ## This module implements variable buffer. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import varint, strutils diff --git a/vendor/nim-libp2p/libp2p/wire.nim b/vendor/nim-libp2p/libp2p/wire.nim index 761a6fdb5..61c0010af 100644 --- a/vendor/nim-libp2p/libp2p/wire.nim +++ b/vendor/nim-libp2p/libp2p/wire.nim @@ -1,13 +1,16 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} ## This module implements wire network connection procedures. import chronos, stew/endians2 diff --git a/vendor/nim-libp2p/mkdocs.yml b/vendor/nim-libp2p/mkdocs.yml new file mode 100644 index 000000000..9c4fcbb29 --- /dev/null +++ b/vendor/nim-libp2p/mkdocs.yml @@ -0,0 +1,45 @@ +site_name: nim-libp2p + +repo_url: https://github.com/status-im/nim-libp2p +repo_name: status-im/nim-libp2p +site_url: https://status-im.github.io/nim-libp2p/docs +edit_uri: edit/unstable/examples/ + +docs_dir: examples + +markdown_extensions: + - pymdownx.highlight: + anchor_linenums: true + - pymdownx.inlinehilite + - pymdownx.snippets + - pymdownx.superfences + - admonition + - pymdownx.details + - pymdownx.superfences + +theme: + logo: https://docs.libp2p.io/images/logo_small.png + favicon: https://docs.libp2p.io/images/logo_small.png + name: material + features: + - navigation.instant + - search.highlight + palette: + - scheme: default + primary: blue grey + toggle: + icon: material/toggle-switch + name: Switch to dark mode + + - scheme: slate + primary: blue grey + toggle: + icon: material/toggle-switch-off-outline + name: Switch to light mode + +nav: + - Introduction: README.md + - Tutorials: + - 'Part I: Simple connection': tutorial_1_connect.md + - 'Part II: Custom protocol': tutorial_2_customproto.md + - Reference: '/nim-libp2p/master/libp2p.html' diff --git a/vendor/nim-libp2p/nimble.lock b/vendor/nim-libp2p/nimble.lock new file mode 100644 index 000000000..a2fc36c53 --- /dev/null +++ b/vendor/nim-libp2p/nimble.lock @@ -0,0 +1,217 @@ +{ + "version": 1, + "packages": { + "unittest2": { + "version": "0.0.4", + "vcsRevision": "f180f596c88dfd266f746ed6f8dbebce39c824db", + "url": "https://github.com/status-im/nim-unittest2.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "fa309c41eaf6ef57895b9e603f2620a2f6e11780" + } + }, + "stew": { + "version": "0.1.0", + "vcsRevision": "6ad35b876fb6ebe0dfee0f697af173acc47906ee", + "url": "https://github.com/status-im/nim-stew.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "46d58c4feb457f3241e3347778334e325dce5268" + } + }, + "bearssl": { + "version": "0.1.5", + "vcsRevision": "ba80e2a0d7ae8aab666cee013e38ff8d33a3e5e7", + "url": "https://github.com/status-im/nim-bearssl", + "downloadMethod": "git", + "dependencies": [ + "unittest2" + ], + "checksums": { + "sha1": "383abd5becc77bf8e365b780a29d20529e1d9c4c" + } + }, + "httputils": { + "version": "0.3.0", + "vcsRevision": "689da19e9e9cfff4ced85e2b25c6b2b5598ed079", + "url": "https://github.com/status-im/nim-http-utils.git", + "downloadMethod": "git", + "dependencies": [ + "stew" + ], + "checksums": { + "sha1": "4ad3ad68d13c50184180ab4b2eacc0bd7ed2ed44" + } + }, + "chronos": { + "version": "3.0.11", + "vcsRevision": "17fed89c99beac5a92d3668d0d3e9b0e4ac13936", + "url": "https://github.com/status-im/nim-chronos.git", + "downloadMethod": "git", + "dependencies": [ + "stew", + "bearssl", + "httputils", + "unittest2" + ], + "checksums": { + "sha1": "f6fffc87571e5f76af2a77c4ebcc0e00909ced4e" + } + }, + "metrics": { + "version": "0.0.1", + "vcsRevision": "71e0f0e354e1f4c59e3dc92153989c8b723c3440", + "url": "https://github.com/status-im/nim-metrics", + "downloadMethod": "git", + "dependencies": [ + "chronos" + ], + "checksums": { + "sha1": "86da251fe532ef2163da30343688ab1c148c0340" + } + }, + "testutils": { + "version": "0.4.2", + "vcsRevision": "aa6e5216f4b4ab5aa971cdcdd70e1ec1203cedf2", + "url": "https://github.com/status-im/nim-testutils", + "downloadMethod": "git", + "dependencies": [ + "unittest2" + ], + "checksums": { + "sha1": "94427e0cce0e0c5841edcd3a6530b4e6b857a3cb" + } + }, + "faststreams": { + "version": "0.3.0", + "vcsRevision": "1b561a9e71b6bdad1c1cdff753418906037e9d09", + "url": "https://github.com/status-im/nim-faststreams.git", + "downloadMethod": "git", + "dependencies": [ + "stew", + "testutils", + "chronos", + "unittest2" + ], + "checksums": { + "sha1": "97edf9797924af48566a0af8267203dc21d80c77" + } + }, + "serialization": { + "version": "0.1.0", + "vcsRevision": "fcd0eadadde0ee000a63df8ab21dc4e9f015a790", + "url": "https://github.com/status-im/nim-serialization.git", + "downloadMethod": "git", + "dependencies": [ + "faststreams", + "unittest2", + "stew" + ], + "checksums": { + "sha1": "fef59519892cac70cccd81b612085caaa5e3e6cf" + } + }, + "json_serialization": { + "version": "0.1.0", + "vcsRevision": "c5f0e2465e8375dfc7aa0f56ccef67cb680bc6b0", + "url": "https://github.com/status-im/nim-json-serialization.git", + "downloadMethod": "git", + "dependencies": [ + "serialization", + "stew" + ], + "checksums": { + "sha1": "d89d79d0679a3a41b350e3ad4be56c0308cc5ec6" + } + }, + "chronicles": { + "version": "0.10.2", + "vcsRevision": "1682096306ddba8185dcfac360a8c3f952d721e4", + "url": "https://github.com/status-im/nim-chronicles.git", + "downloadMethod": "git", + "dependencies": [ + "testutils", + "json_serialization" + ], + "checksums": { + "sha1": "9a5bebb76b0f7d587a31e621d260119279e91c76" + } + }, + "asynctest": { + "version": "0.3.1", + "vcsRevision": "5347c59b4b057443a014722aa40800cd8bb95c69", + "url": "https://github.com/status-im/asynctest.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "53e0b610d13700296755a4ebe789882cae47a3b9" + } + }, + "nimcrypto": { + "version": "0.5.4", + "vcsRevision": "a5742a9a214ac33f91615f3862c7b099aec43b00", + "url": "https://github.com/cheatfate/nimcrypto", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "f76c87707cd4e96355b8bb6ef27e7f8b0aac1e08" + } + }, + "zlib": { + "version": "0.1.0", + "vcsRevision": "74cdeb54b21bededb5a515d36f608bc1850555a2", + "url": "https://github.com/status-im/nim-zlib", + "downloadMethod": "git", + "dependencies": [ + "stew" + ], + "checksums": { + "sha1": "01d330dc4c1924e56b1559ee73bc760e526f635c" + } + }, + "websock": { + "version": "0.1.0", + "vcsRevision": "73edde4417f7b45003113b7a34212c3ccd95b9fd", + "url": "https://github.com/status-im/nim-websock", + "downloadMethod": "git", + "dependencies": [ + "chronos", + "httputils", + "chronicles", + "stew", + "asynctest", + "nimcrypto", + "bearssl", + "zlib" + ], + "checksums": { + "sha1": "ec2b137543f280298ca48de9ed4461a033ba88d3" + } + }, + "dnsclient": { + "version": "0.1.2", + "vcsRevision": "fbb76f8af8a33ab818184a7d4406d9fee20993be", + "url": "https://github.com/ba0f3/dnsclient.nim.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "663239a914c814204b30dda6e0902cc0fbd0b8ee" + } + }, + "secp256k1": { + "version": "0.5.2", + "vcsRevision": "5340cf188168d6afcafc8023770d880f067c0b2f", + "url": "https://github.com/status-im/nim-secp256k1.git", + "downloadMethod": "git", + "dependencies": [ + "stew", + "nimcrypto" + ], + "checksums": { + "sha1": "ae9cbea4487be94a06653ffee075a7f1bd1e231e" + } + } + } +} \ No newline at end of file diff --git a/vendor/nim-libp2p/nimdoc.cfg b/vendor/nim-libp2p/nimdoc.cfg new file mode 100644 index 000000000..38aacf287 --- /dev/null +++ b/vendor/nim-libp2p/nimdoc.cfg @@ -0,0 +1,115 @@ +doc.item = """ +

+
$header
+
+$deprecationMsg +$desc +$seeSrc +
+
+""" + +doc.toc = """ + +
    +$content +
+""" + diff --git a/vendor/nim-libp2p/tests/commoninterop.nim b/vendor/nim-libp2p/tests/commoninterop.nim new file mode 100644 index 000000000..c2850706d --- /dev/null +++ b/vendor/nim-libp2p/tests/commoninterop.nim @@ -0,0 +1,597 @@ +import options, tables +import chronos, chronicles, stew/byteutils +import helpers +import ../libp2p +import ../libp2p/[daemon/daemonapi, varint, transports/wstransport, crypto/crypto] +import ../libp2p/protocols/relay/[relay, client, utils] + +type + SwitchCreator = proc( + ma: MultiAddress = MultiAddress.init("/ip4/127.0.0.1/tcp/0").tryGet(), + prov: TransportProvider = proc(upgr: Upgrade): Transport = TcpTransport.new({}, upgr), + relay: Relay = Relay.new(circuitRelayV1 = true)): + Switch {.gcsafe, raises: [Defect, LPError].} + DaemonPeerInfo = daemonapi.PeerInfo + +proc writeLp(s: StreamTransport, msg: string | seq[byte]): Future[int] {.gcsafe.} = + ## write lenght prefixed + var buf = initVBuffer() + buf.writeSeq(msg) + buf.finish() + result = s.write(buf.buffer) + +proc readLp(s: StreamTransport): Future[seq[byte]] {.async, gcsafe.} = + ## read length prefixed msg + var + size: uint + length: int + res: VarintResult[void] + result = newSeq[byte](10) + + for i in 0.. 0.uint: + await s.readExactly(addr result[0], int(size)) + +proc testPubSubDaemonPublish( + gossip: bool = false, + count: int = 1, + swCreator: SwitchCreator) {.async.} = + var pubsubData = "TEST MESSAGE" + var testTopic = "test-topic" + var msgData = pubsubData.toBytes() + + var flags = {PSFloodSub} + if gossip: + flags = {PSGossipSub} + + let daemonNode = await newDaemonApi(flags) + let daemonPeer = await daemonNode.identity() + let nativeNode = swCreator() + + let pubsub = if gossip: + GossipSub.init( + switch = nativeNode).PubSub + else: + FloodSub.init( + switch = nativeNode).PubSub + + nativeNode.mount(pubsub) + + await nativeNode.start() + await pubsub.start() + let nativePeer = nativeNode.peerInfo + + var finished = false + var times = 0 + proc nativeHandler(topic: string, data: seq[byte]) {.async.} = + let smsg = string.fromBytes(data) + check smsg == pubsubData + times.inc() + if times >= count and not finished: + finished = true + + await nativeNode.connect(daemonPeer.peer, daemonPeer.addresses) + + await sleepAsync(1.seconds) + await daemonNode.connect(nativePeer.peerId, nativePeer.addrs) + + proc pubsubHandler(api: DaemonAPI, + ticket: PubsubTicket, + message: PubSubMessage): Future[bool] {.async.} = + result = true # don't cancel subscription + + asyncDiscard daemonNode.pubsubSubscribe(testTopic, pubsubHandler) + pubsub.subscribe(testTopic, nativeHandler) + await sleepAsync(5.seconds) + + proc publisher() {.async.} = + while not finished: + await daemonNode.pubsubPublish(testTopic, msgData) + await sleepAsync(500.millis) + + await wait(publisher(), 5.minutes) # should be plenty of time + + await nativeNode.stop() + await pubsub.stop() + await daemonNode.close() + +proc testPubSubNodePublish( + gossip: bool = false, + count: int = 1, + swCreator: SwitchCreator) {.async.} = + var pubsubData = "TEST MESSAGE" + var testTopic = "test-topic" + var msgData = pubsubData.toBytes() + + var flags = {PSFloodSub} + if gossip: + flags = {PSGossipSub} + + let daemonNode = await newDaemonApi(flags) + let daemonPeer = await daemonNode.identity() + let nativeNode = swCreator() + + let pubsub = if gossip: + GossipSub.init( + switch = nativeNode).PubSub + else: + FloodSub.init( + switch = nativeNode).PubSub + + nativeNode.mount(pubsub) + + await nativeNode.start() + await pubsub.start() + let nativePeer = nativeNode.peerInfo + + await nativeNode.connect(daemonPeer.peer, daemonPeer.addresses) + + await sleepAsync(1.seconds) + await daemonNode.connect(nativePeer.peerId, nativePeer.addrs) + + var times = 0 + var finished = false + proc pubsubHandler(api: DaemonAPI, + ticket: PubsubTicket, + message: PubSubMessage): Future[bool] {.async.} = + let smsg = string.fromBytes(message.data) + check smsg == pubsubData + times.inc() + if times >= count and not finished: + finished = true + result = true # don't cancel subscription + + discard await daemonNode.pubsubSubscribe(testTopic, pubsubHandler) + proc nativeHandler(topic: string, data: seq[byte]) {.async.} = discard + pubsub.subscribe(testTopic, nativeHandler) + await sleepAsync(5.seconds) + + proc publisher() {.async.} = + while not finished: + discard await pubsub.publish(testTopic, msgData) + await sleepAsync(500.millis) + + await wait(publisher(), 5.minutes) # should be plenty of time + + check finished + await nativeNode.stop() + await pubsub.stop() + await daemonNode.close() + +proc commonInteropTests*(name: string, swCreator: SwitchCreator) = + suite "Interop using " & name: + # TODO: chronos transports are leaking, + # but those are tracked for both the daemon + # and libp2p, so not sure which one it is, + # need to investigate more + # teardown: + # checkTrackers() + + # TODO: this test is failing sometimes on windows + # For some reason we receive EOF before test 4 sometimes + + asyncTest "native -> daemon multiple reads and writes": + var protos = @["/test-stream"] + + let nativeNode = swCreator() + + await nativeNode.start() + let daemonNode = await newDaemonApi() + let daemonPeer = await daemonNode.identity() + + var testFuture = newFuture[void]("test.future") + proc daemonHandler(api: DaemonAPI, stream: P2PStream) {.async.} = + check string.fromBytes(await stream.transp.readLp()) == "test 1" + discard await stream.transp.writeLp("test 2") + check string.fromBytes(await stream.transp.readLp()) == "test 3" + discard await stream.transp.writeLp("test 4") + testFuture.complete() + + await daemonNode.addHandler(protos, daemonHandler) + let conn = await nativeNode.dial(daemonPeer.peer, daemonPeer.addresses, protos[0]) + await conn.writeLp("test 1") + check "test 2" == string.fromBytes((await conn.readLp(1024))) + + await conn.writeLp("test 3") + check "test 4" == string.fromBytes((await conn.readLp(1024))) + + await wait(testFuture, 10.secs) + + await nativeNode.stop() + await daemonNode.close() + + await sleepAsync(1.seconds) + + asyncTest "native -> daemon connection": + var protos = @["/test-stream"] + var test = "TEST STRING" + # We are preparing expect string, which should be prefixed with varint + # length and do not have `\r\n` suffix, because we going to use + # readLine(). + var buffer = initVBuffer() + buffer.writeSeq(test & "\r\n") + buffer.finish() + var expect = newString(len(buffer) - 2) + copyMem(addr expect[0], addr buffer.buffer[0], len(expect)) + + let nativeNode = swCreator() + + await nativeNode.start() + + let daemonNode = await newDaemonApi() + let daemonPeer = await daemonNode.identity() + + var testFuture = newFuture[string]("test.future") + proc daemonHandler(api: DaemonAPI, stream: P2PStream) {.async.} = + # We should perform `readLp()` instead of `readLine()`. `readLine()` + # here reads actually length prefixed string. + var line = await stream.transp.readLine() + check line == expect + testFuture.complete(line) + await stream.close() + + await daemonNode.addHandler(protos, daemonHandler) + let conn = await nativeNode.dial(daemonPeer.peer, daemonPeer.addresses, protos[0]) + await conn.writeLp(test & "\r\n") + check expect == (await wait(testFuture, 10.secs)) + + await conn.close() + await nativeNode.stop() + await daemonNode.close() + + asyncTest "daemon -> native connection": + var protos = @["/test-stream"] + var test = "TEST STRING" + + var testFuture = newFuture[string]("test.future") + proc nativeHandler(conn: Connection, proto: string) {.async.} = + var line = string.fromBytes(await conn.readLp(1024)) + check line == test + testFuture.complete(line) + await conn.close() + + # custom proto + var proto = new LPProtocol + proto.handler = nativeHandler + proto.codec = protos[0] # codec + + let nativeNode = swCreator() + + nativeNode.mount(proto) + + await nativeNode.start() + let nativePeer = nativeNode.peerInfo + + let daemonNode = await newDaemonApi() + await daemonNode.connect(nativePeer.peerId, nativePeer.addrs) + var stream = await daemonNode.openStream(nativePeer.peerId, protos) + discard await stream.transp.writeLp(test) + + check test == (await wait(testFuture, 10.secs)) + + await stream.close() + await nativeNode.stop() + await daemonNode.close() + await sleepAsync(1.seconds) + + asyncTest "native -> daemon websocket connection": + var protos = @["/test-stream"] + var test = "TEST STRING" + + var testFuture = newFuture[string]("test.future") + proc nativeHandler(conn: Connection, proto: string) {.async.} = + var line = string.fromBytes(await conn.readLp(1024)) + check line == test + testFuture.complete(line) + await conn.close() + + # custom proto + var proto = new LPProtocol + proto.handler = nativeHandler + proto.codec = protos[0] # codec + + let wsAddress = MultiAddress.init("/ip4/127.0.0.1/tcp/0/ws").tryGet() + + let nativeNode = swCreator( + ma = wsAddress, + prov = proc (upgr: Upgrade): Transport = WsTransport.new(upgr) + ) + + nativeNode.mount(proto) + + await nativeNode.start() + let nativePeer = nativeNode.peerInfo + + let daemonNode = await newDaemonApi(hostAddresses = @[wsAddress]) + await daemonNode.connect(nativePeer.peerId, nativePeer.addrs) + var stream = await daemonNode.openStream(nativePeer.peerId, protos) + discard await stream.transp.writeLp(test) + + check test == (await wait(testFuture, 10.secs)) + + await stream.close() + await nativeNode.stop() + await daemonNode.close() + await sleepAsync(1.seconds) + + asyncTest "daemon -> native websocket connection": + var protos = @["/test-stream"] + var test = "TEST STRING" + # We are preparing expect string, which should be prefixed with varint + # length and do not have `\r\n` suffix, because we going to use + # readLine(). + var buffer = initVBuffer() + buffer.writeSeq(test & "\r\n") + buffer.finish() + var expect = newString(len(buffer) - 2) + copyMem(addr expect[0], addr buffer.buffer[0], len(expect)) + + let wsAddress = MultiAddress.init("/ip4/127.0.0.1/tcp/0/ws").tryGet() + let nativeNode = SwitchBuilder + .new() + .withAddress(wsAddress) + .withRng(crypto.newRng()) + .withMplex() + .withTransport(proc (upgr: Upgrade): Transport = WsTransport.new(upgr)) + .withNoise() + .build() + + await nativeNode.start() + + let daemonNode = await newDaemonApi(hostAddresses = @[wsAddress]) + let daemonPeer = await daemonNode.identity() + + var testFuture = newFuture[string]("test.future") + proc daemonHandler(api: DaemonAPI, stream: P2PStream) {.async.} = + # We should perform `readLp()` instead of `readLine()`. `readLine()` + # here reads actually length prefixed string. + var line = await stream.transp.readLine() + check line == expect + testFuture.complete(line) + await stream.close() + + await daemonNode.addHandler(protos, daemonHandler) + let conn = await nativeNode.dial(daemonPeer.peer, daemonPeer.addresses, protos[0]) + await conn.writeLp(test & "\r\n") + check expect == (await wait(testFuture, 10.secs)) + + await conn.close() + await nativeNode.stop() + await daemonNode.close() + + asyncTest "daemon -> multiple reads and writes": + var protos = @["/test-stream"] + + var testFuture = newFuture[void]("test.future") + proc nativeHandler(conn: Connection, proto: string) {.async.} = + check "test 1" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("test 2".toBytes()) + + check "test 3" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("test 4".toBytes()) + + testFuture.complete() + await conn.close() + + # custom proto + var proto = new LPProtocol + proto.handler = nativeHandler + proto.codec = protos[0] # codec + + let nativeNode = swCreator() + + nativeNode.mount(proto) + + await nativeNode.start() + let nativePeer = nativeNode.peerInfo + + let daemonNode = await newDaemonApi() + await daemonNode.connect(nativePeer.peerId, nativePeer.addrs) + var stream = await daemonNode.openStream(nativePeer.peerId, protos) + + asyncDiscard stream.transp.writeLp("test 1") + check "test 2" == string.fromBytes(await stream.transp.readLp()) + + asyncDiscard stream.transp.writeLp("test 3") + check "test 4" == string.fromBytes(await stream.transp.readLp()) + + await wait(testFuture, 10.secs) + + await stream.close() + await nativeNode.stop() + await daemonNode.close() + + asyncTest "read write multiple": + var protos = @["/test-stream"] + var test = "TEST STRING" + + var count = 0 + var testFuture = newFuture[int]("test.future") + proc nativeHandler(conn: Connection, proto: string) {.async.} = + while count < 10: + var line = string.fromBytes(await conn.readLp(1024)) + check line == test + await conn.writeLp(test.toBytes()) + count.inc() + + testFuture.complete(count) + await conn.close() + + # custom proto + var proto = new LPProtocol + proto.handler = nativeHandler + proto.codec = protos[0] # codec + + let nativeNode = swCreator() + + nativeNode.mount(proto) + + await nativeNode.start() + let nativePeer = nativeNode.peerInfo + + let daemonNode = await newDaemonApi() + await daemonNode.connect(nativePeer.peerId, nativePeer.addrs) + var stream = await daemonNode.openStream(nativePeer.peerId, protos) + + var count2 = 0 + while count2 < 10: + discard await stream.transp.writeLp(test) + let line = await stream.transp.readLp() + check test == string.fromBytes(line) + inc(count2) + + check 10 == (await wait(testFuture, 1.minutes)) + await stream.close() + await nativeNode.stop() + await daemonNode.close() + + asyncTest "floodsub: daemon publish one": + await testPubSubDaemonPublish(swCreator = swCreator) + + asyncTest "floodsub: daemon publish many": + await testPubSubDaemonPublish(count = 10, swCreator = swCreator) + + asyncTest "gossipsub: daemon publish one": + await testPubSubDaemonPublish(gossip = true, swCreator = swCreator) + + asyncTest "gossipsub: daemon publish many": + await testPubSubDaemonPublish(gossip = true, count = 10, swCreator = swCreator) + + asyncTest "floodsub: node publish one": + await testPubSubNodePublish(swCreator = swCreator) + + asyncTest "floodsub: node publish many": + await testPubSubNodePublish(count = 10, swCreator = swCreator) + + asyncTest "gossipsub: node publish one": + await testPubSubNodePublish(gossip = true, swCreator = swCreator) + + asyncTest "gossipsub: node publish many": + await testPubSubNodePublish(gossip = true, count = 10, swCreator = swCreator) + +proc relayInteropTests*(name: string, relayCreator: SwitchCreator) = + suite "Interop relay using " & name: + asyncTest "NativeSrc -> NativeRelay -> DaemonDst": + let closeBlocker = newFuture[void]() + # TODO: This Future blocks the daemonHandler after sending the last message. + # It exists because there's a strange behavior where stream.close sends + # a Rst instead of Fin. We should investigate this at some point. + proc daemonHandler(api: DaemonAPI, stream: P2PStream) {.async.} = + check "line1" == string.fromBytes(await stream.transp.readLp()) + discard await stream.transp.writeLp("line2") + check "line3" == string.fromBytes(await stream.transp.readLp()) + discard await stream.transp.writeLp("line4") + await closeBlocker + await stream.close() + let + maSrc = MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() + maRel = MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() + src = relayCreator(maSrc, relay = RelayClient.new(circuitRelayV1 = true)) + rel = relayCreator(maRel) + + await src.start() + await rel.start() + let daemonNode = await newDaemonApi() + let daemonPeer = await daemonNode.identity() + let maStr = $rel.peerInfo.addrs[0] & "/p2p/" & $rel.peerInfo.peerId & "/p2p-circuit/p2p/" & $daemonPeer.peer + let maddr = MultiAddress.init(maStr).tryGet() + await src.connect(rel.peerInfo.peerId, rel.peerInfo.addrs) + await rel.connect(daemonPeer.peer, daemonPeer.addresses) + + await daemonNode.addHandler(@[ "/testCustom" ], daemonHandler) + + let conn = await src.dial(daemonPeer.peer, @[ maddr ], @[ "/testCustom" ]) + + await conn.writeLp("line1") + check string.fromBytes(await conn.readLp(1024)) == "line2" + + await conn.writeLp("line3") + check string.fromBytes(await conn.readLp(1024)) == "line4" + + closeBlocker.complete() + await allFutures(src.stop(), rel.stop()) + await daemonNode.close() + + asyncTest "DaemonSrc -> NativeRelay -> NativeDst": + proc customHandler(conn: Connection, proto: string) {.async.} = + check "line1" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("line2") + check "line3" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("line4") + await conn.close() + let + protos = @[ "/customProto", RelayV1Codec ] + var + customProto = new LPProtocol + customProto.handler = customHandler + customProto.codec = protos[0] + let + maRel = MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() + maDst = MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() + rel = relayCreator(maRel) + dst = relayCreator(maDst, relay=RelayClient.new()) + + dst.mount(customProto) + await rel.start() + await dst.start() + let daemonNode = await newDaemonApi() + let daemonPeer = await daemonNode.identity() + let maStr = $rel.peerInfo.addrs[0] & "/p2p/" & $rel.peerInfo.peerId & "/p2p-circuit/p2p/" & $dst.peerInfo.peerId + let maddr = MultiAddress.init(maStr).tryGet() + await daemonNode.connect(rel.peerInfo.peerId, rel.peerInfo.addrs) + await rel.connect(dst.peerInfo.peerId, dst.peerInfo.addrs) + await daemonNode.connect(dst.peerInfo.peerId, @[ maddr ]) + var stream = await daemonNode.openStream(dst.peerInfo.peerId, protos) + + discard await stream.transp.writeLp("line1") + check string.fromBytes(await stream.transp.readLp()) == "line2" + discard await stream.transp.writeLp("line3") + check string.fromBytes(await stream.transp.readLp()) == "line4" + + await allFutures(dst.stop(), rel.stop()) + await daemonNode.close() + + asyncTest "NativeSrc -> DaemonRelay -> NativeDst": + proc customHandler(conn: Connection, proto: string) {.async.} = + check "line1" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("line2") + check "line3" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("line4") + await conn.close() + let + protos = @[ "/customProto", RelayV1Codec ] + var + customProto = new LPProtocol + customProto.handler = customHandler + customProto.codec = protos[0] + let + maSrc = MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() + maDst = MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() + src = relayCreator(maSrc, relay=RelayClient.new()) + dst = relayCreator(maDst, relay=RelayClient.new()) + + dst.mount(customProto) + await src.start() + await dst.start() + let daemonNode = await newDaemonApi({RelayHop}) + let daemonPeer = await daemonNode.identity() + let maStr = $daemonPeer.addresses[0] & "/p2p/" & $daemonPeer.peer & "/p2p-circuit/p2p/" & $dst.peerInfo.peerId + let maddr = MultiAddress.init(maStr).tryGet() + await src.connect(daemonPeer.peer, daemonPeer.addresses) + await daemonNode.connect(dst.peerInfo.peerId, dst.peerInfo.addrs) + let conn = await src.dial(dst.peerInfo.peerId, @[ maddr ], protos[0]) + + await conn.writeLp("line1") + check string.fromBytes(await conn.readLp(1024)) == "line2" + + await conn.writeLp("line3") + check string.fromBytes(await conn.readLp(1024)) == "line4" + + await allFutures(src.stop(), dst.stop()) + await daemonNode.close() diff --git a/vendor/nim-libp2p/tests/config.nims b/vendor/nim-libp2p/tests/config.nims new file mode 100644 index 000000000..3ec031e76 --- /dev/null +++ b/vendor/nim-libp2p/tests/config.nims @@ -0,0 +1,3 @@ +import ../config.nims + +--threads:on diff --git a/vendor/nim-libp2p/tests/helpers.nim b/vendor/nim-libp2p/tests/helpers.nim index a607df68b..b82011f7c 100644 --- a/vendor/nim-libp2p/tests/helpers.nim +++ b/vendor/nim-libp2p/tests/helpers.nim @@ -1,6 +1,9 @@ -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} -import chronos, bearssl +import chronos import ../libp2p/transports/tcptransport import ../libp2p/stream/bufferstream @@ -13,7 +16,6 @@ import ../libp2p/protocols/secure/secure import ./asyncunit export asyncunit -{.push raises: [Defect].} const StreamTransportTrackerName = "stream.transport" @@ -58,11 +60,11 @@ template checkTrackers*() = except: discard type RngWrap = object - rng: ref BrHmacDrbgContext + rng: ref HmacDrbgContext var rngVar: RngWrap -proc getRng(): ref BrHmacDrbgContext = +proc getRng(): ref HmacDrbgContext = # TODO if `rngVar` is a threadvar like it should be, there are random and # spurious compile failures on mac - this is not gcsafe but for the # purpose of the tests, it's ok as long as we only use a single thread @@ -71,7 +73,7 @@ proc getRng(): ref BrHmacDrbgContext = rngVar.rng = newRng() rngVar.rng -template rng*(): ref BrHmacDrbgContext = +template rng*(): ref HmacDrbgContext = getRng() type @@ -87,6 +89,22 @@ proc new*(T: typedesc[TestBufferStream], writeHandler: WriteHandler): T = testBufferStream.initStream() testBufferStream +proc bridgedConnections*: (Connection, Connection) = + let + connA = TestBufferStream() + connB = TestBufferStream() + connA.dir = Direction.Out + connB.dir = Direction.In + connA.initStream() + connB.initStream() + connA.writeHandler = proc(data: seq[byte]) {.async.} = + await connB.pushData(data) + + connB.writeHandler = proc(data: seq[byte]) {.async.} = + await connA.pushData(data) + return (connA, connB) + + proc checkExpiringInternal(cond: proc(): bool {.raises: [Defect].} ): Future[bool] {.async, gcsafe.} = {.gcsafe.}: let start = Moment.now() diff --git a/vendor/nim-libp2p/tests/nim.cfg b/vendor/nim-libp2p/tests/nim.cfg deleted file mode 100644 index 9d57ecf93..000000000 --- a/vendor/nim-libp2p/tests/nim.cfg +++ /dev/null @@ -1 +0,0 @@ ---threads:on \ No newline at end of file diff --git a/vendor/nim-libp2p/tests/pubsub/testfloodsub.nim b/vendor/nim-libp2p/tests/pubsub/testfloodsub.nim index 38d00d9cd..dad332190 100644 --- a/vendor/nim-libp2p/tests/pubsub/testfloodsub.nim +++ b/vendor/nim-libp2p/tests/pubsub/testfloodsub.nim @@ -1,11 +1,11 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. {.used.} @@ -54,13 +54,6 @@ suite "FloodSub": nodes[1].switch.start(), ) - # start pubsub - await allFuturesThrowing( - allFinished( - nodes[0].start(), - nodes[1].start(), - )) - await subscribeNodes(nodes) nodes[1].subscribe("foobar", handler) @@ -74,11 +67,6 @@ suite "FloodSub": nodes[1].switch.stop() ) - await allFuturesThrowing( - nodes[0].stop(), - nodes[1].stop() - ) - await allFuturesThrowing(nodesFut.concat()) asyncTest "FloodSub basic publish/subscribe B -> A": @@ -96,12 +84,6 @@ suite "FloodSub": nodes[1].switch.start(), ) - # start pubsubcon - await allFuturesThrowing( - allFinished( - nodes[0].start(), - nodes[1].start(), - )) await subscribeNodes(nodes) @@ -117,11 +99,6 @@ suite "FloodSub": nodes[1].switch.stop() ) - await allFuturesThrowing( - nodes[0].stop(), - nodes[1].stop() - ) - await allFuturesThrowing(nodesFut) asyncTest "FloodSub validation should succeed": @@ -139,13 +116,6 @@ suite "FloodSub": nodes[1].switch.start(), ) - # start pubsubcon - await allFuturesThrowing( - allFinished( - nodes[0].start(), - nodes[1].start(), - )) - await subscribeNodes(nodes) nodes[1].subscribe("foobar", handler) @@ -168,11 +138,6 @@ suite "FloodSub": nodes[1].switch.stop() ) - await allFuturesThrowing( - nodes[0].stop(), - nodes[1].stop() - ) - await allFuturesThrowing(nodesFut) asyncTest "FloodSub validation should fail": @@ -188,13 +153,6 @@ suite "FloodSub": nodes[1].switch.start(), ) - # start pubsubcon - await allFuturesThrowing( - allFinished( - nodes[0].start(), - nodes[1].start(), - )) - await subscribeNodes(nodes) nodes[1].subscribe("foobar", handler) await waitSub(nodes[0], nodes[1], "foobar") @@ -214,11 +172,6 @@ suite "FloodSub": nodes[1].switch.stop() ) - await allFuturesThrowing( - nodes[0].stop(), - nodes[1].stop() - ) - await allFuturesThrowing(nodesFut) asyncTest "FloodSub validation one fails and one succeeds": @@ -236,13 +189,6 @@ suite "FloodSub": nodes[1].switch.start(), ) - # start pubsubcon - await allFuturesThrowing( - allFinished( - nodes[0].start(), - nodes[1].start(), - )) - await subscribeNodes(nodes) nodes[1].subscribe("foo", handler) await waitSub(nodes[0], nodes[1], "foo") @@ -266,11 +212,6 @@ suite "FloodSub": nodes[1].switch.stop() ) - await allFuturesThrowing( - nodes[0].stop(), - nodes[1].stop() - ) - await allFuturesThrowing(nodesFut) asyncTest "FloodSub multiple peers, no self trigger": @@ -296,7 +237,6 @@ suite "FloodSub": nodes = generateNodes(runs, triggerSelf = false) nodesFut = nodes.mapIt(it.switch.start()) - await allFuturesThrowing(nodes.mapIt(it.start())) await subscribeNodes(nodes) for i in 0.. 0.0 await conn.close() @@ -690,7 +687,7 @@ suite "GossipSub internal": ) peer.iHaveBudget = 0 let iwants = gossipSub.handleIHave(peer, @[msg]) - check: iwants.messageIDs.len == 0 + check: iwants.messageIds.len == 0 block: # given duplicate ihave should generate only one iwant @@ -705,7 +702,7 @@ suite "GossipSub internal": messageIDs: @[id, id, id] ) let iwants = gossipSub.handleIHave(peer, @[msg]) - check: iwants.messageIDs.len == 1 + check: iwants.messageIds.len == 1 block: # given duplicate iwant should generate only one message diff --git a/vendor/nim-libp2p/tests/pubsub/testgossipsub.nim b/vendor/nim-libp2p/tests/pubsub/testgossipsub.nim index 416368dbf..8c4a7667d 100644 --- a/vendor/nim-libp2p/tests/pubsub/testgossipsub.nim +++ b/vendor/nim-libp2p/tests/pubsub/testgossipsub.nim @@ -1,11 +1,11 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. {.used.} @@ -32,18 +32,11 @@ proc `$`(peer: PubSubPeer): string = shortLog(peer) proc waitSub(sender, receiver: auto; key: string) {.async, gcsafe.} = if sender == receiver: return - # turn things deterministic + let timeout = Moment.now() + 5.seconds + let fsub = GossipSub(sender) + # this is for testing purposes only # peers can be inside `mesh` and `fanout`, not just `gossipsub` - var ceil = 15 - let fsub = GossipSub(sender) - let ev = newAsyncEvent() - fsub.heartbeatEvents.add(ev) - - # await first heartbeat - await ev.wait() - ev.clear() - while (not fsub.gossipsub.hasKey(key) or not fsub.gossipsub.hasPeerId(key, receiver.peerInfo.peerId)) and (not fsub.mesh.hasKey(key) or @@ -52,23 +45,19 @@ proc waitSub(sender, receiver: auto; key: string) {.async, gcsafe.} = not fsub.fanout.hasPeerId(key , receiver.peerInfo.peerId)): trace "waitSub sleeping..." - # await more heartbeats - await ev.wait() - ev.clear() + # await + await sleepAsync(5.milliseconds) + doAssert Moment.now() < timeout, "waitSub timeout!" - dec ceil - doAssert(ceil > 0, "waitSub timeout!") - -template tryPublish(call: untyped, require: int, wait: Duration = 1.seconds, times: int = 10): untyped = +template tryPublish(call: untyped, require: int, wait = 10.milliseconds, timeout = 5.seconds): untyped = var - limit = times + expiration = Moment.now() + timeout pubs = 0 - while pubs < require and limit > 0: + while pubs < require and Moment.now() < expiration: pubs = pubs + call await sleepAsync(wait) - limit.dec() - if limit == 0: - doAssert(false, "Failed to publish!") + + doAssert pubs >= require, "Failed to publish!" suite "GossipSub": teardown: @@ -89,13 +78,6 @@ suite "GossipSub": nodes[1].switch.start(), ) - # start pubsub - await allFuturesThrowing( - allFinished( - nodes[0].start(), - nodes[1].start(), - )) - await subscribeNodes(nodes) nodes[0].subscribe("foobar", handler) @@ -125,11 +107,6 @@ suite "GossipSub": nodes[1].switch.stop() ) - await allFuturesThrowing( - nodes[0].stop(), - nodes[1].stop() - ) - await allFuturesThrowing(nodesFut.concat()) asyncTest "GossipSub validation should fail (reject)": @@ -145,13 +122,6 @@ suite "GossipSub": nodes[1].switch.start(), ) - # start pubsub - await allFuturesThrowing( - allFinished( - nodes[0].start(), - nodes[1].start(), - )) - await subscribeNodes(nodes) nodes[0].subscribe("foobar", handler) @@ -187,11 +157,6 @@ suite "GossipSub": nodes[1].switch.stop() ) - await allFuturesThrowing( - nodes[0].stop(), - nodes[1].stop() - ) - await allFuturesThrowing(nodesFut.concat()) asyncTest "GossipSub validation should fail (ignore)": @@ -207,13 +172,6 @@ suite "GossipSub": nodes[1].switch.start(), ) - # start pubsub - await allFuturesThrowing( - allFinished( - nodes[0].start(), - nodes[1].start(), - )) - await subscribeNodes(nodes) nodes[0].subscribe("foobar", handler) @@ -249,11 +207,6 @@ suite "GossipSub": nodes[1].switch.stop() ) - await allFuturesThrowing( - nodes[0].stop(), - nodes[1].stop() - ) - await allFuturesThrowing(nodesFut.concat()) asyncTest "GossipSub validation one fails and one succeeds": @@ -271,13 +224,6 @@ suite "GossipSub": nodes[1].switch.start(), ) - # start pubsub - await allFuturesThrowing( - allFinished( - nodes[0].start(), - nodes[1].start(), - )) - await subscribeNodes(nodes) nodes[1].subscribe("foo", handler) @@ -314,11 +260,6 @@ suite "GossipSub": nodes[1].switch.stop() ) - await allFuturesThrowing( - nodes[0].stop(), - nodes[1].stop() - ) - await allFuturesThrowing(nodesFut.concat()) asyncTest "GossipSub unsub - resub faster than backoff": @@ -336,13 +277,6 @@ suite "GossipSub": nodes[1].switch.start(), ) - # start pubsub - await allFuturesThrowing( - allFinished( - nodes[0].start(), - nodes[1].start(), - )) - await subscribeNodes(nodes) nodes[0].subscribe("foobar", handler) @@ -378,11 +312,6 @@ suite "GossipSub": nodes[1].switch.stop() ) - await allFuturesThrowing( - nodes[0].stop(), - nodes[1].stop() - ) - await allFuturesThrowing(nodesFut.concat()) asyncTest "e2e - GossipSub should add remote peer topic subscriptions": @@ -400,36 +329,24 @@ suite "GossipSub": nodes[1].switch.start(), ) - # start pubsub - await allFuturesThrowing( - allFinished( - nodes[0].start(), - nodes[1].start(), - )) - await subscribeNodes(nodes) nodes[1].subscribe("foobar", handler) - await sleepAsync(10.seconds) let gossip1 = GossipSub(nodes[0]) let gossip2 = GossipSub(nodes[1]) - check: - "foobar" in gossip2.topics - "foobar" in gossip1.gossipsub + check await checkExpiring( + "foobar" in gossip2.topics and + "foobar" in gossip1.gossipsub and gossip1.gossipsub.hasPeerId("foobar", gossip2.peerInfo.peerId) + ) await allFuturesThrowing( nodes[0].switch.stop(), nodes[1].switch.stop() ) - await allFuturesThrowing( - nodes[0].stop(), - nodes[1].stop() - ) - await allFuturesThrowing(nodesFut.concat()) asyncTest "e2e - GossipSub should add remote peer topic subscriptions if both peers are subscribed": @@ -447,13 +364,6 @@ suite "GossipSub": nodes[1].switch.start(), ) - # start pubsub - await allFuturesThrowing( - allFinished( - nodes[0].start(), - nodes[1].start(), - )) - await subscribeNodes(nodes) nodes[0].subscribe("foobar", handler) @@ -487,11 +397,6 @@ suite "GossipSub": nodes[1].switch.stop() ) - await allFuturesThrowing( - nodes[0].stop(), - nodes[1].stop() - ) - await allFuturesThrowing(nodesFut.concat()) asyncTest "e2e - GossipSub send over fanout A -> B": @@ -511,13 +416,6 @@ suite "GossipSub": nodes[1].switch.start(), ) - # start pubsub - await allFuturesThrowing( - allFinished( - nodes[0].start(), - nodes[1].start(), - )) - await subscribeNodes(nodes) nodes[1].subscribe("foobar", handler) @@ -549,19 +447,11 @@ suite "GossipSub": trace "test done, stopping..." - await nodes[0].stop() - await nodes[1].stop() - await allFuturesThrowing( nodes[0].switch.stop(), nodes[1].switch.stop() ) - await allFuturesThrowing( - nodes[0].stop(), - nodes[1].stop() - ) - await allFuturesThrowing(nodesFut.concat()) check observed == 2 @@ -583,13 +473,6 @@ suite "GossipSub": nodes[1].switch.start(), ) - # start pubsub - await allFuturesThrowing( - allFinished( - nodes[0].start(), - nodes[1].start(), - )) - await subscribeNodes(nodes) nodes[1].subscribe("foobar", handler) @@ -616,19 +499,11 @@ suite "GossipSub": trace "test done, stopping..." - await nodes[0].stop() - await nodes[1].stop() - await allFuturesThrowing( nodes[0].switch.stop(), nodes[1].switch.stop() ) - await allFuturesThrowing( - nodes[0].stop(), - nodes[1].stop() - ) - await allFuturesThrowing(nodesFut.concat()) asyncTest "e2e - GossipSub send over mesh A -> B": @@ -648,13 +523,6 @@ suite "GossipSub": nodes[1].switch.start(), ) - # start pubsub - await allFuturesThrowing( - allFinished( - nodes[0].start(), - nodes[1].start(), - )) - await subscribeNodes(nodes) nodes[0].subscribe("foobar", handler) @@ -681,11 +549,6 @@ suite "GossipSub": nodes[1].switch.stop() ) - await allFuturesThrowing( - nodes[0].stop(), - nodes[1].stop() - ) - await allFuturesThrowing(nodesFut.concat()) asyncTest "e2e - GossipSub should not send to source & peers who already seen": @@ -705,14 +568,6 @@ suite "GossipSub": nodes[2].switch.start(), ) - # start pubsub - await allFuturesThrowing( - allFinished( - nodes[0].start(), - nodes[1].start(), - nodes[2].start(), - )) - await subscribeNodes(nodes) var cRelayed: Future[void] = newFuture[void]() @@ -763,12 +618,6 @@ suite "GossipSub": nodes[2].switch.stop() ) - await allFuturesThrowing( - nodes[0].stop(), - nodes[1].stop(), - nodes[2].stop() - ) - await allFuturesThrowing(nodesFut.concat()) asyncTest "e2e - GossipSub send over floodPublish A -> B": @@ -788,13 +637,6 @@ suite "GossipSub": nodes[1].switch.start(), ) - # start pubsub - await allFuturesThrowing( - allFinished( - nodes[0].start(), - nodes[1].start(), - )) - var gossip1: GossipSub = GossipSub(nodes[0]) gossip1.parameters.floodPublish = true var gossip2: GossipSub = GossipSub(nodes[1]) @@ -821,11 +663,6 @@ suite "GossipSub": nodes[1].switch.stop() ) - await allFuturesThrowing( - nodes[0].stop(), - nodes[1].stop() - ) - await allFuturesThrowing(nodesFut.concat()) asyncTest "e2e - GossipSub with multiple peers": @@ -835,7 +672,6 @@ suite "GossipSub": nodes = generateNodes(runs, gossip = true, triggerSelf = true) nodesFut = nodes.mapIt(it.switch.start()) - await allFuturesThrowing(nodes.mapIt(it.start())) await subscribeNodes(nodes) var seen: Table[string, int] @@ -859,7 +695,7 @@ suite "GossipSub": tryPublish await wait(nodes[0].publish("foobar", toBytes("from node " & $nodes[0].peerInfo.peerId)), - 1.minutes), 1, 5.seconds + 1.minutes), 1 await wait(seenFut, 2.minutes) check: seen.len >= runs @@ -875,7 +711,6 @@ suite "GossipSub": await allFuturesThrowing( nodes.mapIt( allFutures( - it.stop(), it.switch.stop()))) await allFuturesThrowing(nodesFut) @@ -887,7 +722,6 @@ suite "GossipSub": nodes = generateNodes(runs, gossip = true, triggerSelf = true) nodesFut = nodes.mapIt(it.switch.start()) - await allFuturesThrowing(nodes.mapIt(it.start())) await subscribeSparseNodes(nodes) var seen: Table[string, int] @@ -911,7 +745,7 @@ suite "GossipSub": tryPublish await wait(nodes[0].publish("foobar", toBytes("from node " & $nodes[0].peerInfo.peerId)), - 1.minutes), 1, 5.seconds + 1.minutes), 1 await wait(seenFut, 5.minutes) check: seen.len >= runs @@ -928,7 +762,6 @@ suite "GossipSub": await allFuturesThrowing( nodes.mapIt( allFutures( - it.stop(), it.switch.stop()))) await allFuturesThrowing(nodesFut) @@ -956,14 +789,6 @@ suite "GossipSub": nodes[2].switch.start(), ) - # start pubsub - await allFuturesThrowing( - allFinished( - nodes[0].start(), - nodes[1].start(), - nodes[2].start(), - )) - var gossip0 = GossipSub(nodes[0]) gossip1 = GossipSub(nodes[1]) @@ -997,11 +822,4 @@ suite "GossipSub": nodes[2].switch.stop() ) - await allFuturesThrowing( - nodes[0].stop(), - nodes[1].stop(), - nodes[2].stop() - ) - await allFuturesThrowing(nodesFut.concat()) - diff --git a/vendor/nim-libp2p/tests/pubsub/testgossipsub2.nim b/vendor/nim-libp2p/tests/pubsub/testgossipsub2.nim index 70d44b865..3f21196e0 100644 --- a/vendor/nim-libp2p/tests/pubsub/testgossipsub2.nim +++ b/vendor/nim-libp2p/tests/pubsub/testgossipsub2.nim @@ -1,11 +1,11 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. {.used.} @@ -28,18 +28,11 @@ import ../helpers proc waitSub(sender, receiver: auto; key: string) {.async, gcsafe.} = if sender == receiver: return - # turn things deterministic + let timeout = Moment.now() + 5.seconds + let fsub = GossipSub(sender) + # this is for testing purposes only # peers can be inside `mesh` and `fanout`, not just `gossipsub` - var ceil = 15 - let fsub = GossipSub(sender) - let ev = newAsyncEvent() - fsub.heartbeatEvents.add(ev) - - # await first heartbeat - await ev.wait() - ev.clear() - while (not fsub.gossipsub.hasKey(key) or not fsub.gossipsub.hasPeerId(key, receiver.peerInfo.peerId)) and (not fsub.mesh.hasKey(key) or @@ -48,23 +41,19 @@ proc waitSub(sender, receiver: auto; key: string) {.async, gcsafe.} = not fsub.fanout.hasPeerId(key , receiver.peerInfo.peerId)): trace "waitSub sleeping..." - # await more heartbeats - await ev.wait() - ev.clear() + # await + await sleepAsync(5.milliseconds) + doAssert Moment.now() < timeout, "waitSub timeout!" - dec ceil - doAssert(ceil > 0, "waitSub timeout!") - -template tryPublish(call: untyped, require: int, wait: Duration = 1.seconds, times: int = 10): untyped = +template tryPublish(call: untyped, require: int, wait = 10.milliseconds, timeout = 10.seconds): untyped = var - limit = times + expiration = Moment.now() + timeout pubs = 0 - while pubs < require and limit > 0: + while pubs < require and Moment.now() < expiration: pubs = pubs + call await sleepAsync(wait) - limit.dec() - if limit == 0: - doAssert(false, "Failed to publish!") + + doAssert pubs >= require, "Failed to publish!" suite "GossipSub": teardown: @@ -77,7 +66,6 @@ suite "GossipSub": nodes = generateNodes(runs, gossip = true, triggerSelf = true) nodesFut = nodes.mapIt(it.switch.start()) - await allFuturesThrowing(nodes.mapIt(it.start())) await subscribeSparseNodes(nodes) var seen: Table[string, int] @@ -120,7 +108,6 @@ suite "GossipSub": await allFuturesThrowing( nodes.mapIt( allFutures( - it.stop(), it.switch.stop()))) await allFuturesThrowing(nodesFut) @@ -140,13 +127,6 @@ suite "GossipSub": nodes[1].switch.start(), ) - # start pubsub - await allFuturesThrowing( - allFinished( - nodes[0].start(), - nodes[1].start(), - )) - # We must subscribe before setting the validator nodes[0].subscribe("foobar", handler) @@ -174,36 +154,15 @@ suite "GossipSub": nodes[1].switch.stop() ) - await allFuturesThrowing( - nodes[0].stop(), - nodes[1].stop() - ) - await allFuturesThrowing(nodesFut.concat()) asyncTest "GossipSub test directPeers": - - let - nodes = generateNodes(2, gossip = true) - - # start switches - nodesFut = await allFinished( - nodes[0].switch.start(), - nodes[1].switch.start(), - ) - - var gossip = GossipSub(nodes[0]) - gossip.parameters.directPeers[nodes[1].switch.peerInfo.peerId] = nodes[1].switch.peerInfo.addrs - - # start pubsub - await allFuturesThrowing( - allFinished( - nodes[0].start(), - nodes[1].start(), - )) + let nodes = generateNodes(2, gossip = true) + await allFutures(nodes[0].switch.start(), nodes[1].switch.start()) + await GossipSub(nodes[0]).addDirectPeer(nodes[1].switch.peerInfo.peerId, nodes[1].switch.peerInfo.addrs) let invalidDetected = newFuture[void]() - gossip.subscriptionValidator = + GossipSub(nodes[0]).subscriptionValidator = proc(topic: string): bool = if topic == "foobar": try: @@ -227,13 +186,6 @@ suite "GossipSub": nodes[1].switch.stop() ) - await allFuturesThrowing( - nodes[0].stop(), - nodes[1].stop() - ) - - await allFuturesThrowing(nodesFut.concat()) - asyncTest "GossipSub directPeers: always forward messages": let nodes = generateNodes(2, gossip = true) @@ -244,15 +196,8 @@ suite "GossipSub": nodes[1].switch.start(), ) - GossipSub(nodes[0]).parameters.directPeers[nodes[1].switch.peerInfo.peerId] = nodes[1].switch.peerInfo.addrs - GossipSub(nodes[1]).parameters.directPeers[nodes[0].switch.peerInfo.peerId] = nodes[0].switch.peerInfo.addrs - - # start pubsub - await allFuturesThrowing( - allFinished( - nodes[0].start(), - nodes[1].start(), - )) + await GossipSub(nodes[0]).addDirectPeer(nodes[1].switch.peerInfo.peerId, nodes[1].switch.peerInfo.addrs) + await GossipSub(nodes[1]).addDirectPeer(nodes[0].switch.peerInfo.peerId, nodes[0].switch.peerInfo.addrs) var handlerFut = newFuture[void]() proc handler(topic: string, data: seq[byte]) {.async, gcsafe.} = @@ -275,11 +220,6 @@ suite "GossipSub": nodes[1].switch.stop() ) - await allFuturesThrowing( - nodes[0].stop(), - nodes[1].stop() - ) - await allFuturesThrowing(nodesFut.concat()) asyncTest "GossipSub directPeers: don't kick direct peer with low score": @@ -292,19 +232,12 @@ suite "GossipSub": nodes[1].switch.start(), ) - GossipSub(nodes[0]).parameters.directPeers[nodes[1].switch.peerInfo.peerId] = nodes[1].switch.peerInfo.addrs - GossipSub(nodes[1]).parameters.directPeers[nodes[0].switch.peerInfo.peerId] = nodes[0].switch.peerInfo.addrs + await GossipSub(nodes[0]).addDirectPeer(nodes[1].switch.peerInfo.peerId, nodes[1].switch.peerInfo.addrs) + await GossipSub(nodes[1]).addDirectPeer(nodes[0].switch.peerInfo.peerId, nodes[0].switch.peerInfo.addrs) GossipSub(nodes[1]).parameters.disconnectBadPeers = true GossipSub(nodes[1]).parameters.graylistThreshold = 100000 - # start pubsub - await allFuturesThrowing( - allFinished( - nodes[0].start(), - nodes[1].start(), - )) - var handlerFut = newFuture[void]() proc handler(topic: string, data: seq[byte]) {.async, gcsafe.} = check topic == "foobar" @@ -334,11 +267,6 @@ suite "GossipSub": nodes[1].switch.stop() ) - await allFuturesThrowing( - nodes[0].stop(), - nodes[1].stop() - ) - await allFuturesThrowing(nodesFut.concat()) asyncTest "GossipsSub peers disconnections mechanics": @@ -348,7 +276,6 @@ suite "GossipSub": nodes = generateNodes(runs, gossip = true, triggerSelf = true) nodesFut = nodes.mapIt(it.switch.start()) - await allFuturesThrowing(nodes.mapIt(it.start())) await subscribeNodes(nodes) var seen: Table[string, int] @@ -376,7 +303,7 @@ suite "GossipSub": tryPublish await wait(nodes[0].publish("foobar", toBytes("from node " & $nodes[0].peerInfo.peerId)), - 1.minutes), 1, 5.seconds + 1.minutes), 1, 5.seconds, 3.minutes await wait(seenFut, 5.minutes) check: seen.len >= runs @@ -399,11 +326,9 @@ suite "GossipSub": # Waiting 2 heartbeats for _ in 0..1: - for i in 0.. 0 and m.fromPeer.data.len > 0: byteutils.toHex(m.seqno) & $m.fromPeer @@ -26,7 +26,7 @@ func defaultMsgIdProvider*(m: Message): Result[MessageID, ValidationResult] = # This part is irrelevant because it's not standard, # We use it exclusively for testing basically and users should # implement their own logic in the case they use anonymization - $m.data.hash & $m.topicIDs.hash + $m.data.hash & $m.topicIds.hash ok mid.toBytes() proc generateNodes*( diff --git a/vendor/nim-libp2p/tests/stublogger.nim b/vendor/nim-libp2p/tests/stublogger.nim new file mode 100644 index 000000000..ef796c375 --- /dev/null +++ b/vendor/nim-libp2p/tests/stublogger.nim @@ -0,0 +1,10 @@ +import std/typetraits +import chronicles + +when defined(chronicles_runtime_filtering): + setLogLevel(INFO) + +when defaultChroniclesStream.outputs.type.arity == 1: + # Hide the json logs, they're just here to check if we compile + proc noOutput(logLevel: LogLevel, msg: LogOutputStr) = discard + defaultChroniclesStream.outputs[0].writer = noOutput \ No newline at end of file diff --git a/vendor/nim-libp2p/tests/testautonat.nim b/vendor/nim-libp2p/tests/testautonat.nim new file mode 100644 index 000000000..8d523fae4 --- /dev/null +++ b/vendor/nim-libp2p/tests/testautonat.nim @@ -0,0 +1,59 @@ +import std/options +import chronos +import + ../libp2p/[ + builders, + protocols/autonat + ], + ./helpers + +proc createAutonatSwitch(): Switch = + result = SwitchBuilder.new() + .withRng(newRng()) + .withAddresses(@[ MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() ]) + .withTcpTransport() + .withMplex() + .withAutonat() + .withNoise() + .build() + +proc makeAutonatServicePrivate(): Switch = + var autonatProtocol = new LPProtocol + autonatProtocol.handler = proc (conn: Connection, proto: string) {.async, gcsafe.} = + discard await conn.readLp(1024) + await conn.writeLp(AutonatDialResponse( + status: DialError, + text: some("dial failed"), + ma: none(MultiAddress)).encode().buffer) + await conn.close() + autonatProtocol.codec = AutonatCodec + result = newStandardSwitch() + result.mount(autonatProtocol) + +suite "Autonat": + teardown: + checkTrackers() + + asyncTest "Simple test": + let + src = newStandardSwitch() + dst = createAutonatSwitch() + await src.start() + await dst.start() + + await src.connect(dst.peerInfo.peerId, dst.peerInfo.addrs) + let ma = await Autonat.new(src).dialMe(dst.peerInfo.peerId, dst.peerInfo.addrs) + await allFutures(src.stop(), dst.stop()) + + asyncTest "Simple failed test": + let + src = newStandardSwitch() + dst = makeAutonatServicePrivate() + + await src.start() + await dst.start() + + await src.connect(dst.peerInfo.peerId, dst.peerInfo.addrs) + expect AutonatError: + discard await Autonat.new(src).dialMe(dst.peerInfo.peerId, dst.peerInfo.addrs) + await allFutures(src.stop(), dst.stop()) diff --git a/vendor/nim-libp2p/tests/testconnmngr.nim b/vendor/nim-libp2p/tests/testconnmngr.nim index 6aaa4edb0..5c705bf36 100644 --- a/vendor/nim-libp2p/tests/testconnmngr.nim +++ b/vendor/nim-libp2p/tests/testconnmngr.nim @@ -243,253 +243,131 @@ suite "Connection Manager": asyncTest "track total incoming connection limits": let connMngr = ConnManager.new(maxConnections = 3) - var conns: seq[Connection] for i in 0..<3: - let conn = connMngr.trackIncomingConn( - proc(): Future[Connection] {.async.} = - return Connection.new( - PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(), - Direction.In) - ) - - check await conn.withTimeout(10.millis) - conns.add(await conn) + check await connMngr.getIncomingSlot().withTimeout(10.millis) # should timeout adding a connection over the limit - let conn = connMngr.trackIncomingConn( - proc(): Future[Connection] {.async.} = - return Connection.new( - PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(), - Direction.In) - ) - - check not(await conn.withTimeout(10.millis)) + check not(await connMngr.getIncomingSlot().withTimeout(10.millis)) await connMngr.close() - await allFuturesThrowing( - allFutures(conns.mapIt( it.close() ))) asyncTest "track total outgoing connection limits": let connMngr = ConnManager.new(maxConnections = 3) - var conns: seq[Connection] for i in 0..<3: - let conn = await connMngr.trackOutgoingConn( - proc(): Future[Connection] {.async.} = - return Connection.new( - PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(), - Direction.In) - ) - - conns.add(conn) + check await connMngr.getOutgoingSlot().withTimeout(10.millis) # should throw adding a connection over the limit expect TooManyConnectionsError: - discard await connMngr.trackOutgoingConn( - proc(): Future[Connection] {.async.} = - return Connection.new( - PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(), - Direction.In) - ) + discard await connMngr.getOutgoingSlot() await connMngr.close() - await allFuturesThrowing( - allFutures(conns.mapIt( it.close() ))) asyncTest "track both incoming and outgoing total connections limits - fail on incoming": let connMngr = ConnManager.new(maxConnections = 3) - var conns: seq[Connection] for i in 0..<3: - let conn = await connMngr.trackOutgoingConn( - proc(): Future[Connection] {.async.} = - return Connection.new( - PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(), - Direction.In) - ) - - conns.add(conn) + check await connMngr.getOutgoingSlot().withTimeout(10.millis) # should timeout adding a connection over the limit - let conn = connMngr.trackIncomingConn( - proc(): Future[Connection] {.async.} = - return Connection.new( - PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(), - Direction.In) - ) - - check not(await conn.withTimeout(10.millis)) + check not(await connMngr.getIncomingSlot().withTimeout(10.millis)) await connMngr.close() - await allFuturesThrowing( - allFutures(conns.mapIt( it.close() ))) asyncTest "track both incoming and outgoing total connections limits - fail on outgoing": let connMngr = ConnManager.new(maxConnections = 3) - var conns: seq[Connection] for i in 0..<3: - let conn = connMngr.trackIncomingConn( - proc(): Future[Connection] {.async.} = - return Connection.new( - PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(), - Direction.In) - ) - - check await conn.withTimeout(10.millis) - conns.add(await conn) + check await connMngr.getIncomingSlot().withTimeout(10.millis) # should throw adding a connection over the limit expect TooManyConnectionsError: - discard await connMngr.trackOutgoingConn( - proc(): Future[Connection] {.async.} = - return Connection.new( - PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(), - Direction.In) - ) + discard await connMngr.getOutgoingSlot() await connMngr.close() - await allFuturesThrowing( - allFutures(conns.mapIt( it.close() ))) asyncTest "track max incoming connection limits": let connMngr = ConnManager.new(maxIn = 3) - var conns: seq[Connection] for i in 0..<3: - let conn = connMngr.trackIncomingConn( - proc(): Future[Connection] {.async.} = - return Connection.new( - PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(), - Direction.In) - ) + check await connMngr.getIncomingSlot().withTimeout(10.millis) - check await conn.withTimeout(10.millis) - conns.add(await conn) - - # should timeout adding a connection over the limit - let conn = connMngr.trackIncomingConn( - proc(): Future[Connection] {.async.} = - return Connection.new( - PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(), - Direction.In) - ) - - check not(await conn.withTimeout(10.millis)) + check not(await connMngr.getIncomingSlot().withTimeout(10.millis)) await connMngr.close() - await allFuturesThrowing( - allFutures(conns.mapIt( it.close() ))) asyncTest "track max outgoing connection limits": let connMngr = ConnManager.new(maxOut = 3) - var conns: seq[Connection] for i in 0..<3: - let conn = await connMngr.trackOutgoingConn( - proc(): Future[Connection] {.async.} = - return Connection.new( - PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(), - Direction.In) - ) - - conns.add(conn) + check await connMngr.getOutgoingSlot().withTimeout(10.millis) # should throw adding a connection over the limit expect TooManyConnectionsError: - discard await connMngr.trackOutgoingConn( - proc(): Future[Connection] {.async.} = - return Connection.new( - PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(), - Direction.In) - ) + discard await connMngr.getOutgoingSlot() await connMngr.close() - await allFuturesThrowing( - allFutures(conns.mapIt( it.close() ))) asyncTest "track incoming max connections limits - fail on incoming": let connMngr = ConnManager.new(maxOut = 3) - var conns: seq[Connection] for i in 0..<3: - let conn = await connMngr.trackOutgoingConn( - proc(): Future[Connection] {.async.} = - return Connection.new( - PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(), - Direction.In) - ) - - conns.add(conn) + check await connMngr.getOutgoingSlot().withTimeout(10.millis) # should timeout adding a connection over the limit - let conn = connMngr.trackIncomingConn( - proc(): Future[Connection] {.async.} = - return Connection.new( - PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(), - Direction.In) - ) - - check not(await conn.withTimeout(10.millis)) + check not(await connMngr.getIncomingSlot().withTimeout(10.millis)) await connMngr.close() - await allFuturesThrowing( - allFutures(conns.mapIt( it.close() ))) asyncTest "track incoming max connections limits - fail on outgoing": let connMngr = ConnManager.new(maxIn = 3) var conns: seq[Connection] for i in 0..<3: - let conn = connMngr.trackIncomingConn( - proc(): Future[Connection] {.async.} = - return Connection.new( - PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(), - Direction.In) - ) - - check await conn.withTimeout(10.millis) - conns.add(await conn) + check await connMngr.getIncomingSlot().withTimeout(10.millis) # should throw adding a connection over the limit expect TooManyConnectionsError: - discard await connMngr.trackOutgoingConn( - proc(): Future[Connection] {.async.} = - return Connection.new( - PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(), - Direction.In) - ) + discard await connMngr.getOutgoingSlot() await connMngr.close() - await allFuturesThrowing( - allFutures(conns.mapIt( it.close() ))) asyncTest "allow force dial": let connMngr = ConnManager.new(maxConnections = 2) var conns: seq[Connection] for i in 0..<3: - let conn = connMngr.trackOutgoingConn( - (proc(): Future[Connection] {.async.} = - return Connection.new( - PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(), - Direction.In) - ), true - ) - - check await conn.withTimeout(10.millis) - conns.add(await conn) + check await connMngr.getOutgoingSlot(true).withTimeout(10.millis) # should throw adding a connection over the limit expect TooManyConnectionsError: - discard await connMngr.trackOutgoingConn( - (proc(): Future[Connection] {.async.} = - return Connection.new( - PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(), - Direction.In) - ), false - ) + discard await connMngr.getOutgoingSlot(false) await connMngr.close() + + asyncTest "release slot on connection end": + let connMngr = ConnManager.new(maxConnections = 3) + + var conns: seq[Connection] + for i in 0..<3: + let slot = await ((connMngr.getOutgoingSlot()).wait(10.millis)) + + let conn = + Connection.new( + PeerId.init(PrivateKey.random(ECDSA, (newRng())[]).tryGet()).tryGet(), + Direction.In) + + slot.trackConnection(conn) + conns.add(conn) + + # should be full now + let incomingSlot = connMngr.getIncomingSlot() + + check (await incomingSlot.withTimeout(10.millis)) == false + await allFuturesThrowing( allFutures(conns.mapIt( it.close() ))) + + check await incomingSlot.withTimeout(10.millis) + + await connMngr.close() diff --git a/vendor/nim-libp2p/tests/testcrypto.nim b/vendor/nim-libp2p/tests/testcrypto.nim index cc72e1a83..b9a6ecfa4 100644 --- a/vendor/nim-libp2p/tests/testcrypto.nim +++ b/vendor/nim-libp2p/tests/testcrypto.nim @@ -1,18 +1,18 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. ## Test vectors was made using Go implementation ## https://github.com/libp2p/go-libp2p-crypto/blob/master/key.go import unittest2 +import bearssl/hash import nimcrypto/[utils, sysrand] import ../libp2p/crypto/[crypto, chacha20poly1305, curve25519, hkdf] -import bearssl when defined(nimHasUsed): {.used.} @@ -560,7 +560,7 @@ suite "Key interface test suite": test "shuffle": var cards = ["Ace", "King", "Queen", "Jack", "Ten"] - var rng = (ref BrHmacDrbgContext)() - brHmacDrbgInit(addr rng[], addr sha256Vtable, nil, 0) + var rng = (ref HmacDrbgContext)() + hmacDrbgInit(rng[], addr sha256Vtable, nil, 0) rng.shuffle(cards) check cards == ["King", "Ten", "Ace", "Queen", "Jack"] diff --git a/vendor/nim-libp2p/tests/testdaemon.nim b/vendor/nim-libp2p/tests/testdaemon.nim index 5c1da3d8b..10b80a29b 100644 --- a/vendor/nim-libp2p/tests/testdaemon.nim +++ b/vendor/nim-libp2p/tests/testdaemon.nim @@ -1,4 +1,4 @@ -import chronos, unittest2, helpers +import chronos, unittest2, helpers, stublogger import ../libp2p/daemon/daemonapi, ../libp2p/multiaddress, ../libp2p/multicodec, ../libp2p/cid, ../libp2p/multihash, ../libp2p/peerid diff --git a/vendor/nim-libp2p/tests/testecnist.nim b/vendor/nim-libp2p/tests/testecnist.nim index 76999a4f3..339de4c43 100644 --- a/vendor/nim-libp2p/tests/testecnist.nim +++ b/vendor/nim-libp2p/tests/testecnist.nim @@ -1,11 +1,11 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. import unittest2 import nimcrypto/utils import ../libp2p/crypto/[crypto, ecnist] diff --git a/vendor/nim-libp2p/tests/tested25519.nim b/vendor/nim-libp2p/tests/tested25519.nim index 1dde4fc3d..8b269f916 100644 --- a/vendor/nim-libp2p/tests/tested25519.nim +++ b/vendor/nim-libp2p/tests/tested25519.nim @@ -1,11 +1,11 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. ## Test vectors are from RFC 8032 (https://tools.ietf.org/html/rfc8032) import unittest2 diff --git a/vendor/nim-libp2p/tests/testidentify.nim b/vendor/nim-libp2p/tests/testidentify.nim index 96ea1c293..8fc529204 100644 --- a/vendor/nim-libp2p/tests/testidentify.nim +++ b/vendor/nim-libp2p/tests/testidentify.nim @@ -1,4 +1,4 @@ -import options, bearssl +import options import chronos, strutils, sequtils, sets, algorithm import ../libp2p/[protocols/identify, multiaddress, diff --git a/vendor/nim-libp2p/tests/testinterop.nim b/vendor/nim-libp2p/tests/testinterop.nim index cecace6d0..5cbd53d5a 100644 --- a/vendor/nim-libp2p/tests/testinterop.nim +++ b/vendor/nim-libp2p/tests/testinterop.nim @@ -1,628 +1,57 @@ -import options, tables -import chronos, chronicles, stew/byteutils -import helpers +import stublogger + +import helpers, commoninterop import ../libp2p -import ../libp2p/[daemon/daemonapi, varint, transports/wstransport, crypto/crypto, protocols/relay ] - -type - DaemonPeerInfo = daemonapi.PeerInfo - -proc writeLp*(s: StreamTransport, msg: string | seq[byte]): Future[int] {.gcsafe.} = - ## write lenght prefixed - var buf = initVBuffer() - buf.writeSeq(msg) - buf.finish() - result = s.write(buf.buffer) - -proc readLp*(s: StreamTransport): Future[seq[byte]] {.async, gcsafe.} = - ## read length prefixed msg - var - size: uint - length: int - res: VarintResult[void] - result = newSeq[byte](10) - - for i in 0.. 0.uint: - await s.readExactly(addr result[0], int(size)) - -proc testPubSubDaemonPublish(gossip: bool = false, count: int = 1) {.async.} = - var pubsubData = "TEST MESSAGE" - var testTopic = "test-topic" - var msgData = pubsubData.toBytes() - - var flags = {PSFloodSub} - if gossip: - flags = {PSGossipSub} - - let daemonNode = await newDaemonApi(flags) - let daemonPeer = await daemonNode.identity() - let nativeNode = newStandardSwitch(outTimeout = 5.minutes) - - let pubsub = if gossip: - GossipSub.init( - switch = nativeNode).PubSub - else: - FloodSub.init( - switch = nativeNode).PubSub - - nativeNode.mount(pubsub) - - await nativeNode.start() - await pubsub.start() - let nativePeer = nativeNode.peerInfo - - var finished = false - var times = 0 - proc nativeHandler(topic: string, data: seq[byte]) {.async.} = - let smsg = string.fromBytes(data) - check smsg == pubsubData - times.inc() - if times >= count and not finished: - finished = true - - await nativeNode.connect(daemonPeer.peer, daemonPeer.addresses) - - await sleepAsync(1.seconds) - await daemonNode.connect(nativePeer.peerId, nativePeer.addrs) - - proc pubsubHandler(api: DaemonAPI, - ticket: PubsubTicket, - message: PubSubMessage): Future[bool] {.async.} = - result = true # don't cancel subscription - - asyncDiscard daemonNode.pubsubSubscribe(testTopic, pubsubHandler) - pubsub.subscribe(testTopic, nativeHandler) - await sleepAsync(5.seconds) - - proc publisher() {.async.} = - while not finished: - await daemonNode.pubsubPublish(testTopic, msgData) - await sleepAsync(500.millis) - - await wait(publisher(), 5.minutes) # should be plenty of time - - await nativeNode.stop() - await pubsub.stop() - await daemonNode.close() - -proc testPubSubNodePublish(gossip: bool = false, count: int = 1) {.async.} = - var pubsubData = "TEST MESSAGE" - var testTopic = "test-topic" - var msgData = pubsubData.toBytes() - - var flags = {PSFloodSub} - if gossip: - flags = {PSGossipSub} - - let daemonNode = await newDaemonApi(flags) - let daemonPeer = await daemonNode.identity() - let nativeNode = newStandardSwitch(outTimeout = 5.minutes) - - let pubsub = if gossip: - GossipSub.init( - switch = nativeNode).PubSub - else: - FloodSub.init( - switch = nativeNode).PubSub - - nativeNode.mount(pubsub) - - await nativeNode.start() - await pubsub.start() - let nativePeer = nativeNode.peerInfo - - await nativeNode.connect(daemonPeer.peer, daemonPeer.addresses) - - await sleepAsync(1.seconds) - await daemonNode.connect(nativePeer.peerId, nativePeer.addrs) - - var times = 0 - var finished = false - proc pubsubHandler(api: DaemonAPI, - ticket: PubsubTicket, - message: PubSubMessage): Future[bool] {.async.} = - let smsg = string.fromBytes(message.data) - check smsg == pubsubData - times.inc() - if times >= count and not finished: - finished = true - result = true # don't cancel subscription - - discard await daemonNode.pubsubSubscribe(testTopic, pubsubHandler) - proc nativeHandler(topic: string, data: seq[byte]) {.async.} = discard - pubsub.subscribe(testTopic, nativeHandler) - await sleepAsync(5.seconds) - - proc publisher() {.async.} = - while not finished: - discard await pubsub.publish(testTopic, msgData) - await sleepAsync(500.millis) - - await wait(publisher(), 5.minutes) # should be plenty of time - - check finished - await nativeNode.stop() - await pubsub.stop() - await daemonNode.close() - -suite "Interop": - # TODO: chronos transports are leaking, - # but those are tracked for both the daemon - # and libp2p, so not sure which one it is, - # need to investigate more - # teardown: - # checkTrackers() - - # TODO: this test is failing sometimes on windows - # For some reason we receive EOF before test 4 sometimes - asyncTest "native -> daemon multiple reads and writes": - var protos = @["/test-stream"] - - let nativeNode = newStandardSwitch( - secureManagers = [SecureProtocol.Noise], - outTimeout = 5.minutes) - - await nativeNode.start() - let daemonNode = await newDaemonApi() - let daemonPeer = await daemonNode.identity() - - var testFuture = newFuture[void]("test.future") - proc daemonHandler(api: DaemonAPI, stream: P2PStream) {.async.} = - check string.fromBytes(await stream.transp.readLp()) == "test 1" - discard await stream.transp.writeLp("test 2") - check string.fromBytes(await stream.transp.readLp()) == "test 3" - discard await stream.transp.writeLp("test 4") - testFuture.complete() - - await daemonNode.addHandler(protos, daemonHandler) - let conn = await nativeNode.dial(daemonPeer.peer, daemonPeer.addresses, protos[0]) - await conn.writeLp("test 1") - check "test 2" == string.fromBytes((await conn.readLp(1024))) - - await conn.writeLp("test 3") - check "test 4" == string.fromBytes((await conn.readLp(1024))) - - await wait(testFuture, 10.secs) - - await nativeNode.stop() - await daemonNode.close() - - await sleepAsync(1.seconds) - - asyncTest "native -> daemon connection": - var protos = @["/test-stream"] - var test = "TEST STRING" - # We are preparing expect string, which should be prefixed with varint - # length and do not have `\r\n` suffix, because we going to use - # readLine(). - var buffer = initVBuffer() - buffer.writeSeq(test & "\r\n") - buffer.finish() - var expect = newString(len(buffer) - 2) - copyMem(addr expect[0], addr buffer.buffer[0], len(expect)) - - let nativeNode = newStandardSwitch( - secureManagers = [SecureProtocol.Noise], - outTimeout = 5.minutes) - - await nativeNode.start() - - let daemonNode = await newDaemonApi() - let daemonPeer = await daemonNode.identity() - - var testFuture = newFuture[string]("test.future") - proc daemonHandler(api: DaemonAPI, stream: P2PStream) {.async.} = - # We should perform `readLp()` instead of `readLine()`. `readLine()` - # here reads actually length prefixed string. - var line = await stream.transp.readLine() - check line == expect - testFuture.complete(line) - await stream.close() - - await daemonNode.addHandler(protos, daemonHandler) - let conn = await nativeNode.dial(daemonPeer.peer, daemonPeer.addresses, protos[0]) - await conn.writeLp(test & "\r\n") - check expect == (await wait(testFuture, 10.secs)) - - await conn.close() - await nativeNode.stop() - await daemonNode.close() - - asyncTest "daemon -> native connection": - var protos = @["/test-stream"] - var test = "TEST STRING" - - var testFuture = newFuture[string]("test.future") - proc nativeHandler(conn: Connection, proto: string) {.async.} = - var line = string.fromBytes(await conn.readLp(1024)) - check line == test - testFuture.complete(line) - await conn.close() - - # custom proto - var proto = new LPProtocol - proto.handler = nativeHandler - proto.codec = protos[0] # codec - - let nativeNode = newStandardSwitch( - secureManagers = [SecureProtocol.Noise], outTimeout = 5.minutes) - - nativeNode.mount(proto) - - await nativeNode.start() - let nativePeer = nativeNode.peerInfo - - let daemonNode = await newDaemonApi() - await daemonNode.connect(nativePeer.peerId, nativePeer.addrs) - var stream = await daemonNode.openStream(nativePeer.peerId, protos) - discard await stream.transp.writeLp(test) - - check test == (await wait(testFuture, 10.secs)) - - await stream.close() - await nativeNode.stop() - await daemonNode.close() - await sleepAsync(1.seconds) - - asyncTest "native -> daemon websocket connection": - var protos = @["/test-stream"] - var test = "TEST STRING" - - var testFuture = newFuture[string]("test.future") - proc nativeHandler(conn: Connection, proto: string) {.async.} = - var line = string.fromBytes(await conn.readLp(1024)) - check line == test - testFuture.complete(line) - await conn.close() - - # custom proto - var proto = new LPProtocol - proto.handler = nativeHandler - proto.codec = protos[0] # codec - - let wsAddress = MultiAddress.init("/ip4/127.0.0.1/tcp/0/ws").tryGet() - - let nativeNode = SwitchBuilder - .new() - .withAddress(wsAddress) - .withRng(crypto.newRng()) - .withMplex() - .withTransport(proc (upgr: Upgrade): Transport = WsTransport.new(upgr)) - .withNoise() - .build() - - nativeNode.mount(proto) - - await nativeNode.start() - let nativePeer = nativeNode.peerInfo - - let daemonNode = await newDaemonApi(hostAddresses = @[wsAddress]) - await daemonNode.connect(nativePeer.peerId, nativePeer.addrs) - var stream = await daemonNode.openStream(nativePeer.peerId, protos) - discard await stream.transp.writeLp(test) - - check test == (await wait(testFuture, 10.secs)) - - await stream.close() - await nativeNode.stop() - await daemonNode.close() - await sleepAsync(1.seconds) - - asyncTest "daemon -> native websocket connection": - var protos = @["/test-stream"] - var test = "TEST STRING" - # We are preparing expect string, which should be prefixed with varint - # length and do not have `\r\n` suffix, because we going to use - # readLine(). - var buffer = initVBuffer() - buffer.writeSeq(test & "\r\n") - buffer.finish() - var expect = newString(len(buffer) - 2) - copyMem(addr expect[0], addr buffer.buffer[0], len(expect)) - - let wsAddress = MultiAddress.init("/ip4/127.0.0.1/tcp/0/ws").tryGet() - let nativeNode = SwitchBuilder - .new() - .withAddress(wsAddress) - .withRng(crypto.newRng()) - .withMplex() - .withTransport(proc (upgr: Upgrade): Transport = WsTransport.new(upgr)) - .withNoise() - .build() - - await nativeNode.start() - - let daemonNode = await newDaemonApi(hostAddresses = @[wsAddress]) - let daemonPeer = await daemonNode.identity() - - var testFuture = newFuture[string]("test.future") - proc daemonHandler(api: DaemonAPI, stream: P2PStream) {.async.} = - # We should perform `readLp()` instead of `readLine()`. `readLine()` - # here reads actually length prefixed string. - var line = await stream.transp.readLine() - check line == expect - testFuture.complete(line) - await stream.close() - - await daemonNode.addHandler(protos, daemonHandler) - let conn = await nativeNode.dial(daemonPeer.peer, daemonPeer.addresses, protos[0]) - await conn.writeLp(test & "\r\n") - check expect == (await wait(testFuture, 10.secs)) - - await conn.close() - await nativeNode.stop() - await daemonNode.close() - - asyncTest "daemon -> multiple reads and writes": - var protos = @["/test-stream"] - - var testFuture = newFuture[void]("test.future") - proc nativeHandler(conn: Connection, proto: string) {.async.} = - check "test 1" == string.fromBytes(await conn.readLp(1024)) - await conn.writeLp("test 2".toBytes()) - - check "test 3" == string.fromBytes(await conn.readLp(1024)) - await conn.writeLp("test 4".toBytes()) - - testFuture.complete() - await conn.close() - - # custom proto - var proto = new LPProtocol - proto.handler = nativeHandler - proto.codec = protos[0] # codec - - let nativeNode = newStandardSwitch( - secureManagers = [SecureProtocol.Noise], outTimeout = 5.minutes) - - nativeNode.mount(proto) - - await nativeNode.start() - let nativePeer = nativeNode.peerInfo - - let daemonNode = await newDaemonApi() - await daemonNode.connect(nativePeer.peerId, nativePeer.addrs) - var stream = await daemonNode.openStream(nativePeer.peerId, protos) - - asyncDiscard stream.transp.writeLp("test 1") - check "test 2" == string.fromBytes(await stream.transp.readLp()) - - asyncDiscard stream.transp.writeLp("test 3") - check "test 4" == string.fromBytes(await stream.transp.readLp()) - - await wait(testFuture, 10.secs) - - await stream.close() - await nativeNode.stop() - await daemonNode.close() - - asyncTest "read write multiple": - var protos = @["/test-stream"] - var test = "TEST STRING" - - var count = 0 - var testFuture = newFuture[int]("test.future") - proc nativeHandler(conn: Connection, proto: string) {.async.} = - while count < 10: - var line = string.fromBytes(await conn.readLp(1024)) - check line == test - await conn.writeLp(test.toBytes()) - count.inc() - - testFuture.complete(count) - await conn.close() - - # custom proto - var proto = new LPProtocol - proto.handler = nativeHandler - proto.codec = protos[0] # codec - - let nativeNode = newStandardSwitch( - secureManagers = [SecureProtocol.Noise], outTimeout = 5.minutes) - - nativeNode.mount(proto) - - await nativeNode.start() - let nativePeer = nativeNode.peerInfo - - let daemonNode = await newDaemonApi() - await daemonNode.connect(nativePeer.peerId, nativePeer.addrs) - var stream = await daemonNode.openStream(nativePeer.peerId, protos) - - var count2 = 0 - while count2 < 10: - discard await stream.transp.writeLp(test) - let line = await stream.transp.readLp() - check test == string.fromBytes(line) - inc(count2) - - check 10 == (await wait(testFuture, 1.minutes)) - await stream.close() - await nativeNode.stop() - await daemonNode.close() - - asyncTest "floodsub: daemon publish one": - await testPubSubDaemonPublish() - - asyncTest "floodsub: daemon publish many": - await testPubSubDaemonPublish(count = 10) - - asyncTest "gossipsub: daemon publish one": - await testPubSubDaemonPublish(gossip = true) - - asyncTest "gossipsub: daemon publish many": - await testPubSubDaemonPublish(gossip = true, count = 10) - - asyncTest "floodsub: node publish one": - await testPubSubNodePublish() - - asyncTest "floodsub: node publish many": - await testPubSubNodePublish(count = 10) - - asyncTest "gossipsub: node publish one": - await testPubSubNodePublish(gossip = true) - - asyncTest "gossipsub: node publish many": - await testPubSubNodePublish(gossip = true, count = 10) - - asyncTest "NativeSrc -> NativeRelay -> DaemonDst": - proc daemonHandler(api: DaemonAPI, stream: P2PStream) {.async.} = - check "line1" == string.fromBytes(await stream.transp.readLp()) - discard await stream.transp.writeLp("line2") - check "line3" == string.fromBytes(await stream.transp.readLp()) - discard await stream.transp.writeLp("line4") - await stream.close() - let - maSrc = MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() - maRel = MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() - src = SwitchBuilder.new() - .withRng(crypto.newRng()) - .withAddresses(@[ maSrc ]) - .withTcpTransport() - .withMplex() - .withNoise() - .withRelayTransport(false) - .build() - rel = SwitchBuilder.new() - .withRng(crypto.newRng()) - .withAddresses(@[ maRel ]) - .withTcpTransport() - .withMplex() - .withNoise() - .withRelayTransport(true) - .build() - - await src.start() - await rel.start() - let daemonNode = await newDaemonApi() - let daemonPeer = await daemonNode.identity() - let maStr = $rel.peerInfo.addrs[0] & "/p2p/" & $rel.peerInfo.peerId & "/p2p-circuit/p2p/" & $daemonPeer.peer - let maddr = MultiAddress.init(maStr).tryGet() - await src.connect(rel.peerInfo.peerId, rel.peerInfo.addrs) - await rel.connect(daemonPeer.peer, daemonPeer.addresses) - - await daemonNode.addHandler(@[ "/testCustom" ], daemonHandler) - - let conn = await src.dial(daemonPeer.peer, @[ maddr ], @[ "/testCustom" ]) - - await conn.writeLp("line1") - check string.fromBytes(await conn.readLp(1024)) == "line2" - - await conn.writeLp("line3") - check string.fromBytes(await conn.readLp(1024)) == "line4" - - await allFutures(src.stop(), rel.stop()) - await daemonNode.close() - - asyncTest "DaemonSrc -> NativeRelay -> NativeDst": - proc customHandler(conn: Connection, proto: string) {.async.} = - check "line1" == string.fromBytes(await conn.readLp(1024)) - await conn.writeLp("line2") - check "line3" == string.fromBytes(await conn.readLp(1024)) - await conn.writeLp("line4") - await conn.close() - let - protos = @[ "/customProto", RelayCodec ] - var - customProto = new LPProtocol - customProto.handler = customHandler - customProto.codec = protos[0] - let - maRel = MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() - maDst = MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() - rel = SwitchBuilder.new() - .withRng(crypto.newRng()) - .withAddresses(@[ maRel ]) - .withTcpTransport() - .withMplex() - .withNoise() - .withRelayTransport(true) - .build() - dst = SwitchBuilder.new() - .withRng(crypto.newRng()) - .withAddresses(@[ maDst ]) - .withTcpTransport() - .withMplex() - .withNoise() - .withRelayTransport(false) - .build() - - dst.mount(customProto) - await rel.start() - await dst.start() - let daemonNode = await newDaemonApi() - let daemonPeer = await daemonNode.identity() - let maStr = $rel.peerInfo.addrs[0] & "/p2p/" & $rel.peerInfo.peerId & "/p2p-circuit/p2p/" & $dst.peerInfo.peerId - let maddr = MultiAddress.init(maStr).tryGet() - await daemonNode.connect(rel.peerInfo.peerId, rel.peerInfo.addrs) - await rel.connect(dst.peerInfo.peerId, dst.peerInfo.addrs) - await daemonNode.connect(dst.peerInfo.peerId, @[ maddr ]) - var stream = await daemonNode.openStream(dst.peerInfo.peerId, protos) - - discard await stream.transp.writeLp("line1") - check string.fromBytes(await stream.transp.readLp()) == "line2" - discard await stream.transp.writeLp("line3") - check string.fromBytes(await stream.transp.readLp()) == "line4" - - await allFutures(dst.stop(), rel.stop()) - await daemonNode.close() - - asyncTest "NativeSrc -> DaemonRelay -> NativeDst": - proc customHandler(conn: Connection, proto: string) {.async.} = - check "line1" == string.fromBytes(await conn.readLp(1024)) - await conn.writeLp("line2") - check "line3" == string.fromBytes(await conn.readLp(1024)) - await conn.writeLp("line4") - await conn.close() - let - protos = @[ "/customProto", RelayCodec ] - var - customProto = new LPProtocol - customProto.handler = customHandler - customProto.codec = protos[0] - let - maSrc = MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() - maDst = MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() - src = SwitchBuilder.new() - .withRng(crypto.newRng()) - .withAddresses(@[ maSrc ]) - .withTcpTransport() - .withMplex() - .withNoise() - .withRelayTransport(false) - .build() - dst = SwitchBuilder.new() - .withRng(crypto.newRng()) - .withAddresses(@[ maDst ]) - .withTcpTransport() - .withMplex() - .withNoise() - .withRelayTransport(false) - .build() - - dst.mount(customProto) - await src.start() - await dst.start() - let daemonNode = await newDaemonApi({RelayHop}) - let daemonPeer = await daemonNode.identity() - let maStr = $daemonPeer.addresses[0] & "/p2p/" & $daemonPeer.peer & "/p2p-circuit/p2p/" & $dst.peerInfo.peerId - let maddr = MultiAddress.init(maStr).tryGet() - await src.connect(daemonPeer.peer, daemonPeer.addresses) - await daemonNode.connect(dst.peerInfo.peerId, dst.peerInfo.addrs) - let conn = await src.dial(dst.peerInfo.peerId, @[ maddr ], protos[0]) - - await conn.writeLp("line1") - check string.fromBytes(await conn.readLp(1024)) == "line2" - - await conn.writeLp("line3") - check string.fromBytes(await conn.readLp(1024)) == "line4" - - await allFutures(src.stop(), dst.stop()) - await daemonNode.close() +import ../libp2p/crypto/crypto, ../libp2p/protocols/relay/[relay, client] + +proc switchMplexCreator( + ma: MultiAddress = MultiAddress.init("/ip4/127.0.0.1/tcp/0").tryGet(), + prov: TransportProvider = proc(upgr: Upgrade): Transport = TcpTransport.new({}, upgr), + relay: Relay = Relay.new(circuitRelayV1 = true)): + Switch {.raises: [Defect, LPError].} = + + SwitchBuilder.new() + .withSignedPeerRecord(false) + .withMaxConnections(MaxConnections) + .withRng(crypto.newRng()) + .withAddresses(@[ ma ]) + .withMaxIn(-1) + .withMaxOut(-1) + .withTransport(prov) + .withMplex() + .withMaxConnsPerPeer(MaxConnectionsPerPeer) + .withPeerStore(capacity=1000) + .withNoise() + .withCircuitRelay(relay) + .withNameResolver(nil) + .build() + +proc switchYamuxCreator( + ma: MultiAddress = MultiAddress.init("/ip4/127.0.0.1/tcp/0").tryGet(), + prov: TransportProvider = proc(upgr: Upgrade): Transport = TcpTransport.new({}, upgr), + relay: Relay = Relay.new(circuitRelayV1 = true)): + Switch {.raises: [Defect, LPError].} = + + SwitchBuilder.new() + .withSignedPeerRecord(false) + .withMaxConnections(MaxConnections) + .withRng(crypto.newRng()) + .withAddresses(@[ ma ]) + .withMaxIn(-1) + .withMaxOut(-1) + .withTransport(prov) + .withYamux() + .withMaxConnsPerPeer(MaxConnectionsPerPeer) + .withPeerStore(capacity=1000) + .withNoise() + .withCircuitRelay(relay) + .withNameResolver(nil) + .build() + + +suite "Tests interop": + commonInteropTests("mplex", switchMplexCreator) + relayInteropTests("mplex", switchMplexCreator) + + commonInteropTests("yamux", switchYamuxCreator) + relayInteropTests("yamux", switchYamuxCreator) diff --git a/vendor/nim-libp2p/tests/testminasn1.nim b/vendor/nim-libp2p/tests/testminasn1.nim index 1dd5817ff..6bda13204 100644 --- a/vendor/nim-libp2p/tests/testminasn1.nim +++ b/vendor/nim-libp2p/tests/testminasn1.nim @@ -1,11 +1,11 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. import unittest2 import ../libp2p/crypto/minasn1 import nimcrypto/utils as ncrutils diff --git a/vendor/nim-libp2p/tests/testminprotobuf.nim b/vendor/nim-libp2p/tests/testminprotobuf.nim index acbe9c927..fae8fd742 100644 --- a/vendor/nim-libp2p/tests/testminprotobuf.nim +++ b/vendor/nim-libp2p/tests/testminprotobuf.nim @@ -1,11 +1,11 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. import unittest2 import ../libp2p/protobuf/minprotobuf diff --git a/vendor/nim-libp2p/tests/testmultiaddress.nim b/vendor/nim-libp2p/tests/testmultiaddress.nim index c4d09a6ff..4ce91f729 100644 --- a/vendor/nim-libp2p/tests/testmultiaddress.nim +++ b/vendor/nim-libp2p/tests/testmultiaddress.nim @@ -367,3 +367,12 @@ suite "MultiAddress test suite": check: MultiAddress.init("/ip4/0.0.0.0").get().protoAddress().get() == address_v4 MultiAddress.init("/ip6/::0").get().protoAddress().get() == address_v6 + + test "MultiAddress getParts": + let ma = MultiAddress.init("/ip4/0.0.0.0/tcp/0/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/p2p-circuit/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSuNEXT/unix/stdio/").get() + check: + $ma[0..0].get() == "/ip4/0.0.0.0" + $ma[0..1].get() == "/ip4/0.0.0.0/tcp/0" + $ma[1..2].get() == "/tcp/0/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC" + $ma[^3..^1].get() == "/p2p-circuit/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSuNEXT/unix/stdio" + ma[5..7].isErr() diff --git a/vendor/nim-libp2p/tests/testmultistream.nim b/vendor/nim-libp2p/tests/testmultistream.nim index 6b07fcc72..6bdf1aa40 100644 --- a/vendor/nim-libp2p/tests/testmultistream.nim +++ b/vendor/nim-libp2p/tests/testmultistream.nim @@ -11,7 +11,10 @@ import ../libp2p/errors, ../libp2p/upgrademngrs/upgrade -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import ./helpers @@ -56,7 +59,7 @@ method readOnce*(s: TestSelectStream, method write*(s: TestSelectStream, msg: seq[byte]) {.async, gcsafe.} = discard -method close(s: TestSelectStream) {.async, gcsafe, raises: [Defect].} = +method close(s: TestSelectStream) {.async, gcsafe.} = s.isClosed = true s.isEof = true diff --git a/vendor/nim-libp2p/tests/testnative.nim b/vendor/nim-libp2p/tests/testnative.nim index 998f104e2..2bad49467 100644 --- a/vendor/nim-libp2p/tests/testnative.nim +++ b/vendor/nim-libp2p/tests/testnative.nim @@ -1,3 +1,5 @@ +import stublogger + import testvarint, testconnection, testminprotobuf, @@ -33,4 +35,7 @@ import testtcptransport, testpeerstore, testping, testmplex, - testrelay + testrelayv1, + testrelayv2, + testyamux, + testautonat diff --git a/vendor/nim-libp2p/tests/testnoise.nim b/vendor/nim-libp2p/tests/testnoise.nim index 8c9e82e82..b0e785be3 100644 --- a/vendor/nim-libp2p/tests/testnoise.nim +++ b/vendor/nim-libp2p/tests/testnoise.nim @@ -1,15 +1,15 @@ -## Nim-LibP2P -## Copyright (c) 2020 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. {.used.} -import tables, bearssl +import tables import chronos, stew/byteutils import chronicles import ../libp2p/[switch, @@ -39,7 +39,12 @@ const type TestProto = ref object of LPProtocol -method init(p: TestProto) {.gcsafe, raises: [Defect].} = +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} + +method init(p: TestProto) {.gcsafe.} = proc handle(conn: Connection, proto: string) {.async, gcsafe.} = let msg = string.fromBytes(await conn.readLp(1024)) check "Hello!" == msg @@ -49,6 +54,9 @@ method init(p: TestProto) {.gcsafe, raises: [Defect].} = p.codec = TestCodec p.handler = handle +{.pop.} + + proc createSwitch(ma: MultiAddress; outgoing: bool, secio: bool = false): (Switch, PeerInfo) = var privateKey = PrivateKey.random(ECDSA, rng[]).get() @@ -61,7 +69,7 @@ proc createSwitch(ma: MultiAddress; outgoing: bool, secio: bool = false): (Switc let identify = Identify.new(peerInfo) mplexProvider = MuxerProvider.new(createMplex, MplexCodec) - muxers = [(MplexCodec, mplexProvider)].toTable() + muxers = @[mplexProvider] secureManagers = if secio: [Secure(Secio.new(rng, privateKey))] else: @@ -75,7 +83,6 @@ proc createSwitch(ma: MultiAddress; outgoing: bool, secio: bool = false): (Switc peerInfo, transports, identify, - muxers, secureManagers, connManager, ms) @@ -97,7 +104,7 @@ suite "Noise": proc acceptHandler() {.async.} = let conn = await transport1.accept() - let sconn = await serverNoise.secure(conn, false) + let sconn = await serverNoise.secure(conn, false, Opt.none(PeerId)) try: await sconn.write("Hello!") finally: @@ -112,8 +119,7 @@ suite "Noise": clientNoise = Noise.new(rng, clientPrivKey, outgoing = true) conn = await transport2.dial(transport1.addrs[0]) - conn.peerId = serverInfo.peerId - let sconn = await clientNoise.secure(conn, true) + let sconn = await clientNoise.secure(conn, true, Opt.some(serverInfo.peerId)) var msg = newSeq[byte](6) await sconn.readExactly(addr msg[0], 6) @@ -142,7 +148,7 @@ suite "Noise": var conn: Connection try: conn = await transport1.accept() - discard await serverNoise.secure(conn, false) + discard await serverNoise.secure(conn, false, Opt.none(PeerId)) except CatchableError: discard finally: @@ -155,11 +161,10 @@ suite "Noise": clientInfo = PeerInfo.new(clientPrivKey, transport1.addrs) clientNoise = Noise.new(rng, clientPrivKey, outgoing = true, commonPrologue = @[1'u8, 2'u8, 3'u8]) conn = await transport2.dial(transport1.addrs[0]) - conn.peerId = serverInfo.peerId var sconn: Connection = nil expect(NoiseDecryptTagError): - sconn = await clientNoise.secure(conn, true) + sconn = await clientNoise.secure(conn, true, Opt.some(conn.peerId)) await conn.close() await handlerWait @@ -179,7 +184,7 @@ suite "Noise": proc acceptHandler() {.async, gcsafe.} = let conn = await transport1.accept() - let sconn = await serverNoise.secure(conn, false) + let sconn = await serverNoise.secure(conn, false, Opt.none(PeerId)) defer: await sconn.close() await conn.close() @@ -195,8 +200,7 @@ suite "Noise": clientInfo = PeerInfo.new(clientPrivKey, transport1.addrs) clientNoise = Noise.new(rng, clientPrivKey, outgoing = true) conn = await transport2.dial(transport1.addrs[0]) - conn.peerId = serverInfo.peerId - let sconn = await clientNoise.secure(conn, true) + let sconn = await clientNoise.secure(conn, true, Opt.some(serverInfo.peerId)) await sconn.write("Hello!") await acceptFut @@ -214,7 +218,7 @@ suite "Noise": readTask = newFuture[void]() var hugePayload = newSeq[byte](0xFFFFF) - brHmacDrbgGenerate(rng[], hugePayload) + hmacDrbgGenerate(rng[], hugePayload) trace "Sending huge payload", size = hugePayload.len let @@ -223,7 +227,7 @@ suite "Noise": proc acceptHandler() {.async, gcsafe.} = let conn = await transport1.accept() - let sconn = await serverNoise.secure(conn, false) + let sconn = await serverNoise.secure(conn, false, Opt.none(PeerId)) defer: await sconn.close() let msg = await sconn.readLp(1024*1024) @@ -237,8 +241,7 @@ suite "Noise": clientInfo = PeerInfo.new(clientPrivKey, transport1.addrs) clientNoise = Noise.new(rng, clientPrivKey, outgoing = true) conn = await transport2.dial(transport1.addrs[0]) - conn.peerId = serverInfo.peerId - let sconn = await clientNoise.secure(conn, true) + let sconn = await clientNoise.secure(conn, true, Opt.some(serverInfo.peerId)) await sconn.writeLp(hugePayload) await readTask diff --git a/vendor/nim-libp2p/tests/testpeerid.nim b/vendor/nim-libp2p/tests/testpeerid.nim index 551bf12ed..bc1f0882b 100644 --- a/vendor/nim-libp2p/tests/testpeerid.nim +++ b/vendor/nim-libp2p/tests/testpeerid.nim @@ -1,11 +1,11 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. ## Test vectors was made using Go implementation ## https://github.com/libp2p/go-libp2p-peer diff --git a/vendor/nim-libp2p/tests/testpeerinfo.nim b/vendor/nim-libp2p/tests/testpeerinfo.nim index 837657926..339836b0d 100644 --- a/vendor/nim-libp2p/tests/testpeerinfo.nim +++ b/vendor/nim-libp2p/tests/testpeerinfo.nim @@ -1,6 +1,6 @@ {.used.} -import options, bearssl +import options import chronos, stew/byteutils import ../libp2p/crypto/crypto, ../libp2p/multicodec, @@ -26,7 +26,7 @@ suite "PeerInfo": let seckey = PrivateKey.random(rng[]).tryGet() - peerId = PeerID.init(seckey).get() + peerId = PeerId.init(seckey).get() multiAddresses = @[MultiAddress.init("/ip4/0.0.0.0/tcp/24").tryGet(), MultiAddress.init("/ip4/0.0.0.0/tcp/25").tryGet()] peerInfo = PeerInfo.new(seckey, multiAddresses) diff --git a/vendor/nim-libp2p/tests/testping.nim b/vendor/nim-libp2p/tests/testping.nim index 49b54b737..88cf69ebc 100644 --- a/vendor/nim-libp2p/tests/testping.nim +++ b/vendor/nim-libp2p/tests/testping.nim @@ -1,4 +1,4 @@ -import options, bearssl +import options import chronos, strutils import ../libp2p/[protocols/identify, protocols/ping, diff --git a/vendor/nim-libp2p/tests/testpkifilter.nim b/vendor/nim-libp2p/tests/testpkifilter.nim index b1ea8a839..fcb9b1fe9 100644 --- a/vendor/nim-libp2p/tests/testpkifilter.nim +++ b/vendor/nim-libp2p/tests/testpkifilter.nim @@ -1,14 +1,15 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. when defined(nimHasUsed): {.used.} import unittest2 +import stublogger import ../libp2p/crypto/crypto import nimcrypto/utils diff --git a/vendor/nim-libp2p/tests/testrelay.nim b/vendor/nim-libp2p/tests/testrelay.nim deleted file mode 100644 index a9fa514e5..000000000 --- a/vendor/nim-libp2p/tests/testrelay.nim +++ /dev/null @@ -1,350 +0,0 @@ -{.used.} - -import options, bearssl, chronos -import stew/byteutils -import ../libp2p/[protocols/relay, - multiaddress, - peerinfo, - peerid, - stream/connection, - multistream, - transports/transport, - switch, - builders, - upgrademngrs/upgrade, - varint, - daemon/daemonapi] -import ./helpers - -proc new(T: typedesc[RelayTransport], relay: Relay): T = - T.new(relay = relay, upgrader = relay.switch.transports[0].upgrader) - -proc writeLp*(s: StreamTransport, msg: string | seq[byte]): Future[int] {.gcsafe.} = - ## write lenght prefixed - var buf = initVBuffer() - buf.writeSeq(msg) - buf.finish() - result = s.write(buf.buffer) - -proc readLp*(s: StreamTransport): Future[seq[byte]] {.async, gcsafe.} = - ## read length prefixed msg - var - size: uint - length: int - res: VarintResult[void] - result = newSeq[byte](10) - - for i in 0.. 0.uint: - await s.readExactly(addr result[0], int(size)) - -suite "Circuit Relay": - asyncTeardown: - await allFutures(src.stop(), dst.stop(), rel.stop()) - checkTrackers() - - var - protos {.threadvar.}: seq[string] - customProto {.threadvar.}: LPProtocol - ma {.threadvar.}: MultiAddress - src {.threadvar.}: Switch - dst {.threadvar.}: Switch - rel {.threadvar.}: Switch - relaySrc {.threadvar.}: Relay - relayDst {.threadvar.}: Relay - relayRel {.threadvar.}: Relay - conn {.threadVar.}: Connection - msg {.threadVar.}: ProtoBuffer - rcv {.threadVar.}: Option[RelayMessage] - - proc createMsg( - msgType: Option[RelayType] = RelayType.none, - status: Option[RelayStatus] = RelayStatus.none, - src: Option[RelayPeer] = RelayPeer.none, - dst: Option[RelayPeer] = RelayPeer.none): ProtoBuffer = - encodeMsg(RelayMessage(msgType: msgType, srcPeer: src, dstPeer: dst, status: status)) - - proc checkMsg(msg: Option[RelayMessage], - msgType: Option[RelayType] = none[RelayType](), - status: Option[RelayStatus] = none[RelayStatus](), - src: Option[RelayPeer] = none[RelayPeer](), - dst: Option[RelayPeer] = none[RelayPeer]()): bool = - msg.isSome and msg.get == RelayMessage(msgType: msgType, srcPeer: src, dstPeer: dst, status: status) - - proc customHandler(conn: Connection, proto: string) {.async.} = - check "line1" == string.fromBytes(await conn.readLp(1024)) - await conn.writeLp("line2") - check "line3" == string.fromBytes(await conn.readLp(1024)) - await conn.writeLp("line4") - await conn.close() - - asyncSetup: - # Create a custom prototype - protos = @[ "/customProto", RelayCodec ] - customProto = new LPProtocol - customProto.handler = customHandler - customProto.codec = protos[0] - ma = MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() - - src = newStandardSwitch() - rel = newStandardSwitch() - dst = SwitchBuilder - .new() - .withRng(newRng()) - .withAddresses(@[ ma ]) - .withTcpTransport() - .withMplex() - .withNoise() - .build() - - relaySrc = Relay.new(src, false) - relayDst = Relay.new(dst, false) - relayRel = Relay.new(rel, true) - - src.mount(relaySrc) - dst.mount(relayDst) - dst.mount(customProto) - rel.mount(relayRel) - - src.addTransport(RelayTransport.new(relaySrc)) - dst.addTransport(RelayTransport.new(relayDst)) - - await src.start() - await dst.start() - await rel.start() - - asyncTest "Handle CanHop": - msg = createMsg(some(CanHop)) - conn = await src.dial(rel.peerInfo.peerId, rel.peerInfo.addrs, RelayCodec) - await conn.writeLp(msg.buffer) - rcv = relay.decodeMsg(await conn.readLp(relay.MsgSize)) - check rcv.checkMsg(some(Status), some(RelayStatus.Success)) - - conn = await src.dial(dst.peerInfo.peerId, dst.peerInfo.addrs, RelayCodec) - await conn.writeLp(msg.buffer) - rcv = relay.decodeMsg(await conn.readLp(relay.MsgSize)) - check rcv.checkMsg(some(Status), some(HopCantSpeakRelay)) - - await conn.close() - - asyncTest "Malformed": - conn = await rel.dial(dst.peerInfo.peerId, dst.peerInfo.addrs, RelayCodec) - msg = createMsg(some(RelayType.Status)) - await conn.writeLp(msg.buffer) - rcv = relay.decodeMsg(await conn.readLp(relay.MsgSize)) - await conn.close() - check rcv.checkMsg(some(Status), some(MalformedMessage)) - - asyncTest "Handle Stop Error": - conn = await rel.dial(dst.peerInfo.peerId, dst.peerInfo.addrs, RelayCodec) - msg = createMsg(some(RelayType.Stop), - none(RelayStatus), - none(RelayPeer), - some(RelayPeer(peerId: dst.peerInfo.peerId, addrs: dst.peerInfo.addrs))) - await conn.writeLp(msg.buffer) - rcv = relay.decodeMsg(await conn.readLp(relay.MsgSize)) - check rcv.checkMsg(some(Status), some(StopSrcMultiaddrInvalid)) - - conn = await rel.dial(dst.peerInfo.peerId, dst.peerInfo.addrs, RelayCodec) - msg = createMsg(some(RelayType.Stop), - none(RelayStatus), - some(RelayPeer(peerId: src.peerInfo.peerId, addrs: src.peerInfo.addrs)), - none(RelayPeer)) - await conn.writeLp(msg.buffer) - rcv = relay.decodeMsg(await conn.readLp(relay.MsgSize)) - check rcv.checkMsg(some(Status), some(StopDstMultiaddrInvalid)) - - conn = await rel.dial(dst.peerInfo.peerId, dst.peerInfo.addrs, RelayCodec) - msg = createMsg(some(RelayType.Stop), - none(RelayStatus), - some(RelayPeer(peerId: dst.peerInfo.peerId, addrs: dst.peerInfo.addrs)), - some(RelayPeer(peerId: src.peerInfo.peerId, addrs: src.peerInfo.addrs))) - await conn.writeLp(msg.buffer) - rcv = relay.decodeMsg(await conn.readLp(relay.MsgSize)) - await conn.close() - check rcv.checkMsg(some(Status), some(StopDstMultiaddrInvalid)) - - asyncTest "Handle Hop Error": - conn = await src.dial(dst.peerInfo.peerId, dst.peerInfo.addrs, RelayCodec) - msg = createMsg(some(RelayType.Hop)) - await conn.writeLp(msg.buffer) - rcv = relay.decodeMsg(await conn.readLp(relay.MsgSize)) - check rcv.checkMsg(some(Status), some(HopCantSpeakRelay)) - - conn = await src.dial(rel.peerInfo.peerId, rel.peerInfo.addrs, RelayCodec) - msg = createMsg(some(RelayType.Hop), - none(RelayStatus), - none(RelayPeer), - some(RelayPeer(peerId: dst.peerInfo.peerId, addrs: dst.peerInfo.addrs))) - await conn.writeLp(msg.buffer) - rcv = relay.decodeMsg(await conn.readLp(relay.MsgSize)) - check rcv.checkMsg(some(Status), some(HopSrcMultiaddrInvalid)) - - conn = await src.dial(rel.peerInfo.peerId, rel.peerInfo.addrs, RelayCodec) - msg = createMsg(some(RelayType.Hop), - none(RelayStatus), - some(RelayPeer(peerId: dst.peerInfo.peerId, addrs: dst.peerInfo.addrs)), - some(RelayPeer(peerId: dst.peerInfo.peerId, addrs: dst.peerInfo.addrs))) - await conn.writeLp(msg.buffer) - rcv = relay.decodeMsg(await conn.readLp(relay.MsgSize)) - check rcv.checkMsg(some(Status), some(HopSrcMultiaddrInvalid)) - - conn = await src.dial(rel.peerInfo.peerId, rel.peerInfo.addrs, RelayCodec) - msg = createMsg(some(RelayType.Hop), - none(RelayStatus), - some(RelayPeer(peerId: src.peerInfo.peerId, addrs: src.peerInfo.addrs)), - none(RelayPeer)) - await conn.writeLp(msg.buffer) - rcv = relay.decodeMsg(await conn.readLp(relay.MsgSize)) - check rcv.checkMsg(some(Status), some(HopDstMultiaddrInvalid)) - - conn = await src.dial(rel.peerInfo.peerId, rel.peerInfo.addrs, RelayCodec) - msg = createMsg(some(RelayType.Hop), - none(RelayStatus), - some(RelayPeer(peerId: src.peerInfo.peerId, addrs: src.peerInfo.addrs)), - some(RelayPeer(peerId: rel.peerInfo.peerId, addrs: rel.peerInfo.addrs))) - await conn.writeLp(msg.buffer) - rcv = relay.decodeMsg(await conn.readLp(relay.MsgSize)) - check rcv.checkMsg(some(Status), some(HopCantRelayToSelf)) - - conn = await src.dial(rel.peerInfo.peerId, rel.peerInfo.addrs, RelayCodec) - msg = createMsg(some(RelayType.Hop), - none(RelayStatus), - some(RelayPeer(peerId: src.peerInfo.peerId, addrs: src.peerInfo.addrs)), - some(RelayPeer(peerId: rel.peerInfo.peerId, addrs: rel.peerInfo.addrs))) - await conn.writeLp(msg.buffer) - rcv = relay.decodeMsg(await conn.readLp(relay.MsgSize)) - check rcv.checkMsg(some(Status), some(HopCantRelayToSelf)) - - conn = await src.dial(rel.peerInfo.peerId, rel.peerInfo.addrs, RelayCodec) - msg = createMsg(some(RelayType.Hop), - none(RelayStatus), - some(RelayPeer(peerId: src.peerInfo.peerId, addrs: src.peerInfo.addrs)), - some(RelayPeer(peerId: dst.peerInfo.peerId, addrs: dst.peerInfo.addrs))) - await conn.writeLp(msg.buffer) - rcv = relay.decodeMsg(await conn.readLp(relay.MsgSize)) - check rcv.checkMsg(some(Status), some(HopNoConnToDst)) - - await rel.connect(dst.peerInfo.peerId, dst.peerInfo.addrs) - - relayRel.maxCircuit = 0 - conn = await src.dial(rel.peerInfo.peerId, rel.peerInfo.addrs, RelayCodec) - await conn.writeLp(msg.buffer) - rcv = relay.decodeMsg(await conn.readLp(relay.MsgSize)) - check rcv.checkMsg(some(Status), some(HopCantSpeakRelay)) - relayRel.maxCircuit = relay.MaxCircuit - await conn.close() - - relayRel.maxCircuitPerPeer = 0 - conn = await src.dial(rel.peerInfo.peerId, rel.peerInfo.addrs, RelayCodec) - await conn.writeLp(msg.buffer) - rcv = relay.decodeMsg(await conn.readLp(relay.MsgSize)) - check rcv.checkMsg(some(Status), some(HopCantSpeakRelay)) - relayRel.maxCircuitPerPeer = relay.MaxCircuitPerPeer - await conn.close() - - let dst2 = newStandardSwitch() - await dst2.start() - await rel.connect(dst2.peerInfo.peerId, dst2.peerInfo.addrs) - - conn = await src.dial(rel.peerInfo.peerId, rel.peerInfo.addrs, RelayCodec) - msg = createMsg(some(RelayType.Hop), - none(RelayStatus), - some(RelayPeer(peerId: src.peerInfo.peerId, addrs: src.peerInfo.addrs)), - some(RelayPeer(peerId: dst2.peerInfo.peerId, addrs: dst2.peerInfo.addrs))) - await conn.writeLp(msg.buffer) - rcv = relay.decodeMsg(await conn.readLp(relay.MsgSize)) - check rcv.checkMsg(some(Status), some(HopCantDialDst)) - await allFutures(dst2.stop()) - - asyncTest "Dial Peer": - let maStr = $rel.peerInfo.addrs[0] & "/p2p/" & $rel.peerInfo.peerId & "/p2p-circuit/p2p/" & $dst.peerInfo.peerId - let maddr = MultiAddress.init(maStr).tryGet() - await src.connect(rel.peerInfo.peerId, rel.peerInfo.addrs) - await rel.connect(dst.peerInfo.peerId, dst.peerInfo.addrs) - conn = await src.dial(dst.peerInfo.peerId, @[ maddr ], protos[0]) - - await conn.writeLp("line1") - check string.fromBytes(await conn.readLp(1024)) == "line2" - - await conn.writeLp("line3") - check string.fromBytes(await conn.readLp(1024)) == "line4" - - asyncTest "SwitchBuilder withRelay": - let - maSrc = MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() - maRel = MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() - maDst = MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() - srcWR = SwitchBuilder.new() - .withRng(newRng()) - .withAddresses(@[ maSrc ]) - .withTcpTransport() - .withMplex() - .withNoise() - .withRelayTransport(false) - .build() - relWR = SwitchBuilder.new() - .withRng(newRng()) - .withAddresses(@[ maRel ]) - .withTcpTransport() - .withMplex() - .withNoise() - .withRelayTransport(true) - .build() - dstWR = SwitchBuilder.new() - .withRng(newRng()) - .withAddresses(@[ maDst ]) - .withTcpTransport() - .withMplex() - .withNoise() - .withRelayTransport(false) - .build() - - dstWR.mount(customProto) - - await srcWR.start() - await dstWR.start() - await relWR.start() - - let maStr = $relWR.peerInfo.addrs[0] & "/p2p/" & $relWR.peerInfo.peerId & "/p2p-circuit/p2p/" & $dstWR.peerInfo.peerId - let maddr = MultiAddress.init(maStr).tryGet() - await srcWR.connect(relWR.peerInfo.peerId, relWR.peerInfo.addrs) - await relWR.connect(dstWR.peerInfo.peerId, dstWR.peerInfo.addrs) - conn = await srcWR.dial(dstWR.peerInfo.peerId, @[ maddr ], protos[0]) - - await conn.writeLp("line1") - check string.fromBytes(await conn.readLp(1024)) == "line2" - - await conn.writeLp("line3") - check string.fromBytes(await conn.readLp(1024)) == "line4" - - await allFutures(srcWR.stop(), dstWR.stop(), relWR.stop()) - - asynctest "Bad MultiAddress": - await src.connect(rel.peerInfo.peerId, rel.peerInfo.addrs) - await rel.connect(dst.peerInfo.peerId, dst.peerInfo.addrs) - expect(CatchableError): - let maStr = $rel.peerInfo.addrs[0] & "/p2p/" & $rel.peerInfo.peerId & "/p2p/" & $dst.peerInfo.peerId - let maddr = MultiAddress.init(maStr).tryGet() - conn = await src.dial(dst.peerInfo.peerId, @[ maddr ], protos[0]) - - expect(CatchableError): - let maStr = $rel.peerInfo.addrs[0] & "/p2p/" & $rel.peerInfo.peerId - let maddr = MultiAddress.init(maStr).tryGet() - conn = await src.dial(dst.peerInfo.peerId, @[ maddr ], protos[0]) - - expect(CatchableError): - let maStr = "/ip4/127.0.0.1" - let maddr = MultiAddress.init(maStr).tryGet() - conn = await src.dial(dst.peerInfo.peerId, @[ maddr ], protos[0]) - - expect(CatchableError): - let maStr = $dst.peerInfo.peerId - let maddr = MultiAddress.init(maStr).tryGet() - conn = await src.dial(dst.peerInfo.peerId, @[ maddr ], protos[0]) diff --git a/vendor/nim-libp2p/tests/testrelayv1.nim b/vendor/nim-libp2p/tests/testrelayv1.nim new file mode 100644 index 000000000..17206be5c --- /dev/null +++ b/vendor/nim-libp2p/tests/testrelayv1.nim @@ -0,0 +1,293 @@ +{.used.} + +import options, bearssl, chronos +import stew/byteutils +import ../libp2p/[protocols/relay/relay, + protocols/relay/client, + protocols/relay/messages, + protocols/relay/utils, + protocols/relay/rtransport, + multiaddress, + peerinfo, + peerid, + stream/connection, + multistream, + transports/transport, + switch, + builders, + upgrademngrs/upgrade, + varint, + daemon/daemonapi] +import ./helpers + +proc new(T: typedesc[RelayTransport], relay: Relay): T = + T.new(relay = relay, upgrader = relay.switch.transports[0].upgrader) + +suite "Circuit Relay": + asyncTeardown: + await allFutures(src.stop(), dst.stop(), srelay.stop()) + checkTrackers() + + var + protos {.threadvar.}: seq[string] + customProto {.threadvar.}: LPProtocol + ma {.threadvar.}: MultiAddress + src {.threadvar.}: Switch + dst {.threadvar.}: Switch + srelay {.threadvar.}: Switch + clSrc {.threadvar.}: RelayClient + clDst {.threadvar.}: RelayClient + r {.threadvar.}: Relay + conn {.threadvar.}: Connection + msg {.threadvar.}: ProtoBuffer + rcv {.threadvar.}: Option[RelayMessage] + + proc createMsg( + msgType: Option[RelayType] = RelayType.none, + status: Option[StatusV1] = StatusV1.none, + src: Option[RelayPeer] = RelayPeer.none, + dst: Option[RelayPeer] = RelayPeer.none): ProtoBuffer = + encode(RelayMessage(msgType: msgType, srcPeer: src, dstPeer: dst, status: status)) + + proc checkMsg(msg: Option[RelayMessage], + msgType: Option[RelayType] = none[RelayType](), + status: Option[StatusV1] = none[StatusV1](), + src: Option[RelayPeer] = none[RelayPeer](), + dst: Option[RelayPeer] = none[RelayPeer]()) = + check: msg.isSome + let m = msg.get() + check: m.msgType == msgType + check: m.status == status + check: m.srcPeer == src + check: m.dstPeer == dst + + proc customHandler(conn: Connection, proto: string) {.async.} = + check "line1" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("line2") + check "line3" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("line4") + await conn.close() + + asyncSetup: + # Create a custom prototype + protos = @[ "/customProto", RelayV1Codec ] + customProto = new LPProtocol + customProto.handler = customHandler + customProto.codec = protos[0] + + ma = MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() + clSrc = RelayClient.new() + clDst = RelayClient.new() + r = Relay.new(circuitRelayV1=true) + src = SwitchBuilder.new() + .withRng(newRng()) + .withAddresses(@[ MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() ]) + .withTcpTransport() + .withMplex() + .withNoise() + .withCircuitRelay(clSrc) + .build() + dst = SwitchBuilder.new() + .withRng(newRng()) + .withAddresses(@[ MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() ]) + .withTcpTransport() + .withMplex() + .withNoise() + .withCircuitRelay(clDst) + .build() + srelay = SwitchBuilder.new() + .withRng(newRng()) + .withAddresses(@[ MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() ]) + .withTcpTransport() + .withMplex() + .withNoise() + .withCircuitRelay(r) + .build() + + dst.mount(customProto) + + await src.start() + await dst.start() + await srelay.start() + + asyncTest "Handle CanHop": + msg = createMsg(some(CanHop)) + conn = await src.dial(srelay.peerInfo.peerId, srelay.peerInfo.addrs, RelayV1Codec) + await conn.writeLp(msg.buffer) + rcv = RelayMessage.decode(await conn.readLp(1024)) + rcv.checkMsg(some(RelayType.Status), some(StatusV1.Success)) + + conn = await src.dial(dst.peerInfo.peerId, dst.peerInfo.addrs, RelayV1Codec) + await conn.writeLp(msg.buffer) + rcv = RelayMessage.decode(await conn.readLp(1024)) + rcv.checkMsg(some(RelayType.Status), some(HopCantSpeakRelay)) + + await conn.close() + + asyncTest "Malformed": + conn = await srelay.dial(dst.peerInfo.peerId, dst.peerInfo.addrs, RelayV1Codec) + msg = createMsg(some(RelayType.Status)) + await conn.writeLp(msg.buffer) + rcv = RelayMessage.decode(await conn.readLp(1024)) + await conn.close() + rcv.checkMsg(some(RelayType.Status), some(StatusV1.MalformedMessage)) + + asyncTest "Handle Stop Error": + conn = await srelay.dial(dst.peerInfo.peerId, dst.peerInfo.addrs, RelayV1Codec) + msg = createMsg(some(RelayType.Stop), + none(StatusV1), + none(RelayPeer), + some(RelayPeer(peerId: dst.peerInfo.peerId, addrs: dst.peerInfo.addrs))) + await conn.writeLp(msg.buffer) + rcv = RelayMessage.decode(await conn.readLp(1024)) + rcv.checkMsg(some(RelayType.Status), some(StopSrcMultiaddrInvalid)) + + conn = await srelay.dial(dst.peerInfo.peerId, dst.peerInfo.addrs, RelayV1Codec) + msg = createMsg(some(RelayType.Stop), + none(StatusV1), + some(RelayPeer(peerId: src.peerInfo.peerId, addrs: src.peerInfo.addrs)), + none(RelayPeer)) + await conn.writeLp(msg.buffer) + rcv = RelayMessage.decode(await conn.readLp(1024)) + rcv.checkMsg(some(RelayType.Status), some(StopDstMultiaddrInvalid)) + + conn = await srelay.dial(dst.peerInfo.peerId, dst.peerInfo.addrs, RelayV1Codec) + msg = createMsg(some(RelayType.Stop), + none(StatusV1), + some(RelayPeer(peerId: dst.peerInfo.peerId, addrs: dst.peerInfo.addrs)), + some(RelayPeer(peerId: src.peerInfo.peerId, addrs: src.peerInfo.addrs))) + await conn.writeLp(msg.buffer) + rcv = RelayMessage.decode(await conn.readLp(1024)) + await conn.close() + rcv.checkMsg(some(RelayType.Status), some(StopDstMultiaddrInvalid)) + + asyncTest "Handle Hop Error": + conn = await src.dial(dst.peerInfo.peerId, dst.peerInfo.addrs, RelayV1Codec) + msg = createMsg(some(RelayType.Hop)) + await conn.writeLp(msg.buffer) + rcv = RelayMessage.decode(await conn.readLp(1024)) + rcv.checkMsg(some(RelayType.Status), some(HopCantSpeakRelay)) + + conn = await src.dial(srelay.peerInfo.peerId, srelay.peerInfo.addrs, RelayV1Codec) + msg = createMsg(some(RelayType.Hop), + none(StatusV1), + none(RelayPeer), + some(RelayPeer(peerId: dst.peerInfo.peerId, addrs: dst.peerInfo.addrs))) + await conn.writeLp(msg.buffer) + rcv = RelayMessage.decode(await conn.readLp(1024)) + rcv.checkMsg(some(RelayType.Status), some(HopSrcMultiaddrInvalid)) + + conn = await src.dial(srelay.peerInfo.peerId, srelay.peerInfo.addrs, RelayV1Codec) + msg = createMsg(some(RelayType.Hop), + none(StatusV1), + some(RelayPeer(peerId: dst.peerInfo.peerId, addrs: dst.peerInfo.addrs)), + some(RelayPeer(peerId: dst.peerInfo.peerId, addrs: dst.peerInfo.addrs))) + await conn.writeLp(msg.buffer) + rcv = RelayMessage.decode(await conn.readLp(1024)) + rcv.checkMsg(some(RelayType.Status), some(HopSrcMultiaddrInvalid)) + + conn = await src.dial(srelay.peerInfo.peerId, srelay.peerInfo.addrs, RelayV1Codec) + msg = createMsg(some(RelayType.Hop), + none(StatusV1), + some(RelayPeer(peerId: src.peerInfo.peerId, addrs: src.peerInfo.addrs)), + none(RelayPeer)) + await conn.writeLp(msg.buffer) + rcv = RelayMessage.decode(await conn.readLp(1024)) + rcv.checkMsg(some(RelayType.Status), some(HopDstMultiaddrInvalid)) + + conn = await src.dial(srelay.peerInfo.peerId, srelay.peerInfo.addrs, RelayV1Codec) + msg = createMsg(some(RelayType.Hop), + none(StatusV1), + some(RelayPeer(peerId: src.peerInfo.peerId, addrs: src.peerInfo.addrs)), + some(RelayPeer(peerId: srelay.peerInfo.peerId, addrs: srelay.peerInfo.addrs))) + await conn.writeLp(msg.buffer) + rcv = RelayMessage.decode(await conn.readLp(1024)) + rcv.checkMsg(some(RelayType.Status), some(HopCantRelayToSelf)) + + conn = await src.dial(srelay.peerInfo.peerId, srelay.peerInfo.addrs, RelayV1Codec) + msg = createMsg(some(RelayType.Hop), + none(StatusV1), + some(RelayPeer(peerId: src.peerInfo.peerId, addrs: src.peerInfo.addrs)), + some(RelayPeer(peerId: srelay.peerInfo.peerId, addrs: srelay.peerInfo.addrs))) + await conn.writeLp(msg.buffer) + rcv = RelayMessage.decode(await conn.readLp(1024)) + rcv.checkMsg(some(RelayType.Status), some(HopCantRelayToSelf)) + + conn = await src.dial(srelay.peerInfo.peerId, srelay.peerInfo.addrs, RelayV1Codec) + msg = createMsg(some(RelayType.Hop), + none(StatusV1), + some(RelayPeer(peerId: src.peerInfo.peerId, addrs: src.peerInfo.addrs)), + some(RelayPeer(peerId: dst.peerInfo.peerId, addrs: dst.peerInfo.addrs))) + await conn.writeLp(msg.buffer) + rcv = RelayMessage.decode(await conn.readLp(1024)) + rcv.checkMsg(some(RelayType.Status), some(HopNoConnToDst)) + + await srelay.connect(dst.peerInfo.peerId, dst.peerInfo.addrs) + + var tmp = r.maxCircuit + r.maxCircuit = 0 + conn = await src.dial(srelay.peerInfo.peerId, srelay.peerInfo.addrs, RelayV1Codec) + await conn.writeLp(msg.buffer) + rcv = RelayMessage.decode(await conn.readLp(1024)) + rcv.checkMsg(some(RelayType.Status), some(HopCantSpeakRelay)) + r.maxCircuit = tmp + await conn.close() + + tmp = r.maxCircuitPerPeer + r.maxCircuitPerPeer = 0 + conn = await src.dial(srelay.peerInfo.peerId, srelay.peerInfo.addrs, RelayV1Codec) + await conn.writeLp(msg.buffer) + rcv = RelayMessage.decode(await conn.readLp(1024)) + rcv.checkMsg(some(RelayType.Status), some(HopCantSpeakRelay)) + r.maxCircuitPerPeer = tmp + await conn.close() + + let dst2 = newStandardSwitch() + await dst2.start() + await srelay.connect(dst2.peerInfo.peerId, dst2.peerInfo.addrs) + + conn = await src.dial(srelay.peerInfo.peerId, srelay.peerInfo.addrs, RelayV1Codec) + msg = createMsg(some(RelayType.Hop), + none(StatusV1), + some(RelayPeer(peerId: src.peerInfo.peerId, addrs: src.peerInfo.addrs)), + some(RelayPeer(peerId: dst2.peerInfo.peerId, addrs: dst2.peerInfo.addrs))) + await conn.writeLp(msg.buffer) + rcv = RelayMessage.decode(await conn.readLp(1024)) + rcv.checkMsg(some(RelayType.Status), some(HopCantDialDst)) + await allFutures(dst2.stop()) + + asyncTest "Dial Peer": + let maStr = $srelay.peerInfo.addrs[0] & "/p2p/" & $srelay.peerInfo.peerId & "/p2p-circuit/p2p/" & $dst.peerInfo.peerId + let maddr = MultiAddress.init(maStr).tryGet() + await src.connect(srelay.peerInfo.peerId, srelay.peerInfo.addrs) + await srelay.connect(dst.peerInfo.peerId, dst.peerInfo.addrs) + conn = await src.dial(dst.peerInfo.peerId, @[ maddr ], protos[0]) + + await conn.writeLp("line1") + check string.fromBytes(await conn.readLp(1024)) == "line2" + + await conn.writeLp("line3") + check string.fromBytes(await conn.readLp(1024)) == "line4" + + asyncTest "Bad MultiAddress": + await src.connect(srelay.peerInfo.peerId, srelay.peerInfo.addrs) + await srelay.connect(dst.peerInfo.peerId, dst.peerInfo.addrs) + expect(CatchableError): + let maStr = $srelay.peerInfo.addrs[0] & "/p2p/" & $srelay.peerInfo.peerId & "/p2p/" & $dst.peerInfo.peerId + let maddr = MultiAddress.init(maStr).tryGet() + conn = await src.dial(dst.peerInfo.peerId, @[ maddr ], protos[0]) + + expect(CatchableError): + let maStr = $srelay.peerInfo.addrs[0] & "/p2p/" & $srelay.peerInfo.peerId + let maddr = MultiAddress.init(maStr).tryGet() + conn = await src.dial(dst.peerInfo.peerId, @[ maddr ], protos[0]) + + expect(CatchableError): + let maStr = "/ip4/127.0.0.1" + let maddr = MultiAddress.init(maStr).tryGet() + conn = await src.dial(dst.peerInfo.peerId, @[ maddr ], protos[0]) + + expect(CatchableError): + let maStr = $dst.peerInfo.peerId + let maddr = MultiAddress.init(maStr).tryGet() + conn = await src.dial(dst.peerInfo.peerId, @[ maddr ], protos[0]) diff --git a/vendor/nim-libp2p/tests/testrelayv2.nim b/vendor/nim-libp2p/tests/testrelayv2.nim new file mode 100644 index 000000000..5ce1f640a --- /dev/null +++ b/vendor/nim-libp2p/tests/testrelayv2.nim @@ -0,0 +1,412 @@ +{.used.} + +import bearssl, chronos, options +import ../libp2p +import ../libp2p/[protocols/relay/relay, + protocols/relay/messages, + protocols/relay/utils, + protocols/relay/client] +import ./helpers +import std/times +import stew/byteutils + +proc createSwitch(r: Relay): Switch = + result = SwitchBuilder.new() + .withRng(newRng()) + .withAddresses(@[ MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() ]) + .withTcpTransport() + .withMplex() + .withNoise() + .withCircuitRelay(r) + .build() + +suite "Circuit Relay V2": + + suite "Reservation": + asyncTeardown: + await allFutures(src1.stop(), src2.stop(), rel.stop()) + checkTrackers() + var + ttl {.threadvar.}: int + ldur {.threadvar.}: uint32 + ldata {.threadvar.}: uint64 + cl1 {.threadvar.}: RelayClient + cl2 {.threadvar.}: RelayClient + rv2 {.threadvar.}: Relay + src1 {.threadvar.}: Switch + src2 {.threadvar.}: Switch + rel {.threadvar.}: Switch + rsvp {.threadvar.}: Rsvp + range {.threadvar.}: HSlice[times.DateTime, times.DateTime] + + asyncSetup: + ttl = 1 + ldur = 60 + ldata = 2048 + cl1 = RelayClient.new() + cl2 = RelayClient.new() + rv2 = Relay.new(reservationTTL=initDuration(seconds=ttl), + limitDuration=ldur, + limitData=ldata, + maxCircuit=1) + src1 = createSwitch(cl1) + src2 = createSwitch(cl2) + rel = createSwitch(rv2) + + await src1.start() + await src2.start() + await rel.start() + await src1.connect(rel.peerInfo.peerId, rel.peerInfo.addrs) + await src2.connect(rel.peerInfo.peerId, rel.peerInfo.addrs) + rsvp = await cl1.reserve(rel.peerInfo.peerId, rel.peerInfo.addrs) + range = now().utc + (ttl-3).seconds..now().utc + (ttl+3).seconds + check: + rsvp.expire.int64.fromUnix.utc in range + rsvp.limitDuration == ldur + rsvp.limitData == ldata + + asyncTest "Too many reservations": + let conn = await cl2.switch.dial(rel.peerInfo.peerId, rel.peerInfo.addrs, RelayV2HopCodec) + let pb = encode(HopMessage(msgType: HopMessageType.Reserve)) + await conn.writeLp(pb.buffer) + let msg = HopMessage.decode(await conn.readLp(RelayMsgSize)).get() + check: + msg.msgType == HopMessageType.Status + msg.status == some(StatusV2.ReservationRefused) + + asyncTest "Too many reservations + Reconnect": + expect(ReservationError): + discard await cl2.reserve(rel.peerInfo.peerId, rel.peerInfo.addrs) + await rel.disconnect(src1.peerInfo.peerId) + rsvp = await cl2.reserve(rel.peerInfo.peerId, rel.peerInfo.addrs) + range = now().utc + (ttl-3).seconds..now().utc + (ttl+3).seconds + check: + rsvp.expire.int64.fromUnix.utc in range + rsvp.limitDuration == ldur + rsvp.limitData == ldata + + asyncTest "Reservation ttl expires": + await sleepAsync(chronos.timer.seconds(ttl + 1)) + rsvp = await cl1.reserve(rel.peerInfo.peerId, rel.peerInfo.addrs) + range = now().utc + (ttl-3).seconds..now().utc + (ttl+3).seconds + check: + rsvp.expire.int64.fromUnix.utc in range + rsvp.limitDuration == ldur + rsvp.limitData == ldata + + asyncTest "Reservation over relay": + let + rv2add = Relay.new() + addrs = @[ MultiAddress.init($rel.peerInfo.addrs[0] & "/p2p/" & + $rel.peerInfo.peerId & "/p2p-circuit/p2p/" & + $src2.peerInfo.peerId).get() ] + rv2add.setup(src2) + await rv2add.start() + src2.mount(rv2add) + rv2.maxCircuit.inc() + + rsvp = await cl2.reserve(rel.peerInfo.peerId, rel.peerInfo.addrs) + range = now().utc + (ttl-3).seconds..now().utc + (ttl+3).seconds + check: + rsvp.expire.int64.fromUnix.utc in range + rsvp.limitDuration == ldur + rsvp.limitData == ldata + expect(ReservationError): + discard await cl1.reserve(src2.peerInfo.peerId, addrs) + + suite "Connection": + asyncTeardown: + checkTrackers() + var + addrs {.threadvar.}: MultiAddress + customProtoCodec {.threadvar.}: string + proto {.threadvar.}: LPProtocol + ttl {.threadvar.}: int + ldur {.threadvar.}: uint32 + ldata {.threadvar.}: uint64 + srcCl {.threadvar.}: RelayClient + dstCl {.threadvar.}: RelayClient + rv2 {.threadvar.}: Relay + src {.threadvar.}: Switch + dst {.threadvar.}: Switch + rel {.threadvar.}: Switch + rsvp {.threadvar.}: Rsvp + conn {.threadvar.}: Connection + + asyncSetup: + customProtoCodec = "/test" + proto = new LPProtocol + proto.codec = customProtoCodec + ttl = 60 + ldur = 120 + ldata = 16384 + srcCl = RelayClient.new() + dstCl = RelayClient.new() + src = createSwitch(srcCl) + dst = createSwitch(dstCl) + rel = newStandardSwitch() + addrs = MultiAddress.init($rel.peerInfo.addrs[0] & "/p2p/" & + $rel.peerInfo.peerId & "/p2p-circuit/p2p/" & + $dst.peerInfo.peerId).get() + + asyncTest "Connection succeed": + proto.handler = proc(conn: Connection, proto: string) {.async.} = + check: "test1" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("test2") + check: "test3" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("test4") + await conn.close() + rv2 = Relay.new(reservationTTL=initDuration(seconds=ttl), + limitDuration=ldur, + limitData=ldata) + rv2.setup(rel) + rel.mount(rv2) + dst.mount(proto) + + await rel.start() + await src.start() + await dst.start() + + await src.connect(rel.peerInfo.peerId, rel.peerInfo.addrs) + await dst.connect(rel.peerInfo.peerId, rel.peerInfo.addrs) + + rsvp = await dstCl.reserve(rel.peerInfo.peerId, rel.peerInfo.addrs) + + conn = await src.dial(dst.peerInfo.peerId, @[ addrs ], customProtoCodec) + await conn.writeLp("test1") + check: "test2" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("test3") + check: "test4" == string.fromBytes(await conn.readLp(1024)) + await allFutures(conn.close()) + await allFutures(src.stop(), dst.stop(), rel.stop()) + + asyncTest "Connection duration exceeded": + ldur = 2 + proto.handler = proc(conn: Connection, proto: string) {.async.} = + check "wanna sleep?" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("yeah!") + check "go!" == string.fromBytes(await conn.readLp(1024)) + await sleepAsync(3000) + await conn.writeLp("that was a cool power nap") + await conn.close() + rv2 = Relay.new(reservationTTL=initDuration(seconds=ttl), + limitDuration=ldur, + limitData=ldata) + rv2.setup(rel) + rel.mount(rv2) + dst.mount(proto) + + await rel.start() + await src.start() + await dst.start() + + await src.connect(rel.peerInfo.peerId, rel.peerInfo.addrs) + await dst.connect(rel.peerInfo.peerId, rel.peerInfo.addrs) + + rsvp = await dstCl.reserve(rel.peerInfo.peerId, rel.peerInfo.addrs) + conn = await src.dial(dst.peerInfo.peerId, @[ addrs ], customProtoCodec) + await conn.writeLp("wanna sleep?") + check: "yeah!" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("go!") + expect(LPStreamEOFError): + discard await conn.readLp(1024) + await allFutures(conn.close()) + await allFutures(src.stop(), dst.stop(), rel.stop()) + + asyncTest "Connection data exceeded": + ldata = 1000 + proto.handler = proc(conn: Connection, proto: string) {.async.} = + check "count me the better story you know" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("do you expect a lorem ipsum or...?") + check "surprise me!" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("""Call me Ishmael. Some years ago--never mind how long +precisely--having little or no money in my purse, and nothing +particular to interest me on shore, I thought I would sail about a +little and see the watery part of the world. It is a way I have of +driving off the spleen and regulating the circulation. Whenever I +find myself growing grim about the mouth; whenever it is a damp, +drizzly November in my soul; whenever I find myself involuntarily +pausing before coffin warehouses, and bringing up the rear of every +funeral I meet; and especially whenever my hypos get such an upper +hand of me, that it requires a strong moral principle to prevent me +from deliberately stepping into the street, and methodically knocking +people's hats off--then, I account it high time to get to sea as soon +as I can. This is my substitute for pistol and ball. With a +philosophical flourish Cato throws himself upon his sword; I quietly +take to the ship.""") + rv2 = Relay.new(reservationTTL=initDuration(seconds=ttl), + limitDuration=ldur, + limitData=ldata) + rv2.setup(rel) + rel.mount(rv2) + dst.mount(proto) + + await rel.start() + await src.start() + await dst.start() + + await src.connect(rel.peerInfo.peerId, rel.peerInfo.addrs) + await dst.connect(rel.peerInfo.peerId, rel.peerInfo.addrs) + + rsvp = await dstCl.reserve(rel.peerInfo.peerId, rel.peerInfo.addrs) + conn = await src.dial(dst.peerInfo.peerId, @[ addrs ], customProtoCodec) + await conn.writeLp("count me the better story you know") + check: "do you expect a lorem ipsum or...?" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("surprise me!") + expect(LPStreamEOFError): + discard await conn.readLp(1024) + await allFutures(conn.close()) + await allFutures(src.stop(), dst.stop(), rel.stop()) + + asyncTest "Reservation ttl expire during connection": + ttl = 1 + proto.handler = proc(conn: Connection, proto: string) {.async.} = + check: "test1" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("test2") + check: "test3" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("test4") + await conn.close() + rv2 = Relay.new(reservationTTL=initDuration(seconds=ttl), + limitDuration=ldur, + limitData=ldata) + rv2.setup(rel) + rel.mount(rv2) + dst.mount(proto) + + await rel.start() + await src.start() + await dst.start() + + await src.connect(rel.peerInfo.peerId, rel.peerInfo.addrs) + await dst.connect(rel.peerInfo.peerId, rel.peerInfo.addrs) + + rsvp = await dstCl.reserve(rel.peerInfo.peerId, rel.peerInfo.addrs) + conn = await src.dial(dst.peerInfo.peerId, @[ addrs ], customProtoCodec) + await conn.writeLp("test1") + check: "test2" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("test3") + check: "test4" == string.fromBytes(await conn.readLp(1024)) + await src.disconnect(rel.peerInfo.peerId) + await sleepAsync(2000) + + expect(DialFailedError): + check: conn.atEof() + await conn.close() + await src.connect(rel.peerInfo.peerId, rel.peerInfo.addrs) + conn = await src.dial(dst.peerInfo.peerId, @[ addrs ], customProtoCodec) + await allFutures(conn.close()) + await allFutures(src.stop(), dst.stop(), rel.stop()) + + asyncTest "Connection over relay": + # src => rel => rel2 => dst + # rel2 reserve rel + # dst reserve rel2 + # src try to connect with dst + proto.handler = proc(conn: Connection, proto: string) {.async.} = + raise newException(CatchableError, "Should not be here") + let + rel2Cl = RelayClient.new(canHop = true) + rel2 = createSwitch(rel2Cl) + rv2 = Relay.new() + addrs = @[ MultiAddress.init($rel.peerInfo.addrs[0] & "/p2p/" & + $rel.peerInfo.peerId & "/p2p-circuit/p2p/" & + $rel2.peerInfo.peerId & "/p2p/" & + $rel2.peerInfo.peerId & "/p2p-circuit/p2p/" & + $dst.peerInfo.peerId).get() ] + rv2.setup(rel) + rel.mount(rv2) + dst.mount(proto) + await rel.start() + await rel2.start() + await src.start() + await dst.start() + + await src.connect(rel.peerInfo.peerId, rel.peerInfo.addrs) + await rel2.connect(rel.peerInfo.peerId, rel.peerInfo.addrs) + await dst.connect(rel2.peerInfo.peerId, rel2.peerInfo.addrs) + + rsvp = await rel2Cl.reserve(rel.peerInfo.peerId, rel.peerInfo.addrs) + let rsvp2 = await dstCl.reserve(rel2.peerInfo.peerId, rel2.peerInfo.addrs) + + expect(DialFailedError): + conn = await src.dial(dst.peerInfo.peerId, addrs, customProtoCodec) + await allFutures(conn.close()) + await allFutures(src.stop(), dst.stop(), rel.stop(), rel2.stop()) + + asyncTest "Connection using ClientRelay": + var + protoABC = new LPProtocol + protoBCA = new LPProtocol + protoCAB = new LPProtocol + protoABC.codec = "/abctest" + protoABC.handler = proc(conn: Connection, proto: string) {.async.} = + check: "testABC1" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("testABC2") + check: "testABC3" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("testABC4") + await conn.close() + protoBCA.codec = "/bcatest" + protoBCA.handler = proc(conn: Connection, proto: string) {.async.} = + check: "testBCA1" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("testBCA2") + check: "testBCA3" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("testBCA4") + await conn.close() + protoCAB.codec = "/cabtest" + protoCAB.handler = proc(conn: Connection, proto: string) {.async.} = + check: "testCAB1" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("testCAB2") + check: "testCAB3" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("testCAB4") + await conn.close() + + let + clientA = RelayClient.new(canHop = true) + clientB = RelayClient.new(canHop = true) + clientC = RelayClient.new(canHop = true) + switchA = createSwitch(clientA) + switchB = createSwitch(clientB) + switchC = createSwitch(clientC) + addrsABC = MultiAddress.init($switchB.peerInfo.addrs[0] & "/p2p/" & + $switchB.peerInfo.peerId & "/p2p-circuit/p2p/" & + $switchC.peerInfo.peerId).get() + addrsBCA = MultiAddress.init($switchC.peerInfo.addrs[0] & "/p2p/" & + $switchC.peerInfo.peerId & "/p2p-circuit/p2p/" & + $switchA.peerInfo.peerId).get() + addrsCAB = MultiAddress.init($switchA.peerInfo.addrs[0] & "/p2p/" & + $switchA.peerInfo.peerId & "/p2p-circuit/p2p/" & + $switchB.peerInfo.peerId).get() + switchA.mount(protoBCA) + switchB.mount(protoCAB) + switchC.mount(protoABC) + + await switchA.start() + await switchB.start() + await switchC.start() + + await switchA.connect(switchB.peerInfo.peerId, switchB.peerInfo.addrs) + await switchB.connect(switchC.peerInfo.peerId, switchC.peerInfo.addrs) + await switchC.connect(switchA.peerInfo.peerId, switchA.peerInfo.addrs) + let rsvpABC = await clientA.reserve(switchC.peerInfo.peerId, switchC.peerInfo.addrs) + let rsvpBCA = await clientB.reserve(switchA.peerInfo.peerId, switchA.peerInfo.addrs) + let rsvpCAB = await clientC.reserve(switchB.peerInfo.peerId, switchB.peerInfo.addrs) + let connABC = await switchA.dial(switchC.peerInfo.peerId, @[ addrsABC ], "/abctest") + let connBCA = await switchB.dial(switchA.peerInfo.peerId, @[ addrsBCA ], "/bcatest") + let connCAB = await switchC.dial(switchB.peerInfo.peerId, @[ addrsCAB ], "/cabtest") + + await connABC.writeLp("testABC1") + await connBCA.writeLp("testBCA1") + await connCAB.writeLp("testCAB1") + check: + "testABC2" == string.fromBytes(await connABC.readLp(1024)) + "testBCA2" == string.fromBytes(await connBCA.readLp(1024)) + "testCAB2" == string.fromBytes(await connCAB.readLp(1024)) + await connABC.writeLp("testABC3") + await connBCA.writeLp("testBCA3") + await connCAB.writeLp("testCAB3") + check: + "testABC4" == string.fromBytes(await connABC.readLp(1024)) + "testBCA4" == string.fromBytes(await connBCA.readLp(1024)) + "testCAB4" == string.fromBytes(await connCAB.readLp(1024)) + await allFutures(connABC.close(), connBCA.close(), connCAB.close()) + await allFutures(switchA.stop(), switchB.stop(), switchC.stop()) diff --git a/vendor/nim-libp2p/tests/testrsa.nim b/vendor/nim-libp2p/tests/testrsa.nim index a209f4446..83d6a8dd0 100644 --- a/vendor/nim-libp2p/tests/testrsa.nim +++ b/vendor/nim-libp2p/tests/testrsa.nim @@ -1,11 +1,11 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. import unittest2 import nimcrypto/utils import ../libp2p/crypto/[crypto, rsa] diff --git a/vendor/nim-libp2p/tests/testsecp256k1.nim b/vendor/nim-libp2p/tests/testsecp256k1.nim index c87e463ad..03c2920c7 100644 --- a/vendor/nim-libp2p/tests/testsecp256k1.nim +++ b/vendor/nim-libp2p/tests/testsecp256k1.nim @@ -1,12 +1,12 @@ -## Nim-Libp2p -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. -import unittest2, bearssl +# Nim-Libp2p +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. +import unittest2 import ../libp2p/crypto/[crypto, secp] import nimcrypto/utils diff --git a/vendor/nim-libp2p/tests/testswitch.nim b/vendor/nim-libp2p/tests/testswitch.nim index 23cb6ed0b..3d47b1a5b 100644 --- a/vendor/nim-libp2p/tests/testswitch.nim +++ b/vendor/nim-libp2p/tests/testswitch.nim @@ -21,6 +21,7 @@ import ../libp2p/[errors, nameresolving/nameresolver, nameresolving/mockresolver, stream/chronosstream, + utils/semaphore, transports/tcptransport, transports/wstransport] import ./helpers @@ -200,12 +201,32 @@ suite "Switch": check not switch1.isConnected(switch2.peerInfo.peerId) check not switch2.isConnected(switch1.peerInfo.peerId) + asyncTest "e2e connect to peer with unkown PeerId": + let switch1 = newStandardSwitch(secureManagers = [SecureProtocol.Noise]) + let switch2 = newStandardSwitch(secureManagers = [SecureProtocol.Noise]) + await switch1.start() + await switch2.start() + + check: (await switch2.connect(switch1.peerInfo.addrs)) == switch1.peerInfo.peerId + await switch2.disconnect(switch1.peerInfo.peerId) + + await allFuturesThrowing( + switch1.stop(), + switch2.stop() + ) + asyncTest "e2e should not leak on peer disconnect": let switch1 = newStandardSwitch() let switch2 = newStandardSwitch() await switch1.start() await switch2.start() + let startCounts = + @[ + switch1.connManager.inSema.count, switch1.connManager.outSema.count, + switch2.connManager.inSema.count, switch2.connManager.outSema.count + ] + await switch2.connect(switch1.peerInfo.peerId, switch1.peerInfo.addrs) check switch1.isConnected(switch2.peerInfo.peerId) @@ -219,6 +240,15 @@ suite "Switch": checkTracker(LPChannelTrackerName) checkTracker(SecureConnTrackerName) + await sleepAsync(1.seconds) + + check: + startCounts == + @[ + switch1.connManager.inSema.count, switch1.connManager.outSema.count, + switch2.connManager.inSema.count, switch2.connManager.outSema.count + ] + await allFuturesThrowing( switch1.stop(), switch2.stop()) @@ -979,3 +1009,29 @@ suite "Switch": await destSwitch.stop() await srcWsSwitch.stop() await srcTcpSwitch.stop() + + asyncTest "mount unstarted protocol": + proc handle(conn: Connection, proto: string) {.async, gcsafe.} = + check "test123" == string.fromBytes(await conn.readLp(1024)) + await conn.writeLp("test456") + await conn.close() + let + src = newStandardSwitch() + dst = newStandardSwitch() + testProto = new TestProto + testProto.codec = TestCodec + testProto.handler = handle + + await src.start() + await dst.start() + expect LPError: + dst.mount(testProto) + await testProto.start() + dst.mount(testProto) + + let conn = await src.dial(dst.peerInfo.peerId, dst.peerInfo.addrs, TestCodec) + await conn.writeLp("test123") + check "test456" == string.fromBytes(await conn.readLp(1024)) + await conn.close() + await src.stop() + await dst.stop() diff --git a/vendor/nim-libp2p/tests/testyamux.nim b/vendor/nim-libp2p/tests/testyamux.nim new file mode 100644 index 000000000..1d745552c --- /dev/null +++ b/vendor/nim-libp2p/tests/testyamux.nim @@ -0,0 +1,154 @@ +import sugar +import chronos +import + ../libp2p/[ + stream/connection, + muxers/yamux/yamux + ], + ./helpers + +suite "Yamux": + teardown: + checkTrackers() + + template mSetup {.inject.} = + #TODO in a template to avoid threadvar + let + (conna {.inject.}, connb {.inject.}) = bridgedConnections() + (yamuxa {.inject.}, yamuxb {.inject.}) = (Yamux.new(conna), Yamux.new(connb)) + (handlera, handlerb) = (yamuxa.handle(), yamuxb.handle()) + + defer: + await allFutures( + conna.close(), connb.close(), + yamuxa.close(), yamuxb.close(), + handlera, handlerb) + + suite "Basic": + asyncTest "Simple test": + mSetup() + + yamuxb.streamHandler = proc(conn: Connection) {.async.} = + check (await conn.readLp(100)) == fromHex("1234") + await conn.writeLp(fromHex("5678")) + await conn.close() + + let streamA = await yamuxa.newStream() + await streamA.writeLp(fromHex("1234")) + check (await streamA.readLp(100)) == fromHex("5678") + await streamA.close() + + asyncTest "Continuing read after close": + mSetup() + let + readerBlocker = newFuture[void]() + handlerBlocker = newFuture[void]() + var numberOfRead = 0 + yamuxb.streamHandler = proc(conn: Connection) {.async.} = + await readerBlocker + var buffer: array[25600, byte] + while (await conn.readOnce(addr buffer[0], 25600)) > 0: + numberOfRead.inc() + await conn.close() + handlerBlocker.complete() + + let streamA = await yamuxa.newStream() + await wait(streamA.write(newSeq[byte](256000)), 1.seconds) # shouldn't block + await streamA.close() + readerBlocker.complete() + await handlerBlocker + check: numberOfRead == 10 + + suite "Window exhaustion": + asyncTest "Basic exhaustion blocking": + mSetup() + let readerBlocker = newFuture[void]() + yamuxb.streamHandler = proc(conn: Connection) {.async.} = + await readerBlocker + var buffer: array[160000, byte] + discard await conn.readOnce(addr buffer[0], 160000) + await conn.close() + let streamA = await yamuxa.newStream() + await wait(streamA.write(newSeq[byte](256000)), 1.seconds) # shouldn't block + + let secondWriter = streamA.write(newSeq[byte](20)) + await sleepAsync(10.milliseconds) + check: not secondWriter.finished() + + readerBlocker.complete() + await wait(secondWriter, 1.seconds) + + await streamA.close() + + asyncTest "Exhaustion doesn't block other channels": + mSetup() + let readerBlocker = newFuture[void]() + yamuxb.streamHandler = proc(conn: Connection) {.async.} = + await readerBlocker + var buffer: array[160000, byte] + discard await conn.readOnce(addr buffer[0], 160000) + await conn.close() + let streamA = await yamuxa.newStream() + await wait(streamA.write(newSeq[byte](256000)), 1.seconds) # shouldn't block + + let secondWriter = streamA.write(newSeq[byte](20)) + await sleepAsync(10.milliseconds) + + # Now that the secondWriter is stuck, create a second stream + # and exchange some data + yamuxb.streamHandler = proc(conn: Connection) {.async.} = + check (await conn.readLp(100)) == fromHex("1234") + await conn.writeLp(fromHex("5678")) + await conn.close() + + let streamB = await yamuxa.newStream() + await streamB.writeLp(fromHex("1234")) + check (await streamB.readLp(100)) == fromHex("5678") + check: not secondWriter.finished() + readerBlocker.complete() + + await wait(secondWriter, 1.seconds) + await streamA.close() + await streamB.close() + + asyncTest "Can set custom window size": + mSetup() + + let writerBlocker = newFuture[void]() + var numberOfRead = 0 + yamuxb.streamHandler = proc(conn: Connection) {.async.} = + YamuxChannel(conn).setMaxRecvWindow(20) + var buffer: array[256000, byte] + while (await conn.readOnce(addr buffer[0], 256000)) > 0: + numberOfRead.inc() + writerBlocker.complete() + await conn.close() + let streamA = await yamuxa.newStream() + # Need to exhaust initial window first + await wait(streamA.write(newSeq[byte](256000)), 1.seconds) # shouldn't block + await streamA.write(newSeq[byte](142)) + await streamA.close() + + await writerBlocker + + # 1 for initial exhaustion + (142 / 20) = 9 + check numberOfRead == 9 + + asyncTest "Saturate until reset": + mSetup() + let writerBlocker = newFuture[void]() + yamuxb.streamHandler = proc(conn: Connection) {.async.} = + await writerBlocker + var buffer: array[256, byte] + check: (await conn.readOnce(addr buffer[0], 256)) == 0 + await conn.close() + + let streamA = await yamuxa.newStream() + await streamA.write(newSeq[byte](256000)) + let wrFut = collect(newSeq): + for _ in 0..3: + streamA.write(newSeq[byte](100000)) + for i in 0..3: + expect(LPStreamEOFError): await wrFut[i] + writerBlocker.complete() + await streamA.close() diff --git a/vendor/nim-libp2p/tools/pbcap_parser.nim b/vendor/nim-libp2p/tools/pbcap_parser.nim index af55e700e..a13ab794d 100644 --- a/vendor/nim-libp2p/tools/pbcap_parser.nim +++ b/vendor/nim-libp2p/tools/pbcap_parser.nim @@ -1,11 +1,11 @@ -## Nim-LibP2P -## Copyright (c) 2018 Status Research & Development GmbH -## Licensed under either of -## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) -## * MIT license ([LICENSE-MIT](LICENSE-MIT)) -## at your option. -## This file may not be copied, modified, or distributed except according to -## those terms. +# Nim-LibP2P +# Copyright (c) 2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. import std/[os, strutils, times] import chronicles import ../libp2p/debugutils diff --git a/vendor/nim-metrics/.github/workflows/ci.yml b/vendor/nim-metrics/.github/workflows/ci.yml index 19b40bb81..69b1479a0 100644 --- a/vendor/nim-metrics/.github/workflows/ci.yml +++ b/vendor/nim-metrics/.github/workflows/ci.yml @@ -146,10 +146,6 @@ jobs: - name: Run tests run: | - if [[ "${{ matrix.target.os }}" == "windows" ]]; then - # https://github.com/status-im/nimbus-eth2/issues/3121 - export NIMFLAGS="-d:nimRawSetjmp" - fi nim --version nimble --version nimble install -y --depsOnly @@ -157,6 +153,3 @@ jobs: nimble install -y chronicles nimble test nimble test_chronicles - export TEST_LANG=cpp - nimble test - nimble test_chronicles diff --git a/vendor/nim-metrics/.gitignore b/vendor/nim-metrics/.gitignore index 32d95ba6d..0a3de04c6 100644 --- a/vendor/nim-metrics/.gitignore +++ b/vendor/nim-metrics/.gitignore @@ -1,3 +1,5 @@ nimcache/ /build +nimble.develop +nimble.paths diff --git a/vendor/nim-metrics/config.nims b/vendor/nim-metrics/config.nims new file mode 100644 index 000000000..7c9db3205 --- /dev/null +++ b/vendor/nim-metrics/config.nims @@ -0,0 +1,4 @@ +# begin Nimble config (version 1) +when fileExists("nimble.paths"): + include "nimble.paths" +# end Nimble config diff --git a/vendor/nim-metrics/metrics.nim b/vendor/nim-metrics/metrics.nim index d4b94959d..0c999a867 100644 --- a/vendor/nim-metrics/metrics.nim +++ b/vendor/nim-metrics/metrics.nim @@ -72,10 +72,10 @@ when defined(metrics): return convert(Seconds, Milliseconds, time.toUnix()) + convert(Nanoseconds, Milliseconds, time.nanosecond()) template processHelp*(help: string): string = - help.multireplace([("\\", "\\\\"), ("\n", "\\n")]) + help.multiReplace([("\\", "\\\\"), ("\n", "\\n")]) template processLabelValue*(labelValue: string): string = - labelValue.multireplace([("\\", "\\\\"), ("\n", "\\n"), ("\"", "\\\"")]) + labelValue.multiReplace([("\\", "\\\\"), ("\n", "\\n"), ("\"", "\\\"")]) proc toText*(metric: Metric, showTimestamp = true): string = result = metric.name @@ -1023,7 +1023,7 @@ when defined(metrics) and defined(linux): # /proc not mounted? discard ticks = sysconf(SC_CLK_TCK).float64 - pagesize = sysconf(SC_PAGE_SIZE).float64 + pagesize = sysconf(SC_PAGESIZE).float64 type ProcessInfo = ref object of Gauge var processInfo* {.global.} = ProcessInfo.newCollector("process_info", "CPU and memory usage") @@ -1070,7 +1070,7 @@ when defined(metrics) and defined(linux): result[@[]].add( Metric( name: "process_max_fds", # Maximum number of open file descriptors. - value: line.splitWhiteSpace()[3].parseFloat(), # a simple `split()` does not combine adjacent whitespace + value: line.splitWhitespace()[3].parseFloat(), # a simple `split()` does not combine adjacent whitespace timestamp: timestamp, ) ) diff --git a/vendor/nim-metrics/metrics.nimble b/vendor/nim-metrics/metrics.nimble index d5681ff33..439275f4c 100644 --- a/vendor/nim-metrics/metrics.nimble +++ b/vendor/nim-metrics/metrics.nimble @@ -20,7 +20,19 @@ proc buildBinary(name: string, srcDir = "./", params = "") = # we're under Nim, not Nimble for i in 2.. 0: + copyMem(addr buffer[1], unsafeAddr message[0], length) + let res = await m.respTransp.write(addr buffer[0], len(buffer)) + if res != len(buffer): + raiseMetricsError("Incomplete response has been sent") + + proc communicate(m: MetricsHttpServerRef, + req: MetricsRequest): Future[MetricsResponse] {.async.} = + var buffer: array[MessageSize + 1, byte] + buffer[0] = byte(req) + block: + let res = await m.reqTransp.write(addr buffer[0], 1) + if res != 1: + raiseMetricsError("Incomplete request has been sent") + await m.respTransp.readExactly(addr buffer[0], len(buffer)) + var res = MetricsResponse(status: buffer[0]) + copyMem(addr res.data[0], addr buffer[1], sizeof(res.data)) + return res + + proc getMessage(m: MetricsResponse): string = + var res = newStringOfCap(MessageSize + 1) + for i in 0 ..< len(m.data): + let ch = m.data[i] + if ch == 0x00'u8: + break + res.add(char(ch)) + res + + proc asyncStep(server: MetricsServerData, data: MetricsThreadData, + lastError: string): Future[bool] {.async.} = + var buffer: array[1, byte] + try: + await data.reqTransp.readExactly(addr buffer[0], len(buffer)) + + if len(lastError) > 0: + await data.respond(ResponseError, lastError) + return true + + if isNil(data.http): + await data.respond(ResponseError, "HTTP server is not bound!") + return true + + return + case buffer[0] + of byte(MetricsRequest.Status): + let message = + case data.http.state() + of ServerStopped: "STOPPED" + of ServerClosed: "CLOSED" + of ServerRunning: "RUNNING" + await data.respond(ResponseOk, message) + true + of byte(MetricsRequest.Start): + if data.http.state() != HttpServerState.ServerStopped: + let message = + if data.http.state() == HttpServerState.ServerClosed: + "HTTP server is already closed" + else: + "HTTP server is already running" + await data.respond(ResponseError, message) + else: + data.http.start() + await data.respond(ResponseOk, "") + true + of byte(MetricsRequest.Stop): + if data.http.state() != HttpServerState.ServerRunning: + let message = + if data.http.state() == HttpServerState.ServerClosed: + "HTTP server is already closed" + else: + "HTTP server is already stopped" + await data.respond(ResponseError, message) + else: + await data.http.stop() + await data.respond(ResponseOk, "") + true + else: + if data.http.state() == HttpServerState.ServerClosed: + await data.respond(ResponseError, "HTTP server is already closed") + true + else: + await data.http.closeWait() + await data.respond(ResponseOk, "") + false + except CatchableError as exc: + printError(exc.msg) + if not(isNil(data.http)): + await data.http.closeWait() + return false + + proc asyncLoop(server: MetricsServerData) {.async.} = + var lastError = "" + + proc cb(r: RequestFence): Future[HttpResponseRef] {.async.} = + if r.isOk(): + let request = r.get() + try: + if request.uri.path == "/metrics": + {.gcsafe.}: + # Prometheus will drop our metrics in surprising ways if we give + # it timestamps, so we don't. + let response = defaultRegistry.toText(showTimestamp = false) + let headers = HttpTable.init([("Content-Type", CONTENT_TYPE)]) + return await request.respond(Http200, response, headers) + elif request.uri.path == "/health": + return await request.respond(Http200, "OK") + else: + return await request.respond(Http404, "Try /metrics") + except CatchableError as exc: + printError(exc.msg) + + let + http = + block: + let socketFlags = {ServerFlags.ReuseAddr} + let res = HttpServerRef.new(server.address, cb, + socketFlags = socketFlags) + if res.isErr(): + lastError = res.error() + nil + else: + res.get() + reqTransp = + try: + fromPipe(server.requestPipe.read) + except CatchableError as exc: + await http.closeWait() + return + respTransp = + try: + fromPipe(server.responsePipe.write) + except CatchableError as exc: + await http.closeWait() + await reqTransp.closeWait() + return + threadData = MetricsThreadData( + reqTransp: reqTransp, respTransp: respTransp, http: http) + + while true: + let res = await asyncStep(server, threadData, lastError) + if not(res): + break + + await allFutures(reqTransp.closeWait(), respTransp.closeWait()) + + proc serveMetricsServer(server: MetricsServerData) {.thread.} = + ignoreSignalsInThread() + let loop {.used.} = getThreadDispatcher() + try: + waitFor asyncLoop(server) + except Exception as exc: + printError($exc.msg) proc startMetricsHttpServer*(address = "127.0.0.1", port = Port(8000)) {. - raises: [Exception].} = + raises: [Exception], + deprecated: "Please use MetricsHttpServerRef API".} = when defined(metrics): httpServerThread.createThread(serveHttp, initTAddress(address, port)) +proc new*(t: typedesc[MetricsHttpServerRef], address: string, + port: Port): Result[MetricsHttpServerRef, cstring] {. + raises: [Defect].} = + ## Initialize new instance of MetricsHttpServerRef. + ## + ## This involves creation of new thread and new processing loop in the new + ## thread. + when defined(metrics): + template closePipe(b: untyped): untyped = + closeHandle(b.read) + closeHandle(b.write) + let + taddress = + try: + initTAddress(address, port) + except TransportAddressError as exc: + return err("Invalid server address") + var + request = + block: + let res = createAsyncPipe() + if (res.read == asyncInvalidPipe) or (res.write == asyncInvalidPipe): + return err("Unable to create communication request pipe") + res + cleanupRequest = true + defer: + if cleanupRequest: request.closePipe() + + var + response = + block: + let res = createAsyncPipe() + if (res.read == asyncInvalidPipe) or (res.write == asyncInvalidPipe): + request.closePipe() + return err("Unable to create communication response pipe") + res + cleanupResponse = true + defer: + if cleanupResponse: response.closePipe() + + let data = MetricsServerData(address: taddress, requestPipe: request, + responsePipe: response) + var server = MetricsHttpServerRef(data: data) + try: + createThread(server.thread, serveMetricsServer, data) + except Exception as exc: + return err("Unexpected error while spawning metrics server's thread") + except ResourceExhaustedError as exc: + return err("Unable to spawn metrics server's thread") + + server.reqTransp = + try: + fromPipe(request.write) + except CatchableError as exc: + return err("Unable to establish communication channel with " & + "metrics server thread") + server.respTransp = + try: + fromPipe(response.read) + except CatchableError as exc: + return err("Unable to establish communication channel with " & + "metrics server thread") + + cleanupRequest = false + cleanupResponse = false + ok(server) + else: + err("Could not initialize metrics server, because metrics are disabled") + +proc start*(server: MetricsHttpServerRef) {.async.} = + ## Start metrics HTTP server. + when defined(metrics): + if not(server.thread.running()): + raiseMetricsError("Metrics server is not running") + let resp = + try: + await communicate(server, MetricsRequest.Start).wait(5.seconds) + except AsyncTimeoutError as exc: + raiseMetricsError(MetricsErrorKind.Timeout, exc) + except MetricsError as exc: + raiseMetricsError(MetricsErrorKind.Communication, exc) + except TransportError as exc: + raiseMetricsError(MetricsErrorKind.Transport, exc) + if resp.status != 0x00'u8: + raiseMetricsError("Metrics server returns an error: " & resp.getMessage()) + +proc stop*(server: MetricsHttpServerRef) {.async.} = + ## Force metrics HTTP server to stop accepting new connections. + when defined(metrics): + if not(server.thread.running()): + raiseMetricsError("Metrics server is not running") + let resp = + try: + await communicate(server, MetricsRequest.Stop).wait(5.seconds) + except AsyncTimeoutError as exc: + raiseMetricsError(MetricsErrorKind.Timeout, exc) + except MetricsError as exc: + raiseMetricsError(MetricsErrorKind.Communication, exc) + except TransportError as exc: + raiseMetricsError(MetricsErrorKind.Transport, exc) + if resp.status != 0x00'u8: + raiseMetricsError("Metrics server returns an error: " & resp.getMessage()) + +proc close*(server: MetricsHttpServerRef) {.async.} = + ## Close metrics HTTP server and release all the resources. + when defined(metrics): + if not(server.thread.running()): + raiseMetricsError("Metrics server is not running") + let resp = + try: + await communicate(server, MetricsRequest.Close).wait(5.seconds) + except AsyncTimeoutError as exc: + raiseMetricsError(MetricsErrorKind.Timeout, exc) + except MetricsError as exc: + raiseMetricsError(MetricsErrorKind.Communication, exc) + except TransportError as exc: + raiseMetricsError(MetricsErrorKind.Transport, exc) + if resp.status != 0x00'u8: + raiseMetricsError("Metrics server returns an error: " & resp.getMessage()) + # Closing pipes, other pipe ends should be closed by foreign thread. + await allFutures(server.reqTransp.closeWait(), + server.respTransp.closeWait()) + # Thread should exit very soon. + server.thread.joinThread() + +proc status*(server: MetricsHttpServerRef): Future[MetricsHttpServerStatus] {. + async.} = + ## Returns current status of metrics HTTP server. + ## + ## Note, that if `metrics` variable is not defined this procedure will return + ## ``MetricsHttpServerStatus.Closed``. + when defined(metrics): + if not(server.thread.running()): + return MetricsHttpServerStatus.Closed + let resp = + try: + await communicate(server, MetricsRequest.Status).wait(5.seconds) + except AsyncTimeoutError as exc: + raiseMetricsError(MetricsErrorKind.Timeout, exc) + except MetricsError as exc: + raiseMetricsError(MetricsErrorKind.Communication, exc) + except TransportError as exc: + raiseMetricsError(MetricsErrorKind.Transport, exc) + if resp.status != 0x00'u8: + raiseMetricsError("Metrics server returns an error: " & resp.getMessage()) + let msg = resp.getMessage() + return + case msg + of "STOPPED": + MetricsHttpServerStatus.Stopped + of "CLOSED": + MetricsHttpServerStatus.Closed + of "RUNNING": + MetricsHttpServerStatus.Running + else: + raiseMetricsError("Metrics server returns unsupported status!") + else: + return MetricsHttpServerStatus.Closed diff --git a/vendor/nim-metrics/nim.cfg b/vendor/nim-metrics/nim.cfg new file mode 100644 index 000000000..371f6d79d --- /dev/null +++ b/vendor/nim-metrics/nim.cfg @@ -0,0 +1,5 @@ +# Avoid some rare stack corruption while using exceptions with a SEH-enabled +# toolchain: https://github.com/status-im/nimbus-eth2/issues/3121 +@if windows and not vcc: + --define:nimRawSetjmp +@end diff --git a/vendor/nim-metrics/nimble.lock b/vendor/nim-metrics/nimble.lock new file mode 100644 index 000000000..5811284fa --- /dev/null +++ b/vendor/nim-metrics/nimble.lock @@ -0,0 +1,64 @@ +{ + "version": 1, + "packages": { + "unittest2": { + "version": "0.0.4", + "vcsRevision": "f180f596c88dfd266f746ed6f8dbebce39c824db", + "url": "https://github.com/status-im/nim-unittest2.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "fa309c41eaf6ef57895b9e603f2620a2f6e11780" + } + }, + "stew": { + "version": "0.1.0", + "vcsRevision": "6ad35b876fb6ebe0dfee0f697af173acc47906ee", + "url": "https://github.com/status-im/nim-stew.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "46d58c4feb457f3241e3347778334e325dce5268" + } + }, + "httputils": { + "version": "0.3.0", + "vcsRevision": "689da19e9e9cfff4ced85e2b25c6b2b5598ed079", + "url": "https://github.com/status-im/nim-http-utils.git", + "downloadMethod": "git", + "dependencies": [ + "stew" + ], + "checksums": { + "sha1": "4ad3ad68d13c50184180ab4b2eacc0bd7ed2ed44" + } + }, + "bearssl": { + "version": "0.1.5", + "vcsRevision": "ba80e2a0d7ae8aab666cee013e38ff8d33a3e5e7", + "url": "https://github.com/status-im/nim-bearssl", + "downloadMethod": "git", + "dependencies": [ + "unittest2" + ], + "checksums": { + "sha1": "383abd5becc77bf8e365b780a29d20529e1d9c4c" + } + }, + "chronos": { + "version": "3.0.11", + "vcsRevision": "17fed89c99beac5a92d3668d0d3e9b0e4ac13936", + "url": "https://github.com/status-im/nim-chronos.git", + "downloadMethod": "git", + "dependencies": [ + "stew", + "bearssl", + "httputils", + "unittest2" + ], + "checksums": { + "sha1": "f6fffc87571e5f76af2a77c4ebcc0e00909ced4e" + } + } + } +} \ No newline at end of file diff --git a/vendor/nim-metrics/tests/chronos_server_tests.nim b/vendor/nim-metrics/tests/chronos_server_tests.nim index 8c8931fa9..d5c635521 100644 --- a/vendor/nim-metrics/tests/chronos_server_tests.nim +++ b/vendor/nim-metrics/tests/chronos_server_tests.nim @@ -1,14 +1,176 @@ -# Copyright (c) 2021 Status Research & Development GmbH +# Copyright (c) 2021-2022 Status Research & Development GmbH # Licensed and distributed under either of # * MIT license: http://opensource.org/licenses/MIT # * Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 # at your option. This file may not be copied, modified, or distributed except according to those terms. -import ../metrics, ../metrics/chronos_httpserver, - os, osproc +import std/[uri, unittest] +import chronos, chronos/apps/http/httpclient +import ../metrics, ../metrics/chronos_httpserver -startMetricsHttpServer() -sleep(1000) -when defined(metrics): - doAssert execCmd("curl http://127.0.0.1:8000/metrics") == 0 +suite "Chronos metrics HTTP server test suite": + proc httpClient(url: string): Future[HttpResponseTuple] {.async.} = + let session = HttpSessionRef.new() + try: + let resp = await session.fetch(parseUri(url)) + return resp + finally: + await session.closeWait() + + test "new()/close() test": + proc test() {.async.} = + let server = MetricsHttpServerRef.new("127.0.0.1", Port(8080)).get() + block: + let status = await server.status() + check status == MetricsHttpServerStatus.Stopped + await server.close() + block: + let status = await server.status() + check status == MetricsHttpServerStatus.Closed + when defined(metrics): + waitFor test() + else: + check MetricsHttpServerRef.new("127.0.0.1", Port(8080)).isErr() == true + test "new()/start()/stop()/close() test": + proc test() {.async.} = + let server = MetricsHttpServerRef.new("127.0.0.1", Port(8080)).get() + block: + let status = await server.status() + check status == MetricsHttpServerStatus.Stopped + await server.start() + block: + let status = await server.status() + check status == MetricsHttpServerStatus.Running + await server.stop() + block: + let status = await server.status() + check status == MetricsHttpServerStatus.Stopped + await server.close() + block: + let status = await server.status() + check status == MetricsHttpServerStatus.Closed + when defined(metrics): + waitFor test() + else: + check MetricsHttpServerRef.new("127.0.0.1", Port(8080)).isErr() == true + test "new()/start()/response/stop()/start()/response/stop()/close() test": + proc test() {.async.} = + let server = MetricsHttpServerRef.new("127.0.0.1", Port(8080)).get() + block: + let status = await server.status() + check status == MetricsHttpServerStatus.Stopped + await server.start() + block: + let status = await server.status() + check status == MetricsHttpServerStatus.Running + block: + let resp = await httpClient("http://127.0.0.1:8080/health") + check: + resp.status == 200 + resp.data.bytesToString == "OK" + await server.stop() + block: + let status = await server.status() + check status == MetricsHttpServerStatus.Stopped + await server.start() + block: + let status = await server.status() + check status == MetricsHttpServerStatus.Running + block: + let resp = await httpClient("http://127.0.0.1:8080/health") + check: + resp.status == 200 + resp.data.bytesToString == "OK" + await server.stop() + block: + let status = await server.status() + check status == MetricsHttpServerStatus.Stopped + await server.close() + block: + let status = await server.status() + check status == MetricsHttpServerStatus.Closed + when defined(metrics): + waitFor test() + else: + check MetricsHttpServerRef.new("127.0.0.1", Port(8080)).isErr() == true + test "new()/start()/close() test": + proc test() {.async.} = + let server = MetricsHttpServerRef.new("127.0.0.1", Port(8080)).get() + block: + let status = await server.status() + check status == MetricsHttpServerStatus.Stopped + await server.start() + block: + let status = await server.status() + check status == MetricsHttpServerStatus.Running + await server.close() + block: + let status = await server.status() + check status == MetricsHttpServerStatus.Closed + when defined(metrics): + waitFor test() + else: + check MetricsHttpServerRef.new("127.0.0.1", Port(8080)).isErr() == true + test "HTTP 200/responses check test": + proc test() {.async.} = + let server = MetricsHttpServerRef.new("127.0.0.1", Port(8080)).get() + block: + let status = await server.status() + check status == MetricsHttpServerStatus.Stopped + await server.start() + block: + let status = await server.status() + check status == MetricsHttpServerStatus.Running + block: + let resp = await httpClient("http://127.0.0.1:8080/metrics") + check: + resp.status == 200 + len(resp.data) > 0 + + block: + let resp = await httpClient("http://127.0.0.1:8080/health") + check: + resp.status == 200 + resp.data.bytesToString() == "OK" + await server.stop() + block: + let status = await server.status() + check status == MetricsHttpServerStatus.Stopped + await server.close() + block: + let status = await server.status() + check status == MetricsHttpServerStatus.Closed + when defined(metrics): + waitFor test() + else: + check MetricsHttpServerRef.new("127.0.0.1", Port(8080)).isErr() == true + test "HTTP 404/response check test": + proc test() {.async.} = + let server = MetricsHttpServerRef.new("127.0.0.1", Port(8080)).get() + block: + let status = await server.status() + check status == MetricsHttpServerStatus.Stopped + await server.start() + block: + let status = await server.status() + check status == MetricsHttpServerStatus.Running + + block: + let resp = await httpClient("http://127.0.0.1:8080/somePath") + check: + resp.status == 404 + len(resp.data) > 0 + + await server.stop() + block: + let status = await server.status() + check status == MetricsHttpServerStatus.Stopped + await server.close() + block: + let status = await server.status() + check status == MetricsHttpServerStatus.Closed + when defined(metrics): + waitFor test() + else: + check MetricsHttpServerRef.new("127.0.0.1", Port(8080)).isErr() == true diff --git a/vendor/nim-metrics/tests/nim.cfg b/vendor/nim-metrics/tests/nim.cfg new file mode 100644 index 000000000..371f6d79d --- /dev/null +++ b/vendor/nim-metrics/tests/nim.cfg @@ -0,0 +1,5 @@ +# Avoid some rare stack corruption while using exceptions with a SEH-enabled +# toolchain: https://github.com/status-im/nimbus-eth2/issues/3121 +@if windows and not vcc: + --define:nimRawSetjmp +@end diff --git a/vendor/nim-nat-traversal/.gitignore b/vendor/nim-nat-traversal/.gitignore index d49be7882..3eb2f9681 100644 --- a/vendor/nim-nat-traversal/.gitignore +++ b/vendor/nim-nat-traversal/.gitignore @@ -11,3 +11,5 @@ nimcache/ /examples/miniupnpc_test /examples/natpmp_test +nimble.develop +nimble.paths diff --git a/vendor/nim-nat-traversal/config.nims b/vendor/nim-nat-traversal/config.nims new file mode 100644 index 000000000..7c9db3205 --- /dev/null +++ b/vendor/nim-nat-traversal/config.nims @@ -0,0 +1,4 @@ +# begin Nimble config (version 1) +when fileExists("nimble.paths"): + include "nimble.paths" +# end Nimble config diff --git a/vendor/nim-nat-traversal/nat_traversal.nimble b/vendor/nim-nat-traversal/nat_traversal.nimble index 5516f2f65..0d9649fdc 100644 --- a/vendor/nim-nat-traversal/nat_traversal.nimble +++ b/vendor/nim-nat-traversal/nat_traversal.nimble @@ -8,7 +8,8 @@ license = "Apache License 2.0 or MIT" installDirs = @["vendor"] ### Dependencies -requires "nim >= 0.19.0", "stew" +requires "nim >= 1.2.0", + "stew" proc compileStaticLibraries() = var cc = getEnv("CC", "") @@ -34,4 +35,3 @@ task buildBundledLibs, "build bundled libraries": before install: compileStaticLibraries() - diff --git a/vendor/nim-nat-traversal/nat_traversal/miniupnpc.nim b/vendor/nim-nat-traversal/nat_traversal/miniupnpc.nim index 069730e94..f237b47a7 100644 --- a/vendor/nim-nat-traversal/nat_traversal/miniupnpc.nim +++ b/vendor/nim-nat-traversal/nat_traversal/miniupnpc.nim @@ -16,21 +16,21 @@ import std/strutils, ./utils when defined(miniupnpcUseSystemLibs): - {.passC: staticExec("pkg-config --cflags miniupnpc").} - {.passL: staticExec("pkg-config --libs miniupnpc").} + {.passc: staticExec("pkg-config --cflags miniupnpc").} + {.passl: staticExec("pkg-config --libs miniupnpc").} else: import os const includePath = currentSourcePath.parentDir().parentDir().replace('\\', '/') & "/vendor/miniupnp/miniupnpc" - {.passC: "-I" & includePath.} + {.passc: "-I" & includePath.} # We can't use the {.link.} pragma in here, because it would place the static # library archive as the first object to be linked, which would lead to all # its exported symbols being ignored. We move it into the last position with {.passL.}. - {.passL: includePath & "/libminiupnpc.a".} + {.passl: includePath & "/libminiupnpc.a".} when defined(windows): import nativesockets # for that wsaStartup() call at the end - {.passC: "-DMINIUPNP_STATICLIB".} - {.passL: "-lws2_32 -liphlpapi".} + {.passc: "-DMINIUPNP_STATICLIB".} + {.passl: "-lws2_32 -liphlpapi".} ################ # upnperrors.h # diff --git a/vendor/nim-nat-traversal/nat_traversal/natpmp.nim b/vendor/nim-nat-traversal/nat_traversal/natpmp.nim index b03b3e41d..5ccd6ab04 100644 --- a/vendor/nim-nat-traversal/nat_traversal/natpmp.nim +++ b/vendor/nim-nat-traversal/nat_traversal/natpmp.nim @@ -19,22 +19,22 @@ else: import posix when defined(libnatpmpUseSystemLibs): - {.passL: "-lnatpmp".} + {.passl: "-lnatpmp".} else: const includePath = currentSourcePath.parentDir().parentDir().replace('\\', '/') & "/vendor/libnatpmp-upstream" - {.passC: "-I" & includePath.} - {.passL: includePath & "/libnatpmp.a".} + {.passc: "-I" & includePath.} + {.passl: includePath & "/libnatpmp.a".} when defined(windows): import nativesockets # for that wsaStartup() call at the end - {.passC: "-DNATPMP_STATICLIB".} - {.passL: "-lws2_32 -liphlpapi".} + {.passc: "-DNATPMP_STATICLIB".} + {.passl: "-lws2_32 -liphlpapi".} ############ # natpmp.h # ############ -{.passC: "-DENABLE_STRNATPMPERR".} +{.passc: "-DENABLE_STRNATPMPERR".} ## NAT-PMP Port as defined by the NAT-PMP draft const NATPMP_PORT* = cint(5351) diff --git a/vendor/nim-nat-traversal/nimble.lock b/vendor/nim-nat-traversal/nimble.lock new file mode 100644 index 000000000..e2e37bb60 --- /dev/null +++ b/vendor/nim-nat-traversal/nimble.lock @@ -0,0 +1,15 @@ +{ + "version": 1, + "packages": { + "stew": { + "version": "0.1.0", + "vcsRevision": "6ad35b876fb6ebe0dfee0f697af173acc47906ee", + "url": "https://github.com/status-im/nim-stew.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "46d58c4feb457f3241e3347778334e325dce5268" + } + } + } +} \ No newline at end of file diff --git a/vendor/nim-presto/.github/workflows/ci.yml b/vendor/nim-presto/.github/workflows/ci.yml index 826c7fca7..29fe78794 100644 --- a/vendor/nim-presto/.github/workflows/ci.yml +++ b/vendor/nim-presto/.github/workflows/ci.yml @@ -30,7 +30,7 @@ jobs: shell: bash - target: os: macos - builder: macos-10.15 + builder: macos-11 shell: bash - target: os: windows @@ -150,10 +150,6 @@ jobs: - name: Run tests run: | - if [[ "${{ matrix.target.os }}" == "windows" ]]; then - # https://github.com/status-im/nimbus-eth2/issues/3121 - export NIMFLAGS="-d:nimRawSetjmp" - fi nim --version nimble --version nimble install -y --depsOnly diff --git a/vendor/nim-presto/.gitignore b/vendor/nim-presto/.gitignore index ff45144c9..f2e7e9b9a 100644 --- a/vendor/nim-presto/.gitignore +++ b/vendor/nim-presto/.gitignore @@ -1,2 +1,4 @@ nimcache *.exe +nimble.develop +nimble.paths diff --git a/vendor/nim-presto/config.nims b/vendor/nim-presto/config.nims new file mode 100644 index 000000000..7c9db3205 --- /dev/null +++ b/vendor/nim-presto/config.nims @@ -0,0 +1,4 @@ +# begin Nimble config (version 1) +when fileExists("nimble.paths"): + include "nimble.paths" +# end Nimble config diff --git a/vendor/nim-presto/nim.cfg b/vendor/nim-presto/nim.cfg new file mode 100644 index 000000000..371f6d79d --- /dev/null +++ b/vendor/nim-presto/nim.cfg @@ -0,0 +1,5 @@ +# Avoid some rare stack corruption while using exceptions with a SEH-enabled +# toolchain: https://github.com/status-im/nimbus-eth2/issues/3121 +@if windows and not vcc: + --define:nimRawSetjmp +@end diff --git a/vendor/nim-presto/nimble.lock b/vendor/nim-presto/nimble.lock new file mode 100644 index 000000000..a5a70444f --- /dev/null +++ b/vendor/nim-presto/nimble.lock @@ -0,0 +1,131 @@ +{ + "version": 1, + "packages": { + "unittest2": { + "version": "0.0.4", + "vcsRevision": "f180f596c88dfd266f746ed6f8dbebce39c824db", + "url": "https://github.com/status-im/nim-unittest2.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "fa309c41eaf6ef57895b9e603f2620a2f6e11780" + } + }, + "testutils": { + "version": "0.4.2", + "vcsRevision": "aa6e5216f4b4ab5aa971cdcdd70e1ec1203cedf2", + "url": "https://github.com/status-im/nim-testutils", + "downloadMethod": "git", + "dependencies": [ + "unittest2" + ], + "checksums": { + "sha1": "94427e0cce0e0c5841edcd3a6530b4e6b857a3cb" + } + }, + "stew": { + "version": "0.1.0", + "vcsRevision": "6ad35b876fb6ebe0dfee0f697af173acc47906ee", + "url": "https://github.com/status-im/nim-stew.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "46d58c4feb457f3241e3347778334e325dce5268" + } + }, + "bearssl": { + "version": "0.1.5", + "vcsRevision": "ba80e2a0d7ae8aab666cee013e38ff8d33a3e5e7", + "url": "https://github.com/status-im/nim-bearssl", + "downloadMethod": "git", + "dependencies": [ + "unittest2" + ], + "checksums": { + "sha1": "383abd5becc77bf8e365b780a29d20529e1d9c4c" + } + }, + "httputils": { + "version": "0.3.0", + "vcsRevision": "689da19e9e9cfff4ced85e2b25c6b2b5598ed079", + "url": "https://github.com/status-im/nim-http-utils.git", + "downloadMethod": "git", + "dependencies": [ + "stew" + ], + "checksums": { + "sha1": "4ad3ad68d13c50184180ab4b2eacc0bd7ed2ed44" + } + }, + "chronos": { + "version": "3.0.11", + "vcsRevision": "17fed89c99beac5a92d3668d0d3e9b0e4ac13936", + "url": "https://github.com/status-im/nim-chronos.git", + "downloadMethod": "git", + "dependencies": [ + "stew", + "bearssl", + "httputils", + "unittest2" + ], + "checksums": { + "sha1": "f6fffc87571e5f76af2a77c4ebcc0e00909ced4e" + } + }, + "faststreams": { + "version": "0.3.0", + "vcsRevision": "1b561a9e71b6bdad1c1cdff753418906037e9d09", + "url": "https://github.com/status-im/nim-faststreams.git", + "downloadMethod": "git", + "dependencies": [ + "stew", + "testutils", + "chronos", + "unittest2" + ], + "checksums": { + "sha1": "97edf9797924af48566a0af8267203dc21d80c77" + } + }, + "serialization": { + "version": "0.1.0", + "vcsRevision": "fcd0eadadde0ee000a63df8ab21dc4e9f015a790", + "url": "https://github.com/status-im/nim-serialization.git", + "downloadMethod": "git", + "dependencies": [ + "faststreams", + "unittest2", + "stew" + ], + "checksums": { + "sha1": "fef59519892cac70cccd81b612085caaa5e3e6cf" + } + }, + "json_serialization": { + "version": "0.1.0", + "vcsRevision": "c5f0e2465e8375dfc7aa0f56ccef67cb680bc6b0", + "url": "https://github.com/status-im/nim-json-serialization.git", + "downloadMethod": "git", + "dependencies": [ + "serialization", + "stew" + ], + "checksums": { + "sha1": "d89d79d0679a3a41b350e3ad4be56c0308cc5ec6" + } + }, + "chronicles": { + "version": "0.10.2", + "vcsRevision": "1682096306ddba8185dcfac360a8c3f952d721e4", + "url": "https://github.com/status-im/nim-chronicles.git", + "downloadMethod": "git", + "dependencies": [ + "testutils", + "json_serialization" + ], + "checksums": { + "sha1": "9a5bebb76b0f7d587a31e621d260119279e91c76" + } + } + } +} \ No newline at end of file diff --git a/vendor/nim-presto/presto.nimble b/vendor/nim-presto/presto.nimble index 40a075ed0..36d409f2d 100644 --- a/vendor/nim-presto/presto.nimble +++ b/vendor/nim-presto/presto.nimble @@ -13,7 +13,14 @@ requires "nim >= 1.2.0", "stew" proc runTest(filename: string) = - var excstr: string = "nim c -r --hints:off --skipParentCfg " & getEnv("NIMFLAGS") & " " + let styleCheckStyle = + if (NimMajor, NimMinor) < (1, 6): + "hint" + else: + "error" + var excstr: string = + "nim c -r --hints:off --styleCheck:usages --styleCheck:" & styleCheckStyle & + " --skipParentCfg " & getEnv("NIMFLAGS") & " " excstr.add("tests/" & filename) exec excstr rmFile "tests/" & filename.toExe diff --git a/vendor/nim-presto/presto/client.nim b/vendor/nim-presto/presto/client.nim index cec24dbc0..4f99dd3fb 100644 --- a/vendor/nim-presto/presto/client.nim +++ b/vendor/nim-presto/presto/client.nim @@ -266,7 +266,7 @@ proc raiseRestDecodingBytesError*(message: cstring) {.noreturn, noinline.} = msg.add("]") raise (ref RestDecodingError)(msg: msg) -proc newArrayNode(nodes: openarray[NimNode]): NimNode = +proc newArrayNode(nodes: openArray[NimNode]): NimNode = newTree(nnkBracket, @nodes) proc isPostMethod(node: NimNode): bool {.compileTime.} = diff --git a/vendor/nim-presto/presto/common.nim b/vendor/nim-presto/presto/common.nim index db9b74339..f01a75996 100644 --- a/vendor/nim-presto/presto/common.nim +++ b/vendor/nim-presto/presto/common.nim @@ -7,13 +7,17 @@ # Apache License, version 2.0, (LICENSE-APACHEv2) # MIT license (LICENSE-MIT) import chronos/apps, chronos/apps/http/httpclient -import stew/[results, byteutils] -export results, apps +import stew/[results, byteutils], httputils +export results, apps, httputils {.push raises: [Defect].} type ContentBody* = object + contentType*: ContentTypeData + data*: seq[byte] + + ResponseContentBody* = object contentType*: string data*: seq[byte] @@ -29,11 +33,12 @@ type RestApiResponse* = object status*: HttpCode + headers*: HttpTable case kind*: RestApiResponseKind of RestApiResponseKind.Empty: discard of RestApiResponseKind.Content: - content*: ContentBody + content*: ResponseContentBody of RestApiResponseKind.Error: errobj*: RestApiError of RestApiResponseKind.Redirect: @@ -55,31 +60,97 @@ type status*: int contentType*: string message*: string + RestKeyValueTuple* = tuple[key: string, value: string] + +proc init*(t: typedesc[ContentBody], + contentType: MediaType, data: openArray[byte]): ContentBody = + ContentBody( + contentType: ContentTypeData(status: HttpStatus.Success, + mediaType: contentType), + data: @data + ) + +proc error*(t: typedesc[RestApiResponse], + status: HttpCode = Http200, msg: string = "", + contentType: string = "text/html", + headers: HttpTable): RestApiResponse = + ## Create REST API error response with status ``status`` and content specified + ## by type ``contentType`` and data ``data``. You can also specify + ## additional HTTP response headers using ``headers`` argument. + ## + ## Please note that ``contentType`` argument's value has priority over + ## ``Content-Type`` header's value in ``headers`` table. + RestApiResponse(kind: RestApiResponseKind.Error, status: status, + headers: headers, + errobj: RestApiError(status: status, message: msg, + contentType: contentType)) + +proc error*(t: typedesc[RestApiResponse], + status: HttpCode = Http200, msg: string = "", + contentType: string = "text/html", + headers: openArray[RestKeyValueTuple]): RestApiResponse = + error(t, status, msg, contentType, HttpTable.init(headers)) proc error*(t: typedesc[RestApiResponse], status: HttpCode = Http200, msg: string = "", contentType: string = "text/html"): RestApiResponse = - RestApiResponse(kind: RestApiResponseKind.Error, status: status, - errobj: RestApiError(status: status, message: msg, - contentType: contentType)) + error(t, status, msg, contentType, HttpTable.init()) proc response*(t: typedesc[RestApiResponse], data: ByteChar, - status: HttpCode = Http200, - contentType = "text/text"): RestApiResponse = + status: HttpCode = Http200, contentType = "text/plain", + headers: HttpTable): RestApiResponse = + ## Create REST API data response with status ``status`` and content specified + ## by type ``contentType`` and data ``data``. You can also specify + ## additional HTTP response headers using ``headers`` argument. + ## + ## Please note that ``contentType`` argument's value has priority over + ## ``Content-Type`` header's value in ``headers`` table. let content = when data is seq[byte]: - ContentBody(contentType: contentType, data: data) + ResponseContentBody(contentType: contentType, data: data) else: block: var default: seq[byte] - ContentBody(contentType: contentType, - data: if len(data) > 0: toBytes(data) else: default) + ResponseContentBody(contentType: contentType, + data: if len(data) > 0: toBytes(data) else: default) + RestApiResponse(kind: RestApiResponseKind.Content, status: status, + headers: headers, content: content) - RestApiResponse(kind: RestApiResponseKind.Content, - status: status, - content: content) +proc response*(t: typedesc[RestApiResponse], data: ByteChar, + status: HttpCode = Http200, contentType = "text/plain", + headers: openArray[RestKeyValueTuple]): RestApiResponse = + response(t, data, status, contentType, HttpTable.init(headers)) + +proc response*(t: typedesc[RestApiResponse], data: ByteChar, + status: HttpCode = Http200, + contentType = "text/plain"): RestApiResponse = + response(t, data, status, contentType, HttpTable.init()) + +proc redirect*(t: typedesc[RestApiResponse], status: HttpCode = Http307, + location: string, preserveQuery = false, + headers: HttpTable): RestApiResponse = + ## Create REST API redirect response with status ``status`` and new location + ## ``location``. + ## + ## You can preserve HTTP query string `uri.query` part using ``preserveQuery`` + ## argument. When ``preserveQuery`` is true new query string will be formed as + ## concatenation of original HTTP request query string and ``location`` query + ## string. + ## + ## You can also specify additional HTTP response headers using ``headers`` + ## argument. + ## + ## Please note that ``location`` argument's value has priority over + ## ``Location`` header's value in ``headers`` table. + RestApiResponse(kind: RestApiResponseKind.Redirect, status: status, + headers: headers, location: location, + preserveQuery: preserveQuery) + +proc redirect*(t: typedesc[RestApiResponse], status: HttpCode = Http307, + location: string, preserveQuery = false, + headers: openArray[RestKeyValueTuple]): RestApiResponse = + redirect(t, status, location, preserveQuery, HttpTable.init(headers)) proc redirect*(t: typedesc[RestApiResponse], status: HttpCode = Http307, location: string, preserveQuery = false): RestApiResponse = - RestApiResponse(kind: RestApiResponseKind.Redirect, status: status, - location: location, preserveQuery: preserveQuery) + redirect(t, status, location, preserveQuery, HttpTable.init()) diff --git a/vendor/nim-presto/presto/route.nim b/vendor/nim-presto/presto/route.nim index 3d1d9509d..2e0e2a717 100644 --- a/vendor/nim-presto/presto/route.nim +++ b/vendor/nim-presto/presto/route.nim @@ -17,10 +17,11 @@ import common, segpath, macrocommon export chronos, options, common, httpcommon, httptable type - RestApiCallback* = proc(request: HttpRequestRef, pathParams: HttpTable, - queryParams: HttpTable, - body: Option[ContentBody]): Future[RestApiResponse] {. - raises: [Defect], gcsafe.} + RestApiCallback* = + proc(request: HttpRequestRef, pathParams: HttpTable, + queryParams: HttpTable, + body: Option[ContentBody]): Future[RestApiResponse] {. + raises: [Defect], gcsafe.} RestRouteKind* {.pure.} = enum None, Handler, Redirect @@ -59,10 +60,12 @@ proc init*(t: typedesc[RestRouter], routes: initBTree[SegmentedPath, RestRouteItem](), allowedOrigin: allowedOrigin) -proc optionsRequestHandler(request: HttpRequestRef, - pathParams: HttpTable, - queryParams: HttpTable, - body: Option[ContentBody]): Future[RestApiResponse] {.async.} = +proc optionsRequestHandler( + request: HttpRequestRef, + pathParams: HttpTable, + queryParams: HttpTable, + body: Option[ContentBody] + ): Future[RestApiResponse] {.async.} = return RestApiResponse.response("", Http200) proc addRoute*(rr: var RestRouter, request: HttpMethod, path: string, @@ -365,10 +368,11 @@ proc processApiCall(router: NimNode, meth: HttpMethod, var res = newStmtList() res.add quote do: proc `doMain`(`requestParam`: HttpRequestRef, `pathParams`: HttpTable, - `queryParams`: HttpTable, `bodyParam`: Option[ContentBody] + `queryParams`: HttpTable, + `bodyParam`: Option[ContentBody] ): Future[RestApiResponse] {.raises: [Defect], async.} = template preferredContentType( - t: varargs[MediaType]): Result[MediaType, cstring] {.used.} = + t: varargs[MediaType]): Result[MediaType, cstring] {.used.} = `requestParam`.preferredContentType(t) `pathDecoder` `optDecoder` diff --git a/vendor/nim-presto/presto/segpath.nim b/vendor/nim-presto/presto/segpath.nim index 971a2024d..1f580bf74 100644 --- a/vendor/nim-presto/presto/segpath.nim +++ b/vendor/nim-presto/presto/segpath.nim @@ -223,7 +223,7 @@ proc init*(st: typedesc[SegmentedPath], request: HttpMethod, $request & "/" & upath SegmentedPath.init(path, patternCb) -proc createPath*(upath: string, values: openarray[KeyValueTuple]): string = +proc createPath*(upath: string, values: openArray[KeyValueTuple]): string = var data: seq[string] var counter = 0 var valuesCount = 0 diff --git a/vendor/nim-presto/presto/servercommon.nim b/vendor/nim-presto/presto/servercommon.nim index 1ba40d53e..955d4b08e 100644 --- a/vendor/nim-presto/presto/servercommon.nim +++ b/vendor/nim-presto/presto/servercommon.nim @@ -20,7 +20,7 @@ chronicles.formatIt(HttpTable): chronicles.formatIt(Option[ContentBody]): if it.isSome(): let body = it.get() - "(" & body.contentType & ", " & $len(body.data) & " bytes)" + "(" & $body.contentType & ", " & $len(body.data) & " bytes)" else: "(None)" diff --git a/vendor/nim-presto/presto/serverprivate.nim b/vendor/nim-presto/presto/serverprivate.nim index a546ad61f..bb7edf14a 100644 --- a/vendor/nim-presto/presto/serverprivate.nim +++ b/vendor/nim-presto/presto/serverprivate.nim @@ -12,20 +12,22 @@ import chronicles import stew/results import route, common, segpath, servercommon -proc getContentBody*(r: HttpRequestRef): Future[Option[ContentBody]] {.async.} = +proc getContentBody*(r: HttpRequestRef): Future[Option[ContentBody]] {. + async.} = if r.meth notin PostMethods: return none[ContentBody]() else: var default: seq[byte] - let cres = getContentType(r.headers.getList("content-type")) - if not(cres.isOk()): - raise newException(RestBadRequestError, "Incorrect Content-Type header") + if r.contentTypeData.isNone(): + raise newException(RestBadRequestError, + "Incorrect/missing Content-Type header") let data = if r.hasBody(): await r.getBody() else: default - let cbody = ContentBody(contentType: cres.get(), data: data) + let cbody = ContentBody(contentType: r.contentTypeData.get(), + data: data) return some[ContentBody](cbody) proc originsMatch(requestOrigin, allowedOrigin: string): bool = @@ -38,6 +40,14 @@ proc originsMatch(requestOrigin, allowedOrigin: string): bool = else: false +proc mergeHttpHeaders(a: var HttpTable, b: HttpTable) = + # Copy headers from table ``b`` to table ``a`` whose keys are not present in + # ``a``. + for key, items in b.items(): + if key notin a: + for item in items: + a.add(key, item) + proc processRestRequest*[T](server: T, rf: RequestFence): Future[HttpResponseRef] {. gcsafe, async.} = @@ -133,6 +143,7 @@ proc processRestRequest*[T](server: T, content_type = restRes.content.contentType, content_size = len(restRes.content.data) + headers.mergeHttpHeaders(restRes.headers) return await request.respond(restRes.status, restRes.content.data, headers) of RestApiResponseKind.Error: @@ -141,8 +152,10 @@ proc processRestRequest*[T](server: T, status = restRes.status.toInt(), meth = $request.meth, peer = $request.remoteAddress(), uri = $request.uri, error - let headers = HttpTable.init([("Content-Type", + var headers = HttpTable.init([("Content-Type", error.contentType)]) + + headers.mergeHttpHeaders(restRes.headers) return await request.respond(error.status, error.message, headers) of RestApiResponseKind.Redirect: @@ -159,7 +172,8 @@ proc processRestRequest*[T](server: T, else: uri.query = uri.query & "&" & request.uri.query $uri - return await request.redirect(restRes.status, location) + return await request.redirect(restRes.status, location, + restRes.headers) else: debug "Response was sent in request handler", meth = $request.meth, peer = $request.remoteAddress(), uri = $request.uri, diff --git a/vendor/nim-presto/tests/config.nims b/vendor/nim-presto/tests/config.nims deleted file mode 100644 index 463650e63..000000000 --- a/vendor/nim-presto/tests/config.nims +++ /dev/null @@ -1,4 +0,0 @@ -switch("threads", "on") -# The compiler doth protest too much, methinks, about all these cases where it can't -# do its (N)RVO pass: https://github.com/nim-lang/RFCs/issues/230 -switch("warning", "ObservableStores:off") diff --git a/vendor/nim-presto/tests/helpers.nim b/vendor/nim-presto/tests/helpers.nim index 66765114e..c0547b045 100644 --- a/vendor/nim-presto/tests/helpers.nim +++ b/vendor/nim-presto/tests/helpers.nim @@ -72,11 +72,11 @@ proc decodeString*(t: typedesc[CustomType1], else: err("Unable to decode value") -proc decodeBytes*(t: typedesc[CustomType1], value: openarray[byte], +proc decodeBytes*(t: typedesc[CustomType1], value: openArray[byte], contentType: string): RestResult[CustomType1] = discard -proc decodeBytes*(t: typedesc[string], value: openarray[byte], +proc decodeBytes*(t: typedesc[string], value: openArray[byte], contentType: string): RestResult[string] = var res: string if len(value) > 0: @@ -84,7 +84,7 @@ proc decodeBytes*(t: typedesc[string], value: openarray[byte], copyMem(addr res[0], unsafeAddr value[0], len(value)) ok(res) -proc decodeBytes*(t: typedesc[int], value: openarray[byte], +proc decodeBytes*(t: typedesc[int], value: openArray[byte], contentType: string): RestResult[int] = if len(value) == 0: err("Could not find any integer") @@ -125,7 +125,7 @@ proc encodeString*(value: int): RestResult[string] = proc encodeString*(value: string): RestResult[string] = ok(value) -proc encodeString*(value: openarray[byte]): RestResult[string] = +proc encodeString*(value: openArray[byte]): RestResult[string] = ok(toHex(value)) proc decodeString*(t: typedesc[int], value: string): RestResult[int] = diff --git a/vendor/nim-presto/tests/nim.cfg b/vendor/nim-presto/tests/nim.cfg new file mode 100644 index 000000000..eb48bba7c --- /dev/null +++ b/vendor/nim-presto/tests/nim.cfg @@ -0,0 +1,10 @@ +--threads:on +# The compiler doth protest too much, methinks, about all these cases where it can't +# do its (N)RVO pass: https://github.com/nim-lang/RFCs/issues/230 +--warning[ObservableStores]:off + +# Avoid some rare stack corruption while using exceptions with a SEH-enabled +# toolchain: https://github.com/status-im/nimbus-eth2/issues/3121 +@if windows and not vcc: + --define:nimRawSetjmp +@end diff --git a/vendor/nim-presto/tests/testclient.nim b/vendor/nim-presto/tests/testclient.nim index 6509f35d2..b72823e7c 100644 --- a/vendor/nim-presto/tests/testclient.nim +++ b/vendor/nim-presto/tests/testclient.nim @@ -24,7 +24,7 @@ suite "REST API client test suite": let obody = if contentBody.isSome(): let body = contentBody.get() - body.contentType & "," & bytesToString(body.data) + $body.contentType & "," & bytesToString(body.data) else: "nobody" return RestApiResponse.response(obody) @@ -52,7 +52,7 @@ suite "REST API client test suite": let obody = if contentBody.isSome(): let body = contentBody.get() - body.contentType & "," & bytesToString(body.data) + $body.contentType & "," & bytesToString(body.data) else: "nobody" return RestApiResponse.response(obody) @@ -89,12 +89,12 @@ suite "REST API client test suite": var client = RestClientRef.new(serverAddress, HttpClientScheme.NonSecure) let res1 = await client.testSimple1() - let res2 = await client.testSimple2("ok-2", restContentType = "text/text") + let res2 = await client.testSimple2("ok-2", restContentType = "text/plain") let res5 = await client.testSimple5() let res6 = await client.testSimple6("ok-6", restContentType = "text/html") check: res1 == "ok-1" - res2 == "text/text,ok-2" + res2 == "text/plain,ok-2" res5 == "ok-5-redirect" res6 == "text/html,ok-6" @@ -117,7 +117,7 @@ suite "REST API client test suite": let (code, message, contentType) = try: let res3 {.used.} = await client.testSimple4("ok-4", - restContentType = "text/text") + restContentType = "text/plain") (0, "", "") except RestResponseError as exc: (exc.status, exc.message, exc.contentType) @@ -135,7 +135,8 @@ suite "REST API client test suite": extraHeaders = @[("Authorization", "Bearer XXX")]) check postRes == "Bearer XXX" - let getRes = await client.testEchoAuthorizationGet(extraHeaders = @[("Authorization", "Bearer XYZ")]) + let getRes = await client.testEchoAuthorizationGet( + extraHeaders = @[("Authorization", "Bearer XYZ")]) check getRes == "Bearer XYZ" await client.closeWait() @@ -160,7 +161,7 @@ suite "REST API client test suite": let obody = if contentBody.isSome(): let body = contentBody.get() - body.contentType & "," & bytesToString(body.data) + $body.contentType & "," & bytesToString(body.data) else: "nobody" return RestApiResponse.response($smp1.get() & ":" & smp2.get() & ":" & @@ -189,7 +190,7 @@ suite "REST API client test suite": let obody = if contentBody.isSome(): let body = contentBody.get() - body.contentType & "," & bytesToString(body.data) + $body.contentType & "," & bytesToString(body.data) else: "nobody" return RestApiResponse.response($smp1.get() & ":" & smp2.get() & ":" & @@ -222,7 +223,7 @@ suite "REST API client test suite": let obody = if contentBody.isSome(): let body = contentBody.get() - body.contentType & "," & bytesToString(body.data) + $body.contentType & "," & bytesToString(body.data) else: "nobody" return RestApiResponse.response("ok-redirect-" & $smp1.get() & ":" & @@ -252,7 +253,7 @@ suite "REST API client test suite": let res1 = await client.testPath1(123456) let res2 = await client.testPath2(234567, "argstr1", "ok-2", - restContentType = "text/text") + restContentType = "text/plain") let res3 = await client.testGetPath3(345678, "argstr2", stringToBytes("876543")) let res4 = await client.testPostPath3(456789, "argstr3", @@ -261,17 +262,17 @@ suite "REST API client test suite": restContentType = "text/html") let res5 = await client.testGetRedirect(567890) let res6 = await client.testPostRedirect(678901, "ok-post-6", - restContentType = "text/text") + restContentType = "text/plain") let res7 = await client.testGetPath3(345678, "запрос", stringToBytes("876543")) check: res1 == "ok:123456" - res2 == "234567:argstr1:text/text,ok-2" + res2 == "234567:argstr1:text/plain,ok-2" res3 == "345678:argstr2:876543" res4 == "456789:argstr3:987654:text/html,ok-post-4" res5 == "ok-redirect-567890" - res6 == "ok-redirect-678901:text/text,ok-post-6" + res6 == "ok-redirect-678901:text/plain,ok-post-6" res7 == "345678:запрос:876543" await client.closeWait() @@ -323,7 +324,7 @@ suite "REST API client test suite": let obody = if contentBody.isSome(): let body = contentBody.get() - body.contentType & "," & bytesToString(body.data) + $body.contentType & "," & bytesToString(body.data) else: "nobody" return RestApiResponse.response("ok-3:" & @@ -346,7 +347,7 @@ suite "REST API client test suite": let obody = if contentBody.isSome(): let body = contentBody.get() - body.contentType & "," & bytesToString(body.data) + $body.contentType & "," & bytesToString(body.data) else: "nobody" return RestApiResponse.response("ok-4:" & @@ -385,12 +386,14 @@ suite "REST API client test suite": return RestApiResponse.response("ok-6:[" & o1 & "]") router.api(MethodPost, "/test/query/7") do ( - q1: Option[int], contentBody: Option[ContentBody]) -> RestApiResponse: + q1: Option[int], + contentBody: Option[ContentBody]) -> RestApiResponse: return RestApiResponse.redirect(location = "/test/query/redirect/7", preserveQuery = true) router.api(MethodPost, "/test/query/redirect/7",) do ( - q1: Option[int], contentBody: Option[ContentBody]) -> RestApiResponse: + q1: Option[int], + contentBody: Option[ContentBody]) -> RestApiResponse: let o1 = if q1.isSome(): let res = q1.get() @@ -402,13 +405,14 @@ suite "REST API client test suite": let obody = if contentBody.isSome(): let body = contentBody.get() - body.contentType & "," & bytesToString(body.data) + $body.contentType & "," & bytesToString(body.data) else: "nobody" return RestApiResponse.response("ok-7:[" & o1 & "]:" & obody) router.api(MethodPost, "/test/query/8") do ( - q1: seq[int], contentBody: Option[ContentBody]) -> RestApiResponse: + q1: seq[int], + contentBody: Option[ContentBody]) -> RestApiResponse: return RestApiResponse.redirect(location = "/test/query/redirect/8", preserveQuery = true) @@ -422,7 +426,7 @@ suite "REST API client test suite": let obody = if contentBody.isSome(): let body = contentBody.get() - body.contentType & "," & bytesToString(body.data) + $body.contentType & "," & bytesToString(body.data) else: "nobody" return RestApiResponse.response("ok-8:[" & o1 & "]:" & obody) @@ -468,35 +472,35 @@ suite "REST API client test suite": let res4 = await client.testQuery2() let res5 = await client.testQuery2(newSeq[int]()) let res6 = await client.testQuery2(@[1,2,3,4,5,6]) - let res7 = await client.testQuery3("body3", restContentType = "text/text") + let res7 = await client.testQuery3("body3", restContentType = "text/plain") let res8 = await client.testQuery3(none[int](), some("запрос"), - "body4", restContentType = "text/text") + "body4", restContentType = "text/plain") let res9 = await client.testQuery3(some(234567), none[string](), - "body5", restContentType = "text/text") + "body5", restContentType = "text/plain") let res10 = await client.testQuery3(some(345678), some("запрос"), - "body6", restContentType = "text/text") + "body6", restContentType = "text/plain") let res11 = await client.testQuery4("body4", - restContentType = "text/text") + restContentType = "text/plain") let res12 = await client.testQuery4(@[1, 2, 3], newSeq[string](), - "body5", restContentType = "text/text") + "body5", restContentType = "text/plain") let res13 = await client.testQuery4(newSeq[int](), @["запрос1", "запрос2", "запрос3"], - "body6", restContentType = "text/text") + "body6", restContentType = "text/plain") let res14 = await client.testQuery4(@[1, 2, 3], @["запрос1", "запрос2", "запрос3"], - "body7", restContentType = "text/text") + "body7", restContentType = "text/plain") let res15 = await client.testQueryGetRedirect(none[int]()) let res16 = await client.testQueryGetRedirect(some(123456)) let res17 = await client.testQueryGetRedirect(newSeq[int]()) let res18 = await client.testQueryGetRedirect(@[11, 22, 33, 44, 55]) let res19 = await client.testQueryPostRedirect(none[int](), - "bodyPost1", restContentType = "text/text") + "bodyPost1", restContentType = "text/plain") let res20 = await client.testQueryPostRedirect(some(123456), - "bodyPost2", restContentType = "text/text") + "bodyPost2", restContentType = "text/plain") let res21 = await client.testQueryPostRedirect(newSeq[int](), - "bodyPost3", restContentType = "text/text") + "bodyPost3", restContentType = "text/plain") let res22 = await client.testQueryPostRedirect(@[11, 22, 33, 44, 55], - "bodyPost4", restContentType = "text/text") + "bodyPost4", restContentType = "text/plain") check: res1 == "ok-1:[]" @@ -505,22 +509,22 @@ suite "REST API client test suite": res4 == "ok-2:[]" res5 == "ok-2:[]" res6 == "ok-2:[1,2,3,4,5,6]" - res7 == "ok-3:[]:[]:text/text,body3" - res8 == "ok-3:[]:[запрос]:text/text,body4" - res9 == "ok-3:[234567]:[]:text/text,body5" - res10 == "ok-3:[345678]:[запрос]:text/text,body6" - res11 == "ok-4:[]:[]:text/text,body4" - res12 == "ok-4:[1,2,3]:[]:text/text,body5" - res13 == "ok-4:[]:[запрос1,запрос2,запрос3]:text/text,body6" - res14 == "ok-4:[1,2,3]:[запрос1,запрос2,запрос3]:text/text,body7" + res7 == "ok-3:[]:[]:text/plain,body3" + res8 == "ok-3:[]:[запрос]:text/plain,body4" + res9 == "ok-3:[234567]:[]:text/plain,body5" + res10 == "ok-3:[345678]:[запрос]:text/plain,body6" + res11 == "ok-4:[]:[]:text/plain,body4" + res12 == "ok-4:[1,2,3]:[]:text/plain,body5" + res13 == "ok-4:[]:[запрос1,запрос2,запрос3]:text/plain,body6" + res14 == "ok-4:[1,2,3]:[запрос1,запрос2,запрос3]:text/plain,body7" res15 == "ok-5:[]" res16 == "ok-5:[123456]" res17 == "ok-6:[]" res18 == "ok-6:[11,22,33,44,55]" - res19 == "ok-7:[]:text/text,bodyPost1" - res20 == "ok-7:[123456]:text/text,bodyPost2" - res21 == "ok-8:[]:text/text,bodyPost3" - res22 == "ok-8:[11,22,33,44,55]:text/text,bodyPost4" + res19 == "ok-7:[]:text/plain,bodyPost1" + res20 == "ok-7:[123456]:text/plain,bodyPost2" + res21 == "ok-8:[]:text/plain,bodyPost3" + res22 == "ok-8:[11,22,33,44,55]:text/plain,bodyPost4" await client1.closeWait() await client2.closeWait() @@ -560,7 +564,7 @@ suite "REST API client test suite": let obody = if contentBody.isSome(): let body = contentBody.get() - body.contentType & "," & bytesToString(body.data) + $body.contentType & "," & bytesToString(body.data) else: "nobody" return RestApiResponse.response("ok-2:" & @@ -628,7 +632,7 @@ suite "REST API client test suite": let obody = if contentBody.isSome(): let body = contentBody.get() - body.contentType & "," & bytesToString(body.data) + $body.contentType & "," & bytesToString(body.data) else: "nobody" return RestApiResponse.response("ok-3:" & @@ -675,7 +679,7 @@ suite "REST API client test suite": let obody = if contentBody.isSome(): let body = contentBody.get() - body.contentType & "," & bytesToString(body.data) + $body.contentType & "," & bytesToString(body.data) else: "nobody" return RestApiResponse.response( @@ -759,30 +763,30 @@ suite "REST API client test suite": let res2 = await client.testFull1(124, newSeq[int]()) let res3 = await client.testFull1(125, @[16, 32, 64, 128, 256, 512, 1024]) let res4 = await client.testFull2(126, "textarg1", "bodydata1", - restContentType = "text/text") + restContentType = "text/plain") let res5 = await client.testFull2(127, "textarg2", newSeq[int](), "bodydata2", - restContentType = "text/text") + restContentType = "text/plain") let res6 = await client.testFull2(128, "textarg3", @[16, 32, 64, 128, 256], "bodydata3", - restContentType = "text/text") + restContentType = "text/plain") let res7 = await client.testFull2(129, "textarg4", newSeq[string](), "bodydata4", - restContentType = "text/text") + restContentType = "text/plain") let res8 = await client.testFull2(130, "textarg5", @["запрос1", "запрос2", "запрос3"], "bodydata5", - restContentType = "text/text") + restContentType = "text/plain") let res9 = await client.testFull2(131, "textarg6", newSeq[int](), newSeq[string](), "bodydata6", - restContentType = "text/text") + restContentType = "text/plain") let res10 = await client.testFull2(132, "textarg7", @[16, 32, 64, 128, 256], @["запрос1", "запрос2", "запрос3"], "bodydata7", - restContentType = "text/text") + restContentType = "text/plain") let res11 = await client.testFull3Get(133, "textarg1", stringToBytes("133")) let res12 = await client.testFull3Get(134, "textarg2", @@ -831,99 +835,99 @@ suite "REST API client test suite": let res24 = await client.testFull3Post(146, "textarg1", stringToBytes("146"), "bodyArg1", - restContentType = "text/text1") + restContentType = "text/plain1") let res25 = await client.testFull3Post(147, "textarg2", stringToBytes("147"), newSeq[int](), "bodyArg2", - restContentType = "text/text2") + restContentType = "text/plain2") let res26 = await client.testFull3Post(148, "textarg3", stringToBytes("148"), @[16, 32, 64, 128, 256], "bodyArg3", - restContentType = "text/text3") + restContentType = "text/plain3") let res27 = await client.testFull3Post(149, "textarg4", stringToBytes("149"), newSeq[string](), "bodyArg4", - restContentType = "text/text4") + restContentType = "text/plain4") let res28 = await client.testFull3Post(150, "textarg5", stringToBytes("150"), @["запрос1", "запрос2", "запрос3"], "bodyArg5", - restContentType = "text/text5") + restContentType = "text/plain5") let res29 = await client.testFull3Post(151, "textarg6", stringToBytes("151"), none[seq[byte]](), "bodyArg6", - restContentType = "text/text6") + restContentType = "text/plain6") let res30 = await client.testFull3Post(152, "textarg7", stringToBytes("152"), some(stringToBytes("byteArg1")), "bodyArg7", - restContentType = "text/text7") + restContentType = "text/plain7") let res31 = await client.testFull3Post(153, "textarg8", stringToBytes("153"), newSeq[int](), none[seq[byte]](), "bodyArg8", - restContentType = "text/text8") + restContentType = "text/plain8") let res32 = await client.testFull3Post(154, "textarg9", stringToBytes("154"), @[16, 32, 64, 128, 256], none[seq[byte]](), "bodyArg9", - restContentType = "text/text9") + restContentType = "text/plain9") let res33 = await client.testFull3Post(155, "textarg10", stringToBytes("155"), newSeq[int](), some(stringToBytes("byteArg2")), "bodyArg10", - restContentType = "text/text10") + restContentType = "text/plain10") let res34 = await client.testFull3Post(156, "textarg11", stringToBytes("156"), @[16, 32, 64, 128, 256], some(stringToBytes("byteArg3")), "bodyArg11", - restContentType = "text/text11") + restContentType = "text/plain11") let res35 = await client.testFull3Post(157, "textarg12", stringToBytes("157"), newSeq[int](), newSeq[string](), none[seq[byte]](), "bodyArg12", - restContentType = "text/text12") + restContentType = "text/plain12") let res36 = await client.testFull3Post(158, "textarg13", stringToBytes("158"), @[16, 32, 64, 128, 256], @["запрос1", "запрос2", "запрос3"], some(stringToBytes("byteArg4")), "bodyArg13", - restContentType = "text/text13") + restContentType = "text/plain13") let res37 = await client.testFull4Redirect(159) let res38 = await client.testFull4Redirect(160, newSeq[int]()) let res39 = await client.testFull4Redirect(161, @[16, 32, 64, 128, 256]) let res40 = await client.testFull5Redirect(162, "bodyArg14", - restContentType = "text/text") + restContentType = "text/plain") let res41 = await client.testFull5Redirect(163, newSeq[int](), "bodyArg15", - restContentType = "text/text") + restContentType = "text/plain") let res42 = await client.testFull5Redirect(164, @[256, 512, 1024, 2048], "bodyArg16", - restContentType = "text/text") + restContentType = "text/plain") check: res1 == "ok-1:123:[]" res2 == "ok-1:124:[]" res3 == "ok-1:125:[16,32,64,128,256,512,1024]" - res4 == "ok-2:126:textarg1:[]:[]:text/text,bodydata1" - res5 == "ok-2:127:textarg2:[]:[]:text/text,bodydata2" - res6 == "ok-2:128:textarg3:[16,32,64,128,256]:[]:text/text,bodydata3" - res7 == "ok-2:129:textarg4:[]:[]:text/text,bodydata4" - res8 == "ok-2:130:textarg5:[]:[запрос1,запрос2,запрос3]:text/text," & + res4 == "ok-2:126:textarg1:[]:[]:text/plain,bodydata1" + res5 == "ok-2:127:textarg2:[]:[]:text/plain,bodydata2" + res6 == "ok-2:128:textarg3:[16,32,64,128,256]:[]:text/plain,bodydata3" + res7 == "ok-2:129:textarg4:[]:[]:text/plain,bodydata4" + res8 == "ok-2:130:textarg5:[]:[запрос1,запрос2,запрос3]:text/plain," & "bodydata5" - res9 == "ok-2:131:textarg6:[]:[]:text/text,bodydata6" + res9 == "ok-2:131:textarg6:[]:[]:text/plain,bodydata6" res10 == "ok-2:132:textarg7:[16,32,64,128,256]:[запрос1,запрос2," & - "запрос3]:text/text,bodydata7" + "запрос3]:text/plain,bodydata7" res11 == "ok-3:133:textarg1:133:[]:[]:[]" res12 == "ok-3:134:textarg2:134:[]:[]:[]" res13 == "ok-3:135:textarg3:135:[16,32,64,128,256]:[]:[]" @@ -938,30 +942,30 @@ suite "REST API client test suite": res22 == "ok-3:144:textarg12:144:[]:[]:[]" res23 == "ok-3:145:textarg13:145:[16,32,64,128,256]:[запрос1,запрос2," & "запрос3]:[byteArg4]" - res24 == "ok-3:146:textarg1:146:[]:[]:[]:text/text1,bodyArg1" - res25 == "ok-3:147:textarg2:147:[]:[]:[]:text/text2,bodyArg2" - res26 == "ok-3:148:textarg3:148:[16,32,64,128,256]:[]:[]:text/text3," & + res24 == "ok-3:146:textarg1:146:[]:[]:[]:text/plain1,bodyArg1" + res25 == "ok-3:147:textarg2:147:[]:[]:[]:text/plain2,bodyArg2" + res26 == "ok-3:148:textarg3:148:[16,32,64,128,256]:[]:[]:text/plain3," & "bodyArg3" - res27 == "ok-3:149:textarg4:149:[]:[]:[]:text/text4,bodyArg4" + res27 == "ok-3:149:textarg4:149:[]:[]:[]:text/plain4,bodyArg4" res28 == "ok-3:150:textarg5:150:[]:[запрос1,запрос2,запрос3]:[]:" & - "text/text5,bodyArg5" - res29 == "ok-3:151:textarg6:151:[]:[]:[]:text/text6,bodyArg6" - res30 == "ok-3:152:textarg7:152:[]:[]:[byteArg1]:text/text7,bodyArg7" - res31 == "ok-3:153:textarg8:153:[]:[]:[]:text/text8,bodyArg8" - res32 == "ok-3:154:textarg9:154:[16,32,64,128,256]:[]:[]:text/text9," & + "text/plain5,bodyArg5" + res29 == "ok-3:151:textarg6:151:[]:[]:[]:text/plain6,bodyArg6" + res30 == "ok-3:152:textarg7:152:[]:[]:[byteArg1]:text/plain7,bodyArg7" + res31 == "ok-3:153:textarg8:153:[]:[]:[]:text/plain8,bodyArg8" + res32 == "ok-3:154:textarg9:154:[16,32,64,128,256]:[]:[]:text/plain9," & "bodyArg9" - res33 == "ok-3:155:textarg10:155:[]:[]:[byteArg2]:text/text10,bodyArg10" + res33 == "ok-3:155:textarg10:155:[]:[]:[byteArg2]:text/plain10,bodyArg10" res34 == "ok-3:156:textarg11:156:[16,32,64,128,256]:[]:[byteArg3]:" & - "text/text11,bodyArg11" - res35 == "ok-3:157:textarg12:157:[]:[]:[]:text/text12,bodyArg12" + "text/plain11,bodyArg11" + res35 == "ok-3:157:textarg12:157:[]:[]:[]:text/plain12,bodyArg12" res36 == "ok-3:158:textarg13:158:[16,32,64,128,256]:[запрос1,запрос2," & - "запрос3]:[byteArg4]:text/text13,bodyArg13" + "запрос3]:[byteArg4]:text/plain13,bodyArg13" res37 == "ok-redirect-159:[]" res38 == "ok-redirect-160:[]" res39 == "ok-redirect-161:[16,32,64,128,256]" - res40 == "ok-redirect-162:[]:text/text,bodyArg14" - res41 == "ok-redirect-163:[]:text/text,bodyArg15" - res42 == "ok-redirect-164:[256,512,1024,2048]:text/text,bodyArg16" + res40 == "ok-redirect-162:[]:text/plain,bodyArg14" + res41 == "ok-redirect-163:[]:text/plain,bodyArg15" + res42 == "ok-redirect-164:[256,512,1024,2048]:text/plain,bodyArg16" await client1.closeWait() await client2.closeWait() @@ -975,7 +979,7 @@ suite "REST API client test suite": router.api(MethodGet, "/test/error/411") do () -> RestApiResponse: return RestApiResponse.error(Http411, "ERROR-411") router.api(MethodGet, "/test/success/200") do () -> RestApiResponse: - return RestApiResponse.response("SUCCESS-200", Http200, "text/text") + return RestApiResponse.response("SUCCESS-200", Http200, "text/plain") router.api(MethodGet, "/test/success/204") do () -> RestApiResponse: return RestApiResponse.response("204", Http204, "text/integer") @@ -1040,7 +1044,7 @@ suite "REST API client test suite": res7.contentType == "text/html" bytesToString(res7.data) == "ERROR-411" res8.status == 200 - res8.contentType == "text/text" + res8.contentType == "text/plain" bytesToString(res8.data) == "SUCCESS-200" res9.status == 204 res9.contentType == "text/integer" @@ -1061,7 +1065,7 @@ suite "REST API client test suite": res12.contentType == "text/html" res12.data == "ERROR-411" res13.status == 200 - res13.contentType == "text/text" + res13.contentType == "text/plain" res13.data == "SUCCESS-200" res14.status == 204 res14.contentType == "text/integer" @@ -1139,7 +1143,7 @@ suite "REST API client test suite": let obody = if contentBody.isSome(): let b = contentBody.get() - b.contentType & "," & bytesToString(b.data) + $b.contentType & "," & bytesToString(b.data) else: "nobody" let preferred = preferredContentType(testMediaType1, testMediaType2) diff --git a/vendor/nim-presto/tests/testroute.nim b/vendor/nim-presto/tests/testroute.nim index bfb772415..33824a1b4 100644 --- a/vendor/nim-presto/tests/testroute.nim +++ b/vendor/nim-presto/tests/testroute.nim @@ -31,8 +31,8 @@ proc sendMockRequest(router: RestRouter, meth: HttpMethod, proc sendMockRequest(router: RestRouter, meth: HttpMethod, url: string, data: string): RestApiResponse = - let contentBody = ContentBody(contentType: "text/text", - data: stringToBytes(data)) + let contentBody = ContentBody.init( + MediaType.init("text/plain"), stringToBytes(data)) sendMockRequest(router, meth, url, some[ContentBody](contentBody)) suite "REST API router & macro tests": @@ -189,7 +189,8 @@ suite "REST API router & macro tests": "/test/custom_args/2/{pat1}/{pat2}/{pat3}") do ( pat1: CustomType1, pat2: CustomType1, pat3: CustomType1, opt1: Option[CustomType1], opt2: Option[CustomType1], - opt3: Option[CustomType1], body: Option[ContentBody]) -> RestApiResponse: + opt3: Option[CustomType1], + body: Option[ContentBody]) -> RestApiResponse: let p1 = pat1.get() let p2 = pat2.get() let p3 = pat3.get() @@ -374,9 +375,10 @@ suite "REST API router & macro tests": test "Unique routes test": var router = RestRouter.init(testValidate) - proc apiCallback(request: HttpRequestRef, pathParams: HttpTable, - queryParams: HttpTable, - body: Option[ContentBody]): Future[RestApiResponse] = + proc apiCallback( + request: HttpRequestRef, pathParams: HttpTable, + queryParams: HttpTable, + body: Option[ContentBody]): Future[RestApiResponse] = discard # Use HTTP method GET diff --git a/vendor/nim-presto/tests/testsecureserver.nim b/vendor/nim-presto/tests/testsecureserver.nim index 0a40a3737..2faabe195 100644 --- a/vendor/nim-presto/tests/testsecureserver.nim +++ b/vendor/nim-presto/tests/testsecureserver.nim @@ -83,7 +83,7 @@ proc httpsClient(server: TransportAddress, meth: HttpMethod, url: string, var transp: StreamTransport - tlsstream: TlsAsyncStream + tlsstream: TLSAsyncStream reader: AsyncStreamReader writer: AsyncStreamWriter @@ -416,7 +416,7 @@ suite "Secure REST API server test suite": let obody = if contentBody.isSome(): let body = contentBody.get() - body.contentType & "," & bytesToString(body.data) + $body.contentType & "," & bytesToString(body.data) else: "nobody" @@ -429,24 +429,24 @@ suite "Secure REST API server test suite": const PostVectors = [ ( - ("/test/1/2/0xaa", "text/text", "textbody"), + ("/test/1/2/0xaa", "text/plain", "textbody"), ClientResponse(status: 200, - data: "1:2:aa:::::::text/text,textbody") + data: "1:2:aa:::::::text/plain,textbody") ), ( ("/test/1/2/0xaa", "", ""), ClientResponse(status: 400) ), ( - ("/test/1/2/0xaa", "text/text", ""), + ("/test/1/2/0xaa", "text/plain", ""), ClientResponse(status: 200, - data: "1:2:aa:::::::text/text,") + data: "1:2:aa:::::::text/plain,") ), ( ("/test/1/2/0xaa?opt1=1&opt2=2&opt3=0xbb&opt4=2&opt4=3&opt4=4&opt5=t&" & - "opt5=e&opt5=s&opt5=t&opt6=0xCA&opt6=0xFE", "text/text", "textbody"), + "opt5=e&opt5=s&opt5=t&opt6=0xCA&opt6=0xFE", "text/plain", "textbody"), ClientResponse(status: 200, data: - "1:2:aa:1:2:bb:2,3,4:t,e,s,t:ca,fe:text/text,textbody") + "1:2:aa:1:2:bb:2,3,4:t,e,s,t:ca,fe:text/plain,textbody") ) ] @@ -503,7 +503,8 @@ suite "Secure REST API server test suite": router.api(MethodPost, "/test/{smp1}") do ( smp1: int, opt1: Option[int], opt4: seq[int], - body: Option[ContentBody], resp: HttpResponseRef) -> RestApiResponse: + body: Option[ContentBody], + resp: HttpResponseRef) -> RestApiResponse: if smp1.isErr(): return RestApiResponse.error(Http411, $smp1.error()) @@ -524,7 +525,7 @@ suite "Secure REST API server test suite": let obody = if body.isSome(): let b = body.get() - b.contentType & "," & bytesToString(b.data) + $b.contentType & "," & bytesToString(b.data) else: "nobody" @@ -547,23 +548,23 @@ suite "Secure REST API server test suite": ( # Empty result with response sent via `resp`. ("/test/1?opt1=2345&opt4=3456&opt4=4567&opt4=5678&opt4=6789", - "text/text", "somebody"), + "text/plain", "somebody"), ClientResponse(status: 200, - data: "1:2345:3456,4567,5678,6789:text/text,somebody") + data: "1:2345:3456,4567,5678,6789:text/plain,somebody") ), ( # Result with response sent via `resp`. ("/test/2?opt1=2345&opt4=3456&opt4=4567&opt4=5678&opt4=6789", - "text/text", "somebody"), + "text/plain", "somebody"), ClientResponse(status: 200, - data: "2:2345:3456,4567,5678,6789:text/text,somebody") + data: "2:2345:3456,4567,5678,6789:text/plain,somebody") ), ( # Error with response sent via `resp`. ("/test/3?opt1=2345&opt4=3456&opt4=4567&opt4=5678&opt4=6789", - "text/text", "somebody"), + "text/plain", "somebody"), ClientResponse(status: 200, - data: "3:2345:3456,4567,5678,6789:text/text,somebody") + data: "3:2345:3456,4567,5678,6789:text/plain,somebody") ) ] diff --git a/vendor/nim-presto/tests/testserver.nim b/vendor/nim-presto/tests/testserver.nim index 17ea42c69..75e7b35b2 100644 --- a/vendor/nim-presto/tests/testserver.nim +++ b/vendor/nim-presto/tests/testserver.nim @@ -1,4 +1,4 @@ -import std/[unittest, strutils] +import std/[unittest, strutils, algorithm] import helpers import chronos, chronos/apps import stew/byteutils @@ -10,6 +10,38 @@ type ClientResponse = object status*: int data*: string + headers*: HttpTable + +proc cmpNoHeaders(a, b: ClientResponse): bool = + (a.status == b.status) and (a.data == b.data) + +proc cmpWithHeaders(a, b: ClientResponse): bool = + if (a.status != b.status) or (a.data != b.data): + return false + for header in b.headers.items(): + if header.key notin a.headers: + return false + let checkItems = a.headers.getList(header.key).sorted() + let expectItems = header.value.sorted() + if checkItems != expectItems: + return false + true + +proc init(t: typedesc[ClientResponse], status: int): ClientResponse = + ClientResponse(status: status) + +proc init(t: typedesc[ClientResponse], status: int, + data: string): ClientResponse = + ClientResponse(status: status, data: data) + +proc init(t: typedesc[ClientResponse], status: int, data: string, + headers: HttpTable): ClientResponse = + ClientResponse(status: status, data: data, headers: headers) + +proc init(t: typedesc[ClientResponse], status: int, data: string, + headers: openArray[tuple[key, value: string]]): ClientResponse = + let table = HttpTable.init(headers) + ClientResponse(status: status, data: data, headers: table) proc httpClient(server: TransportAddress, meth: HttpMethod, url: string, body: string, ctype = "", @@ -34,15 +66,23 @@ proc httpClient(server: TransportAddress, meth: HttpMethod, url: string, headersBuf.setLen(rlen) let resp = parseResponse(headersBuf, true) doAssert(resp.success()) + + let headers = + block: + var res = HttpTable.init() + for key, value in resp.headers(headersBuf): + res.add(key, value) + res + let length = resp.contentLength() doAssert(length >= 0) let cresp = if length > 0: var dataBuf = newString(length) await transp.readExactly(addr dataBuf[0], len(dataBuf)) - ClientResponse(status: resp.code, data: dataBuf) + ClientResponse.init(resp.code, dataBuf, headers) else: - ClientResponse(status: resp.code, data: "") + ClientResponse.init(resp.code, "", headers) await transp.closeWait() return cresp @@ -94,12 +134,12 @@ suite "REST API server test suite": "//////////////////////////////////////////" & "//////////////////////////test", "") check: - res1 == ClientResponse(status: 410) - res2 == ClientResponse(status: 200, data: "ok-1") - res3.status == 505 - res4 == ClientResponse(status: 503) - res5 == ClientResponse(status: 404) - res6 == ClientResponse(status: 400) + cmpNoHeaders(res1, ClientResponse.init(410)) + cmpNoHeaders(res2, ClientResponse.init(200, "ok-1")) + cmpNoHeaders(res3, ClientResponse.init(505, "Some error")) + cmpNoHeaders(res4, ClientResponse.init(503)) + cmpNoHeaders(res5, ClientResponse.init(404)) + cmpNoHeaders(res6, ClientResponse.init(400)) finally: await server.closeWait() @@ -132,35 +172,35 @@ suite "REST API server test suite": toHex(smp3.get())) const TestVectors = [ - ("/test/1234", ClientResponse(status: 200, data: "1234")), - ("/test/12345678", ClientResponse(status: 200, data: "12345678")), - ("/test/00000001", ClientResponse(status: 200, data: "1")), - ("/test/0000000", ClientResponse(status: 200, data: "0")), - ("/test/99999999999999999999999", ClientResponse(status: 411)), - ("/test/nondec", ClientResponse(status: 404)), + ("/test/1234", ClientResponse.init(200, "1234")), + ("/test/12345678", ClientResponse.init(200, "12345678")), + ("/test/00000001", ClientResponse.init(200, "1")), + ("/test/0000000", ClientResponse.init(200, "0")), + ("/test/99999999999999999999999", ClientResponse.init(411)), + ("/test/nondec", ClientResponse.init(404)), - ("/test/1234/text1", ClientResponse(status: 200, data: "1234:text1")), + ("/test/1234/text1", ClientResponse.init(200, "1234:text1")), ("/test/12345678/texttext2", - ClientResponse(status: 200, data: "12345678:texttext2")), + ClientResponse.init(200, "12345678:texttext2")), ("/test/00000001/texttexttext3", - ClientResponse(status: 200, data: "1:texttexttext3")), + ClientResponse.init(200, "1:texttexttext3")), ("/test/0000000/texttexttexttext4", - ClientResponse(status: 200, data: "0:texttexttexttext4")), - ("/test/nondec/texttexttexttexttext5", ClientResponse(status: 404)), + ClientResponse.init(200, "0:texttexttexttext4")), + ("/test/nondec/texttexttexttexttext5", ClientResponse.init(404)), ("/test/99999999999999999999999/texttexttexttexttext5", - ClientResponse(status: 411)), + ClientResponse.init(411)), ("/test/1234/text1/0xCAFE", - ClientResponse(status: 200, data: "1234:text1:cafe")), + ClientResponse.init(200, "1234:text1:cafe")), ("/test/12345678/text2text2/0xdeadbeaf", - ClientResponse(status: 200, data: "12345678:text2text2:deadbeaf")), + ClientResponse.init(200, "12345678:text2text2:deadbeaf")), ("/test/00000001/text3text3text3/0xabcdef012345", - ClientResponse(status: 200, data: "1:text3text3text3:abcdef012345")), + ClientResponse.init(200, "1:text3text3text3:abcdef012345")), ("/test/00000000/text4text4text4text4/0xaa", - ClientResponse(status: 200, data: "0:text4text4text4text4:aa")), - ("/test/nondec/text5/0xbb", ClientResponse(status: 404)), - ("/test/99999999999999999999999/text6/0xcc", ClientResponse(status: 411)), - ("/test/1234/text7/0xxx", ClientResponse(status: 413)) + ClientResponse.init(200, "0:text4text4text4text4:aa")), + ("/test/nondec/text5/0xbb", ClientResponse.init(404)), + ("/test/99999999999999999999999/text6/0xcc", ClientResponse.init(411)), + ("/test/1234/text7/0xxx", ClientResponse.init(413)) ] var sres = RestServerRef.new(router, serverAddress) @@ -243,25 +283,25 @@ suite "REST API server test suite": const TestVectors = [ ("/test/1/2/0xaa?opt1=1&opt2=2&opt3=0xbb&opt4=2&opt4=3&opt4=4&opt5=t&" & "opt5=e&opt5=s&opt5=t&opt6=0xCA&opt6=0xFE", - ClientResponse(status: 200, data: "1:2:aa:1:2:bb:2,3,4:t,e,s,t:ca,fe")), + ClientResponse.init(200, "1:2:aa:1:2:bb:2,3,4:t,e,s,t:ca,fe")), # Optional argument will not pass decoding procedure `opt1=a`. ("/test/1/2/0xaa?opt1=a&opt2=2&opt3=0xbb&opt4=2&opt4=3&opt4=4&opt5=t&" & "opt5=e&opt5=s&opt5=t&opt6=0xCA&opt6=0xFE", - ClientResponse(status: 414)), + ClientResponse.init(414)), # Sequence argument will not pass decoding procedure `opt4=a`. ("/test/1/2/0xaa?opt1=1&opt2=2&opt3=0xbb&opt4=2&opt4=3&opt4=a&opt5=t&" & "opt5=e&opt5=s&opt5=t&opt6=0xCA&opt6=0xFE", - ClientResponse(status: 417)), + ClientResponse.init(417)), # Optional argument will not pass decoding procedure `opt3=0xxx`. ("/test/1/2/0xaa?opt1=1&opt2=2&opt3=0xxx&opt4=2&opt4=3&opt4=4&opt5=t&" & "opt5=e&opt5=s&opt5=t&opt6=0xCA&opt6=0xFE", - ClientResponse(status: 416)), + ClientResponse.init(416)), # Sequence argument will not pass decoding procedure `opt6=0xxx`. ("/test/1/2/0xaa?opt1=1&opt2=2&opt3=0xbb&opt4=2&opt4=3&opt4=5&opt5=t&" & "opt5=e&opt5=s&opt5=t&opt6=0xCA&opt6=0xxx", - ClientResponse(status: 421)), + ClientResponse.init(421)), # All optional arguments are missing - ("/test/1/2/0xaa", ClientResponse(status: 200, data: "1:2:aa::::::")) + ("/test/1/2/0xaa", ClientResponse.init(200, "1:2:aa::::::")) ] var sres = RestServerRef.new(router, serverAddress) @@ -340,7 +380,7 @@ suite "REST API server test suite": let obody = if contentBody.isSome(): let body = contentBody.get() - body.contentType & "," & bytesToString(body.data) + $body.contentType & "," & bytesToString(body.data) else: "nobody" @@ -353,24 +393,22 @@ suite "REST API server test suite": const PostVectors = [ ( - ("/test/1/2/0xaa", "text/text", "textbody"), - ClientResponse(status: 200, - data: "1:2:aa:::::::text/text,textbody") + ("/test/1/2/0xaa", "text/plain", "textbody"), + ClientResponse.init(200, "1:2:aa:::::::text/plain,textbody") ), ( ("/test/1/2/0xaa", "", ""), - ClientResponse(status: 400) + ClientResponse.init(400) ), ( - ("/test/1/2/0xaa", "text/text", ""), - ClientResponse(status: 200, - data: "1:2:aa:::::::text/text,") + ("/test/1/2/0xaa", "text/plain", ""), + ClientResponse.init(200, "1:2:aa:::::::text/plain,") ), ( ("/test/1/2/0xaa?opt1=1&opt2=2&opt3=0xbb&opt4=2&opt4=3&opt4=4&opt5=t&" & - "opt5=e&opt5=s&opt5=t&opt6=0xCA&opt6=0xFE", "text/text", "textbody"), - ClientResponse(status: 200, data: - "1:2:aa:1:2:bb:2,3,4:t,e,s,t:ca,fe:text/text,textbody") + "opt5=e&opt5=s&opt5=t&opt6=0xCA&opt6=0xFE", "text/plain", "textbody"), + ClientResponse.init(200, + "1:2:aa:1:2:bb:2,3,4:t,e,s,t:ca,fe:text/plain,textbody") ) ] @@ -428,7 +466,8 @@ suite "REST API server test suite": router.api(MethodPost, "/test/{smp1}") do ( smp1: int, opt1: Option[int], opt4: seq[int], - body: Option[ContentBody], resp: HttpResponseRef) -> RestApiResponse: + body: Option[ContentBody], + resp: HttpResponseRef) -> RestApiResponse: if smp1.isErr(): return RestApiResponse.error(Http411, $smp1.error()) @@ -449,7 +488,7 @@ suite "REST API server test suite": let obody = if body.isSome(): let b = body.get() - b.contentType & "," & bytesToString(b.data) + $b.contentType & "," & bytesToString(b.data) else: "nobody" @@ -472,23 +511,23 @@ suite "REST API server test suite": ( # Empty result with response sent via `resp`. ("/test/1?opt1=2345&opt4=3456&opt4=4567&opt4=5678&opt4=6789", - "text/text", "somebody"), - ClientResponse(status: 200, - data: "1:2345:3456,4567,5678,6789:text/text,somebody") + "text/plain", "somebody"), + ClientResponse.init(200, + "1:2345:3456,4567,5678,6789:text/plain,somebody") ), ( # Result with response sent via `resp`. ("/test/2?opt1=2345&opt4=3456&opt4=4567&opt4=5678&opt4=6789", - "text/text", "somebody"), - ClientResponse(status: 200, - data: "2:2345:3456,4567,5678,6789:text/text,somebody") + "text/plain", "somebody"), + ClientResponse.init(200, + "2:2345:3456,4567,5678,6789:text/plain,somebody") ), ( # Error with response sent via `resp`. ("/test/3?opt1=2345&opt4=3456&opt4=4567&opt4=5678&opt4=6789", - "text/text", "somebody"), - ClientResponse(status: 200, - data: "3:2345:3456,4567,5678,6789:text/text,somebody") + "text/plain", "somebody"), + ClientResponse.init(200, + "3:2345:3456,4567,5678,6789:text/plain,somebody") ) ] @@ -496,17 +535,17 @@ suite "REST API server test suite": ( # Empty result with response sent via `resp`. "/test/1?opt1=2345&opt4=3456&opt4=4567&opt4=5678&opt4=6789", - ClientResponse(status: 200, data: "1:2345:3456,4567,5678,6789") + ClientResponse.init(200, "1:2345:3456,4567,5678,6789") ), ( # Result with response sent via `resp`. "/test/2?opt1=2345&opt4=3456&opt4=4567&opt4=5678&opt4=6789", - ClientResponse(status: 200, data: "2:2345:3456,4567,5678,6789") + ClientResponse.init(200, "2:2345:3456,4567,5678,6789") ), ( # Error with response sent via `resp`. "/test/3?opt1=2345&opt4=3456&opt4=4567&opt4=5678&opt4=6789", - ClientResponse(status: 200, data: "3:2345:3456,4567,5678,6789") + ClientResponse.init(200, "3:2345:3456,4567,5678,6789") ) ] @@ -531,51 +570,192 @@ suite "REST API server test suite": finally: await server.closeWait() + asyncTest "Responses with headers test": + var router = RestRouter.init(testValidate) + + router.api(MethodGet, "/test/get/success") do ( + param: Option[string]) -> RestApiResponse: + let test = param.get().get() + case test + of "test1": + let headers = [ + ("test-header", "SUCCESS"), ("test-header", "TEST"), + ("test-header", "1") + ] + return RestApiResponse.response("TEST1:OK", Http200, headers = headers) + of "test2": + let headers = HttpTable.init([ + ("test-header", "SUCCESS"), ("test-header", "TEST"), + ("test-header", "2") + ]) + return RestApiResponse.response("TEST2:OK", Http200, headers = headers) + of "test3": + let headers = HttpTable.init([ + ("test-header", "SUCCESS"), ("test-header", "TEST"), + ("test-header", "3"), ("content-type", "application/success") + ]) + return RestApiResponse.response("TEST3:OK", Http200, + contentType = "text/success", + headers = headers) + else: + return RestApiResponse.error(Http400) + + router.api(MethodGet, "/test/get/error") do ( + param: Option[string]) -> RestApiResponse: + let testName = param.get().get() + case testName + of "test1": + let headers = [ + ("test-header", "ERROR"), ("test-header", "TEST"), + ("test-header", "1") + ] + return RestApiResponse.error(Http404, "ERROR1:OK", headers = headers) + of "test2": + let headers = HttpTable.init([ + ("test-header", "ERROR"), ("test-header", "TEST"), + ("test-header", "2") + ]) + return RestApiResponse.error(Http404, "ERROR2:OK", headers = headers) + of "test3": + let headers = HttpTable.init([ + ("test-header", "ERROR"), ("test-header", "TEST"), + ("test-header", "3"), ("content-type", "application/error") + ]) + return RestApiResponse.error(Http404, "ERROR3:OK", + contentType = "text/error", + headers = headers) + else: + return RestApiResponse.error(Http400) + + router.api(MethodGet, "/test/get/redirect") do ( + param: Option[string]) -> RestApiResponse: + let testName = param.get().get() + case testName + of "test1": + let headers = [ + ("test-header", "REDIRECT"), ("test-header", "TEST"), + ("test-header", "1") + ] + return RestApiResponse.redirect(Http307, "/test/get/redirect1", + preserveQuery = true, headers = headers) + of "test2": + let headers = HttpTable.init([ + ("test-header", "REDIRECT"), ("test-header", "TEST"), + ("test-header", "2") + ]) + return RestApiResponse.redirect(Http307, "/test/get/redirect2", + preserveQuery = false, + headers = headers) + of "test3": + let headers = HttpTable.init([ + ("test-header", "REDIRECT"), ("test-header", "TEST"), + ("test-header", "3"), ("location", "/test/get/wrong_redirect") + ]) + return RestApiResponse.redirect(Http307, "/test/get/redirect3", + preserveQuery = true, + headers = headers) + else: + return RestApiResponse.error(Http400) + + const HttpHeadersVectors = [ + ("/test/get/success?param=test1", + ClientResponse.init(200, "TEST1:OK", + [("test-header", "SUCCESS"), ("test-header", "TEST"), + ("test-header", "1")])), + ("/test/get/success?param=test2", + ClientResponse.init(200, "TEST2:OK", + [("test-header", "SUCCESS"), ("test-header", "TEST"), + ("test-header", "2")])), + ("/test/get/success?param=test3", + ClientResponse.init(200, "TEST3:OK", + [("test-header", "SUCCESS"), ("test-header", "TEST"), + ("test-header", "3"), ("content-type", "text/success")])), + + ("/test/get/error?param=test1", + ClientResponse.init(404, "ERROR1:OK", + [("test-header", "ERROR"), ("test-header", "TEST"), + ("test-header", "1")])), + ("/test/get/error?param=test2", + ClientResponse.init(404, "ERROR2:OK", + [("test-header", "ERROR"), ("test-header", "TEST"), + ("test-header", "2")])), + ("/test/get/error?param=test3", + ClientResponse.init(404, "ERROR3:OK", + [("test-header", "ERROR"), ("test-header", "TEST"), + ("test-header", "3"), ("content-type", "text/error")])), + + ("/test/get/redirect?param=test1", + ClientResponse.init(307, "", + [("test-header", "REDIRECT"), ("test-header", "TEST"), + ("test-header", "1"), + ("location", "/test/get/redirect1?param=test1")])), + ("/test/get/redirect?param=test2", + ClientResponse.init(307, "", + [("test-header", "REDIRECT"), ("test-header", "TEST"), + ("test-header", "2"), + ("location", "/test/get/redirect2")])), + ("/test/get/redirect?param=test3", + ClientResponse.init(307, "", + [("test-header", "REDIRECT"), ("test-header", "TEST"), + ("test-header", "3"), + ("location", "/test/get/redirect3?param=test3")])), + ] + var sres = RestServerRef.new(router, serverAddress) + let server = sres.get() + server.start() + try: + for item in HttpHeadersVectors: + let res = await httpClient(serverAddress, MethodGet, item[0], "") + check cmpWithHeaders(res, item[1]) + finally: + await server.closeWait() + asyncTest "preferredContentType() test": const PostVectors = [ ( ("/test/post", "somebody0908", "text/html", "app/type1;q=0.9,app/type2;q=0.8"), - ClientResponse(status: 200, data: "type1[text/html,somebody0908]") + ClientResponse.init(200, "type1[text/html,somebody0908]") ), ( ("/test/post", "somebody0908", "text/html", "app/type2;q=0.8,app/type1;q=0.9"), - ClientResponse(status: 200, data: "type1[text/html,somebody0908]") + ClientResponse.init(200, "type1[text/html,somebody0908]") ), ( ("/test/post", "somebody09", "text/html", "app/type2,app/type1;q=0.9"), - ClientResponse(status: 200, data: "type2[text/html,somebody09]") + ClientResponse.init(200, "type2[text/html,somebody09]") ), ( ("/test/post", "somebody09", "text/html", "app/type1;q=0.9,app/type2"), - ClientResponse(status: 200, data: "type2[text/html,somebody09]") + ClientResponse.init(200, "type2[text/html,somebody09]") ), ( ("/test/post", "somebody", "text/html", "*/*"), - ClientResponse(status: 200, data: "type1[text/html,somebody]") + ClientResponse.init(200, "type1[text/html,somebody]") ), ( ("/test/post", "somebody", "text/html", ""), - ClientResponse(status: 200, data: "type1[text/html,somebody]") + ClientResponse.init(200, "type1[text/html,somebody]") ), ( ("/test/post", "somebody", "text/html", "app/type2"), - ClientResponse(status: 200, data: "type2[text/html,somebody]") + ClientResponse.init(200, "type2[text/html,somebody]") ), ( ("/test/post", "somebody", "text/html", "app/type3"), - ClientResponse(status: 406, data: "") + ClientResponse.init(406, "") ) ] var router = RestRouter.init(testValidate) router.api(MethodPost, "/test/post") do ( - body: Option[ContentBody], resp: HttpResponseRef) -> RestApiResponse: + body: Option[ContentBody], + resp: HttpResponseRef) -> RestApiResponse: let obody = if body.isSome(): let b = body.get() - b.contentType & "," & bytesToString(b.data) + $b.contentType & "," & bytesToString(b.data) else: "nobody" diff --git a/vendor/nim-serialization/.github/workflows/ci.yml b/vendor/nim-serialization/.github/workflows/ci.yml index 578324ac6..04f05ed9c 100644 --- a/vendor/nim-serialization/.github/workflows/ci.yml +++ b/vendor/nim-serialization/.github/workflows/ci.yml @@ -149,10 +149,6 @@ jobs: - name: Run tests run: | - if [[ "${{ matrix.target.os }}" == "windows" ]]; then - # https://github.com/status-im/nimbus-eth2/issues/3121 - export NIMFLAGS="-d:nimRawSetjmp" - fi nim --version nimble --version nimble install -y --depsOnly diff --git a/vendor/nim-serialization/.gitignore b/vendor/nim-serialization/.gitignore index 24e9d9e8f..35e10c22c 100644 --- a/vendor/nim-serialization/.gitignore +++ b/vendor/nim-serialization/.gitignore @@ -1,2 +1,4 @@ nimcache/ tests/test_all +nimble.develop +nimble.paths diff --git a/vendor/nim-serialization/README.md b/vendor/nim-serialization/README.md index d36fb293d..add5c1e73 100644 --- a/vendor/nim-serialization/README.md +++ b/vendor/nim-serialization/README.md @@ -26,21 +26,14 @@ A serialization format is implemented through defining a `Reader` and `Writer` type for the format and then by providing the following type declaration: ```nim -serializationFormat Json, # This is the name of the format. - # Most APIs provided by the library will accept - # this identifier as a required parameter. +serializationFormat Json, # This is the name of the format. + # Most APIs provided by the library will accept + # this identifier as a required parameter. + mimeType = "application/json" # Mime type associated with the format (Optional). - Reader = JsonReader, # The associated Reader type. - Writer = JsonWriter, # The associated Writer type. - - PreferredOutput = string, # APIs such as `Json.encode` will return this type. - # The type must support the following operations: - # proc initWithCapacity(_: type T, n: int) - # proc add(v: var T, bytes: openArray[byte]) - # By default, the PreferredOutput is `seq[byte]`. - - mimeType = "application/json", # Mime type associated with the format (Optional). - fileExt = "json" # File extension associated with the format (Optional). +Json.setReader JsonReader # The associated Reader type. +Json.setWriter JsonWriter, # The associated Writer type. + PreferredOutput = string # APIs such as `Json.encode` will return this type. ``` ## Common API @@ -66,11 +59,11 @@ Decodes and returns a value of the specified `RecordType`. All params will be forwarded without modification to the used `Reader` type. A Format-specific descendant of `SerializationError` may be thrown in case of error. -#### `Format.saveFile(filename: string, params: varargs)` +#### `Format.saveFile(filename: string, value: auto, params: varargs)` Similar to `encode`, but saves the result in a file. -#### `Format.loadFile` +#### `Format.loadFile(filename: string, RecordType: type, params: varargs): RecordType` Similar to `decode`, but treats the contents of a file as an input. @@ -81,53 +74,40 @@ particular reader. #### `writer.writeValue(value: auto)` -Encodes a single value and writes it to the output stream of a paticular writer. +Encodes a single value and writes it to the output stream of a particular writer. ### Custom serialization of user-defined types By default, record types will have all of their fields serialized. You can -alter this behavior by attaching the `dontSerialize(varargs[Format])` pragma -to black-list fields or the `serialize(varargs[Format])` to white-list fields. -If no formats are listed in the pragmas above, they will affect all formats. +alter this behavior by attaching the `dontSerialize` pragma to exclude fields. The pragma `serializedFieldName(name: string)` can be used to modify the name of the field in formats such as Json and XML. Alternatively, if you are not able to modify the definition of a particular -Nim type, you can use the `serializedFields` macro to achive the same in less -instrusive way. +Nim type, you can use the `setSerializedFields` macro to achieve the same +in a less intrusive way. -The following two definitions can be consired equivalent: +The following two definitions can be considered equivalent: ```nim type Foo = object a: string b {.dontSerialize.}: int - c {.dontSerialize(JSON).}: float - d {.serializedFieldName("z").}: int -serializedFields Foo: +setSerializedFields Foo: a - c [-JSON] - # The `d` field is renamed to `z`: - d -> z ``` -As you can see, `serializedFields` accepts a block where each serialzied -field is listed on a separate line. The `->` operator is used to indicate -field renames, while the optional `[]` modifiers can be used to while-list -or black-list specific formats where the field should appear (using `+` -and `-` respectively). +As you can see, `setSerializedFields` accepts a block where each serialized +field is listed on a separate line. #### `customSerialization(RecordType: type, spec)` -#### `Format.customSerialization(RecordType, spec)` -#### `customSerialization(RecordType.field, spec)` -#### `Format.customSerialization(Record.field, spec)` -#### `Record.totalSerializedFields(Format)` +#### `totalSerializedFields(RecordType: type)` Returns the number of serialized fields in the specified format. diff --git a/vendor/nim-serialization/config.nims b/vendor/nim-serialization/config.nims new file mode 100644 index 000000000..7c9db3205 --- /dev/null +++ b/vendor/nim-serialization/config.nims @@ -0,0 +1,4 @@ +# begin Nimble config (version 1) +when fileExists("nimble.paths"): + include "nimble.paths" +# end Nimble config diff --git a/vendor/nim-serialization/nim.cfg b/vendor/nim-serialization/nim.cfg new file mode 100644 index 000000000..371f6d79d --- /dev/null +++ b/vendor/nim-serialization/nim.cfg @@ -0,0 +1,5 @@ +# Avoid some rare stack corruption while using exceptions with a SEH-enabled +# toolchain: https://github.com/status-im/nimbus-eth2/issues/3121 +@if windows and not vcc: + --define:nimRawSetjmp +@end diff --git a/vendor/nim-serialization/nimble.lock b/vendor/nim-serialization/nimble.lock new file mode 100644 index 000000000..30a7817da --- /dev/null +++ b/vendor/nim-serialization/nimble.lock @@ -0,0 +1,91 @@ +{ + "version": 1, + "packages": { + "unittest2": { + "version": "0.0.4", + "vcsRevision": "f180f596c88dfd266f746ed6f8dbebce39c824db", + "url": "https://github.com/status-im/nim-unittest2.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "fa309c41eaf6ef57895b9e603f2620a2f6e11780" + } + }, + "stew": { + "version": "0.1.0", + "vcsRevision": "6ad35b876fb6ebe0dfee0f697af173acc47906ee", + "url": "https://github.com/status-im/nim-stew.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "46d58c4feb457f3241e3347778334e325dce5268" + } + }, + "httputils": { + "version": "0.3.0", + "vcsRevision": "689da19e9e9cfff4ced85e2b25c6b2b5598ed079", + "url": "https://github.com/status-im/nim-http-utils.git", + "downloadMethod": "git", + "dependencies": [ + "stew" + ], + "checksums": { + "sha1": "4ad3ad68d13c50184180ab4b2eacc0bd7ed2ed44" + } + }, + "bearssl": { + "version": "0.1.5", + "vcsRevision": "ba80e2a0d7ae8aab666cee013e38ff8d33a3e5e7", + "url": "https://github.com/status-im/nim-bearssl", + "downloadMethod": "git", + "dependencies": [ + "unittest2" + ], + "checksums": { + "sha1": "383abd5becc77bf8e365b780a29d20529e1d9c4c" + } + }, + "chronos": { + "version": "3.0.11", + "vcsRevision": "17fed89c99beac5a92d3668d0d3e9b0e4ac13936", + "url": "https://github.com/status-im/nim-chronos.git", + "downloadMethod": "git", + "dependencies": [ + "stew", + "bearssl", + "httputils", + "unittest2" + ], + "checksums": { + "sha1": "f6fffc87571e5f76af2a77c4ebcc0e00909ced4e" + } + }, + "testutils": { + "version": "0.4.2", + "vcsRevision": "aa6e5216f4b4ab5aa971cdcdd70e1ec1203cedf2", + "url": "https://github.com/status-im/nim-testutils", + "downloadMethod": "git", + "dependencies": [ + "unittest2" + ], + "checksums": { + "sha1": "94427e0cce0e0c5841edcd3a6530b4e6b857a3cb" + } + }, + "faststreams": { + "version": "0.3.0", + "vcsRevision": "1b561a9e71b6bdad1c1cdff753418906037e9d09", + "url": "https://github.com/status-im/nim-faststreams.git", + "downloadMethod": "git", + "dependencies": [ + "stew", + "testutils", + "chronos", + "unittest2" + ], + "checksums": { + "sha1": "97edf9797924af48566a0af8267203dc21d80c77" + } + } + } +} \ No newline at end of file diff --git a/vendor/nim-serialization/serialization/object_serialization.nim b/vendor/nim-serialization/serialization/object_serialization.nim index d36c2ac01..8b8ece544 100644 --- a/vendor/nim-serialization/serialization/object_serialization.nim +++ b/vendor/nim-serialization/serialization/object_serialization.nim @@ -4,7 +4,7 @@ import type DefaultFlavor* = object - FieldTag*[RecordType; fieldName: static string; FieldType] = distinct void + FieldTag*[RecordType: object; fieldName: static string] = distinct void let # Identifiers affecting the public interface of the library: @@ -31,7 +31,7 @@ template enumInstanceSerializedFields*(obj: auto, ## will refer to the field value. ## ## The order of visited fields matches the order of the fields in - ## the object definition unless `serialziedFields` is used to specify + ## the object definition unless `setSerializedFields` is used to specify ## a different order. Fields marked with the `dontSerialize` pragma ## are skipped. ## @@ -81,7 +81,7 @@ macro enumAllSerializedFieldsImpl(T: type, body: untyped): untyped = ## case object discriminator which make this field accessible. ## ## The order of visited fields matches the order of the fields in - ## the object definition unless `serialziedFields` is used to specify + ## the object definition unless `setSerializedFields` is used to specify ## a different order. Fields marked with the `dontSerialize` pragma ## are skipped. ## @@ -179,18 +179,27 @@ template totalSerializedFields*(T: type): int = macro customSerialization*(field: untyped, definition): untyped = discard +template GetFieldType(FT: type FieldTag): type = + typeof field(declval(FT.RecordType), FT.fieldName) + template readFieldIMPL[Reader](field: type FieldTag, reader: var Reader): untyped = mixin readValue {.gcsafe.}: # needed by Nim-1.6 - reader.readValue(field.FieldType) + reader.readValue GetFieldType(field) + +template readFieldIMPL[Reader](field: type FieldTag, + reader: var Reader): untyped = + mixin readValue + {.gcsafe.}: # needed by Nim-1.6 + reader.readValue GetFieldType(field) template writeFieldIMPL*[Writer](writer: var Writer, fieldTag: type FieldTag, fieldVal: auto, holderObj: auto) = mixin writeValue - writer.writeValue(fieldVal) + writeValue(writer, fieldVal) proc makeFieldReadersTable(RecordType, ReaderType: distinct type): seq[FieldReader[RecordType, ReaderType]] = @@ -201,11 +210,12 @@ proc makeFieldReadersTable(RecordType, ReaderType: distinct type): {.gcsafe, nimcall, raises: [SerializationError, Defect].} = when RecordType is tuple: const i = fieldName.parseInt + try: - type F = FieldTag[RecordType, realFieldName, type(FieldType)] when RecordType is tuple: - obj[i] = readFieldIMPL(F, reader) + reader.readValue obj[i] else: + type F = FieldTag[RecordType, realFieldName] # TODO: The `FieldType` coercion below is required to deal # with a nim bug caused by the distinct `ssz.List` type. # It seems to break the generics cache mechanism, which @@ -215,8 +225,9 @@ proc makeFieldReadersTable(RecordType, ReaderType: distinct type): except SerializationError as err: raise err except CatchableError as err: + type LocalRecordType = `RecordType` # workaround to allow compile time evaluation reader.handleReadException( - `RecordType`, + LocalRecordType, fieldName, when RecordType is tuple: obj[i] else: field(obj, realFieldName), err) @@ -236,6 +247,20 @@ proc fieldReadersTable*(RecordType, ReaderType: distinct type): tbl[] = makeFieldReadersTable(RecordType, ReaderType) return addr(tbl[]) +proc findFieldIdx*(fieldsTable: FieldReadersTable, + fieldName: string, + expectedFieldPos: var int): int = + for i in expectedFieldPos ..< fieldsTable.len: + if fieldsTable[i].fieldName == fieldName: + expectedFieldPos = i + 1 + return i + + for i in 0 ..< expectedFieldPos: + if fieldsTable[i].fieldName == fieldName: + return i + + return -1 + proc findFieldReader*(fieldsTable: FieldReadersTable, fieldName: string, expectedFieldPos: var int): auto = @@ -344,7 +369,7 @@ proc genCustomSerializationForField(Format, field, if readBody != nil: result.add quote do: type ReaderType = Reader(`Format`) - proc readFieldIMPL*(F: type FieldTag[`RecordType`, `fieldName`, auto], + proc readFieldIMPL*(F: type FieldTag[`RecordType`, `fieldName`], `readerSym`: var ReaderType): `FieldType` {.raises: [IOError, SerializationError, Defect].} = `readBody` @@ -353,10 +378,10 @@ proc genCustomSerializationForField(Format, field, result.add quote do: type WriterType = Writer(`Format`) proc writeFieldIMPL*(`writerSym`: var WriterType, - F: type FieldTag[`RecordType`, `fieldName`, auto], + F: type FieldTag[`RecordType`, `fieldName`], `valueSym`: auto, `holderSym`: `RecordType`) - {.raises: [IOError, SerializationError, Defect].} = + {.raises: [IOError, Defect].} = `writeBody` proc genCustomSerializationForType(Format, typ: NimNode, @@ -374,7 +399,7 @@ proc genCustomSerializationForType(Format, typ: NimNode, result.add quote do: type WriterType = Writer(`Format`) proc writeValue*(`writerSym`: var WriterType, `valueSym`: `typ`) - {.raises: [IOError, SerializationError, Defect].} = + {.raises: [IOError, Defect].} = `writeBody` macro useCustomSerialization*(Format: typed, field: untyped, body: untyped): untyped = diff --git a/vendor/nim-serialization/tests/nim.cfg b/vendor/nim-serialization/tests/nim.cfg new file mode 100644 index 000000000..371f6d79d --- /dev/null +++ b/vendor/nim-serialization/tests/nim.cfg @@ -0,0 +1,5 @@ +# Avoid some rare stack corruption while using exceptions with a SEH-enabled +# toolchain: https://github.com/status-im/nimbus-eth2/issues/3121 +@if windows and not vcc: + --define:nimRawSetjmp +@end diff --git a/vendor/nim-stew/.github/workflows/ci.yml b/vendor/nim-stew/.github/workflows/ci.yml index 0172dbced..5bb9ec711 100644 --- a/vendor/nim-stew/.github/workflows/ci.yml +++ b/vendor/nim-stew/.github/workflows/ci.yml @@ -30,7 +30,7 @@ jobs: shell: bash - target: os: macos - builder: macos-10.15 + builder: macos-12 shell: bash - target: os: windows @@ -155,23 +155,25 @@ jobs: fi nim --version nimble --version + nimble install -y --depsOnly env TEST_LANG=c nimble test env TEST_LANG=cpp nimble test - - name: Setup VCC (Windows-i386) - if: runner.os == 'Windows' && matrix.target.cpu == 'i386' - uses: ilammy/msvc-dev-cmd@v1.5.0 - with: - arch: amd64_x86 + # - name: Setup VCC (Windows-i386) + # if: runner.os == 'Windows' && matrix.target.cpu == 'i386' + # uses: ilammy/msvc-dev-cmd@v1.5.0 + # with: + # arch: amd64_x86 - - name: Setup VCC (Windows-amd64) - if: runner.os == 'Windows' && matrix.target.cpu == 'amd64' - uses: ilammy/msvc-dev-cmd@v1.5.0 - with: - arch: x64 + # - name: Setup VCC (Windows-amd64) + # if: runner.os == 'Windows' && matrix.target.cpu == 'amd64' + # uses: ilammy/msvc-dev-cmd@v1.5.0 + # with: + # arch: x64 - - name: Test using VCC - if: runner.os == 'Windows' - run: | - env TEST_LANG=c nimble testvcc - env TEST_LANG=cpp nimble testvcc + # - name: Test using VCC + # if: runner.os == 'Windows' + # run: | + # nimble install -y --depsOnly + # env TEST_LANG=c nimble testvcc + # env TEST_LANG=cpp nimble testvcc diff --git a/vendor/nim-stew/.gitignore b/vendor/nim-stew/.gitignore index ff45144c9..f2e7e9b9a 100644 --- a/vendor/nim-stew/.gitignore +++ b/vendor/nim-stew/.gitignore @@ -1,2 +1,4 @@ nimcache *.exe +nimble.develop +nimble.paths diff --git a/vendor/nim-stew/config.nims b/vendor/nim-stew/config.nims new file mode 100644 index 000000000..325acb1e9 --- /dev/null +++ b/vendor/nim-stew/config.nims @@ -0,0 +1,4 @@ +# begin Nimble config (version 1) +when system.fileExists("nimble.paths"): + include "nimble.paths" +# end Nimble config diff --git a/vendor/nim-stew/nimble.lock b/vendor/nim-stew/nimble.lock new file mode 100644 index 000000000..a05d20dd3 --- /dev/null +++ b/vendor/nim-stew/nimble.lock @@ -0,0 +1,4 @@ +{ + "version": 1, + "packages": {} +} \ No newline at end of file diff --git a/vendor/nim-stew/stew.nimble b/vendor/nim-stew/stew.nimble index d2fdbe226..1651e930f 100644 --- a/vendor/nim-stew/stew.nimble +++ b/vendor/nim-stew/stew.nimble @@ -7,20 +7,49 @@ description = "Backports, standard library candidates and small utilities that license = "Apache License 2.0" skipDirs = @["tests"] -requires "nim >= 1.2.0" +requires "nim >= 1.2.0", + "unittest2" ### Helper functions proc test(args, path: string) = + # nnkArglist was changed to nnkArgList, so can't always use --styleCheck:error + # https://github.com/nim-lang/Nim/pull/17529 + # https://github.com/nim-lang/Nim/pull/19822 + let styleCheckStyle = + if (NimMajor, NimMinor) < (1, 6): + "hint" + else: + "error" + # Compilation language is controlled by TEST_LANG - exec "nim " & getEnv("TEST_LANG", "c") & " " & getEnv("NIMFLAGS") & " " & args & - " -r --hints:off --skipParentCfg --styleCheck:usages --styleCheck:error " & path + exec "nim " & getEnv("TEST_LANG", "c") & " " & getEnv("NIMFLAGS") & + " " & args & + " -r --hints:off --skipParentCfg --styleCheck:usages --styleCheck:" & + styleCheckStyle & " " & path + +proc buildHelper(args, path: string) = + let styleCheckStyle = + if (NimMajor, NimMinor) < (1, 6): + "hint" + else: + "error" + exec "nim " & getEnv("TEST_LANG", "c") & " " & getEnv("NIMFLAGS") & + " " & args & + " --hints:off --skipParentCfg --styleCheck:usages --styleCheck:" & + styleCheckStyle & " " & path task test, "Run all tests": + # Building `test_helper.nim`. + buildHelper("", "tests/test_helper") test "--threads:off", "tests/all_tests" test "--threads:on -d:nimTypeNames", "tests/all_tests" - test "--threads:on -d:noIntrinsicsBitOpts -d:noIntrinsicsEndians", "tests/all_tests" + test "--threads:on -d:noIntrinsicsBitOpts -d:noIntrinsicsEndians", + "tests/all_tests" task testvcc, "Run all tests with vcc compiler": + # Building `test_helper.nim`. + buildHelper("--cc:vcc", "tests/test_helper") test "--cc:vcc --threads:off", "tests/all_tests" test "--cc:vcc --threads:on -d:nimTypeNames", "tests/all_tests" - test "--cc:vcc --threads:on -d:noIntrinsicsBitOpts -d:noIntrinsicsEndians", "tests/all_tests" + test "--cc:vcc --threads:on -d:noIntrinsicsBitOpts -d:noIntrinsicsEndians", + "tests/all_tests" diff --git a/vendor/nim-stew/stew/arrayops.nim b/vendor/nim-stew/stew/arrayops.nim index 0b6b4fb53..3060a1262 100644 --- a/vendor/nim-stew/stew/arrayops.nim +++ b/vendor/nim-stew/stew/arrayops.nim @@ -1,10 +1,13 @@ -# Copyright (c) 2020 Status Research & Development GmbH +# Copyright (c) 2020-2022 Status Research & Development GmbH # Licensed and distributed under either of # * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT). # * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0). # at your option. This file may not be copied, modified, or distributed except according to those terms. -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} ## Operations on array and openArray diff --git a/vendor/nim-stew/stew/assign2.nim b/vendor/nim-stew/stew/assign2.nim index 6ab460db1..cc8ecad0c 100644 --- a/vendor/nim-stew/stew/assign2.nim +++ b/vendor/nim-stew/stew/assign2.nim @@ -2,7 +2,10 @@ import std/typetraits, ./shims/macros -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} func assign*[T](tgt: var seq[T], src: openArray[T]) {.gcsafe.} func assign*[T](tgt: var openArray[T], src: openArray[T]) {.gcsafe.} diff --git a/vendor/nim-stew/stew/base10.nim b/vendor/nim-stew/stew/base10.nim index 02faacfdc..19c2456ea 100644 --- a/vendor/nim-stew/stew/base10.nim +++ b/vendor/nim-stew/stew/base10.nim @@ -1,4 +1,4 @@ -## Copyright (c) 2021 Status Research & Development GmbH +## Copyright (c) 2021-2022 Status Research & Development GmbH ## Licensed under either of ## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) ## * MIT license ([LICENSE-MIT](LICENSE-MIT)) @@ -13,7 +13,10 @@ import results export results -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} type Base10* = object diff --git a/vendor/nim-stew/stew/bitops2.nim b/vendor/nim-stew/stew/bitops2.nim index d1e1133cf..e2523626f 100644 --- a/vendor/nim-stew/stew/bitops2.nim +++ b/vendor/nim-stew/stew/bitops2.nim @@ -443,20 +443,6 @@ template getBitBE*(x: BitIndexable, bit: Natural): bool = ## `getBitLE` is considering the default indexing scheme. (x and mostSignificantBit(x.type) shr bit) != 0 -func changeBit*(x: var BitIndexable, bit: Natural, val: bool) {.inline.} = - ## changes a bit in `x` to val, assuming 0 to be the position of the - ## least significant bit - type T = type(x) - x = (x and not (T(1) shl bit)) or (T(val) shl bit) - -template changeBitLE*(x: var BitIndexable, bit: Natural, val: bool) = - setBit(x, bit, val) - -func changeBitBE*(x: var BitIndexable, bit: Natural, val: bool) {.inline.} = - ## changes a bit in `x` to val, assuming 0 to be the position of the - ## most significant bit - changeBit(x, bitsof(x) - 1 - bit, val) - func setBit*(x: var BitIndexable, bit: Natural) {.inline.} = ## sets bit in `x`, assuming 0 to be the position of the ## least significant bit @@ -473,6 +459,20 @@ func setBitBE*(x: var BitIndexable, bit: Natural) {.inline.} = let mask = mostSignificantBit(x.type) shr bit x = x or mask +func changeBit*(x: var BitIndexable, bit: Natural, val: bool) {.inline.} = + ## changes a bit in `x` to val, assuming 0 to be the position of the + ## least significant bit + type T = type(x) + x = (x and not (T(1) shl bit)) or (T(val) shl bit) + +template changeBitLE*(x: var BitIndexable, bit: Natural, val: bool) = + setBit(x, bit, val) + +func changeBitBE*(x: var BitIndexable, bit: Natural, val: bool) {.inline.} = + ## changes a bit in `x` to val, assuming 0 to be the position of the + ## most significant bit + changeBit(x, bitsof(x) - 1 - bit, val) + func clearBit*(x: var BitIndexable, bit: Natural) {.inline.} = ## clears bit in a byte, assuming 0 to be the position of the ## least significant bit diff --git a/vendor/nim-stew/stew/bitseqs.nim b/vendor/nim-stew/stew/bitseqs.nim index cdbfc3316..0907ee1c5 100644 --- a/vendor/nim-stew/stew/bitseqs.nim +++ b/vendor/nim-stew/stew/bitseqs.nim @@ -1,4 +1,7 @@ -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import bitops2, ptrops diff --git a/vendor/nim-stew/stew/byteutils.nim b/vendor/nim-stew/stew/byteutils.nim index 56b45c045..db97adeb3 100644 --- a/vendor/nim-stew/stew/byteutils.nim +++ b/vendor/nim-stew/stew/byteutils.nim @@ -16,7 +16,10 @@ import # backwards compat export arrayops.`&`, arrayops.initArrayWith, arrayops.`[]=` -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} ######################################################################################################## ##################################### Hex utilities ################################################ @@ -31,14 +34,14 @@ proc readHexChar*(c: char): byte else: raise newException(ValueError, $c & " is not a hexadecimal character") -template skip0xPrefix(hexStr: string): int = +template skip0xPrefix(hexStr: openArray[char]): int = ## Returns the index of the first meaningful char in `hexStr` by skipping ## "0x" prefix if hexStr.len > 1 and hexStr[0] == '0' and hexStr[1] in {'x', 'X'}: 2 else: 0 -func hexToByteArray*(hexStr: string, output: var openArray[byte], fromIdx, toIdx: int) - {.raises: [ValueError, Defect].} = +func hexToByteArrayImpl(hexStr: openArray[char], output: var openArray[byte], fromIdx, toIdx: int): int + {.raises: [ValueError, Defect].} = ## Read a hex string and store it in a byte array `output`. No "endianness" reordering is done. ## Allows specifying the byte range to process into the array var sIdx = skip0xPrefix(hexStr) @@ -53,28 +56,65 @@ func hexToByteArray*(hexStr: string, output: var openArray[byte], fromIdx, toIdx output[bIdx] = hexStr[sIdx].readHexChar shl 4 or hexStr[sIdx + 1].readHexChar inc(sIdx, 2) + sIdx + +func hexToByteArray*(hexStr: string, output: var openArray[byte], fromIdx, toIdx: int) + {.raises: [ValueError, Defect].} = + ## Read a hex string and store it in a byte array `output`. No "endianness" reordering is done. + ## Allows specifying the byte range to process into the array. + ## The hex input may be longer than strictly necessary. + discard hexToByteArrayImpl(hexStr, output, fromIdx, toIdx) + func hexToByteArray*(hexStr: string, output: var openArray[byte]) {.raises: [ValueError, Defect], inline.} = ## Read a hex string and store it in a byte array `output`. No "endianness" reordering is done. + ## The hex input may be longer than strictly necessary. hexToByteArray(hexStr, output, 0, output.high) func hexToByteArray*[N: static[int]](hexStr: string): array[N, byte] {.raises: [ValueError, Defect], noinit, inline.}= ## Read an hex string and store it in a byte array. No "endianness" reordering is done. + ## The hex input may be longer than strictly necessary. hexToByteArray(hexStr, result) func hexToByteArray*(hexStr: string, N: static int): array[N, byte] {.raises: [ValueError, Defect], noinit, inline.}= ## Read an hex string and store it in a byte array. No "endianness" reordering is done. + ## The hex input may be longer than strictly necessary. hexToByteArray(hexStr, result) +func hexToByteArrayStrict*(hexStr: openArray[char], output: var openArray[byte], fromIdx, toIdx: int) + {.raises: [ValueError, Defect].} = + ## Read a hex string and store it in a byte array `output`. No "endianness" reordering is done. + ## Allows specifying the byte range to process into the array. The entire input must be consumed. + if hexToByteArrayImpl(hexStr, output, fromIdx, toIdx) != hexStr.len: + raise (ref ValueError)(msg: "hex string too long") + +func hexToByteArrayStrict*(hexStr: openArray[char], output: var openArray[byte]) + {.raises: [ValueError, Defect], inline.} = + ## Read a hex string and store it in a byte array `output`. No "endianness" reordering is done. + ## The entire input must be consumed. + hexToByteArrayStrict(hexStr, output, 0, output.high) + +func hexToByteArrayStrict*[N: static[int]](hexStr: openArray[char]): array[N, byte] + {.raises: [ValueError, Defect], noinit, inline.}= + ## Read an hex string and store it in a byte array. No "endianness" reordering is done. + ## The entire input must be consumed. + hexToByteArrayStrict(hexStr, result) + +func hexToByteArrayStrict*(hexStr: openArray[char], N: static int): array[N, byte] + {.raises: [ValueError, Defect], noinit, inline.}= + ## Read an hex string and store it in a byte array. No "endianness" reordering is done. + ## The entire input must be consumed. + hexToByteArrayStrict(hexStr, result) + func fromHex*[N](A: type array[N, byte], hexStr: string): A - {.raises: [ValueError, Defect], noinit, inline.}= + {.raises: [ValueError, Defect], noinit, inline.}= ## Read an hex string and store it in a byte array. No "endianness" reordering is done. hexToByteArray(hexStr, result) func hexToPaddedByteArray*[N: static[int]](hexStr: string): array[N, byte] - {.raises: [ValueError, Defect].} = + {.raises: [ValueError, Defect].} = ## Read a hex string and store it in a byte array `output`. ## The string may be shorter than the byte array. ## No "endianness" reordering is done. diff --git a/vendor/nim-stew/stew/interval_set.nim b/vendor/nim-stew/stew/interval_set.nim new file mode 100644 index 000000000..538d073ad --- /dev/null +++ b/vendor/nim-stew/stew/interval_set.nim @@ -0,0 +1,1230 @@ +# Nimbus - Types, data structures and shared utilities used in network sync +# +# Copyright (c) 2018-2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or +# http://www.apache.org/licenses/LICENSE-2.0) +# * MIT license ([LICENSE-MIT](LICENSE-MIT) or +# http://opensource.org/licenses/MIT) +# at your option. This file may not be copied, modified, or +# distributed except according to those terms. + +## Efficient set of non-adjacent disjunct intervals +## ================================================ +## +## This molule efficiently manages a set `Q` of non-adjacent intervals `I` +## over a scalar type `S`. The elements of the intervals are not required to +## be scalar, yet they need to fulfil some ordering properties and must map +## into `S` by the `-` operator. +## +## Application examples +## -------------------- +## * Intervals `I` are sub-ranges of `distinct uint`, scalar `S` is `uint64` +## * Intervals `I` are sub-ranges of `distinct UInt256`, scalar `S` is `Uint256` +## * Intervals `I` art sub-ranges of `uint`, scalar `S` is `uint` +## +## Mathematical heuristic reasoning +## -------------------------------- +## Let `S` be a scalar structure isomorphic to a sub-ring of `Z`, the ring of +## integers. Typical representants would be `uint`, `uint64`, `UInt256` when +## seen as residue classes. `S` need not be bounded. We require `0` and `1` in +## `S`. +## +## Define `P` as a finite set of elements with the following properties: +## +## * There is an order relation defined on `P` (ie. `<`, `=` exists and is +## transitive.) +## +## * Define an interval `I` to be a set of elements of `P` with: +## + If `a`,`b` are in `I`, `w` in `P` with `a<=w<=b`, then `b` is in `I`. +## + We write `[a,b]` for the interval `I` with `a=min(I)` and `b=max(I)`. +## + We have `P=[min(P),max(P)]` (note that `P` is ordered.) +## +## * There is a binary *minus* operation `-:PxP -> S` with the following +## properties: +## + If `a`, `b` are in `P` and `a<=b`, then`b-a=card([a,b])-1`. So +## `a-a=0` for all `a`. +## + For any `a S`, ie. `b-a` is of scalar type `S`. +## * Right addition of scalar: `+:PxS -> P`, ie. `a+n` is a point `b` and +## `b-a` is `n`. +## * The function `$()` must be defined (used for debugging, only) +## +## Additional requirements for the scalar type `S`: +## +## * `S.default` must be the `0` element (of the additive group) +## * `S.default+1` must be the `1` element (of the implied multiplicative +## group) +## * The scalar space `S` must contain all the numbers `0 .. high(P)-low(P)` +## +## User interface considerations +## ----------------------------- +## The data set descriptor is implemented as an object reference. For deep +## copy and deep comparison, the functions `dup()` and `==` are provided. +## +## For any function, the argument points of `P` are assumed be in the +## range `low(P) .. high(P)`. This is not checked explicitely. Using points +## outside this range might have unintended side effects (applicable only +## if `P` is a proper sub-range of a larger data range.) +## +## The data set represents compact intervals `[a,b]` over a point space `P` +## where the length of the largest possible interval is `card(P)` which might +## exceed the highest available scalar `high(S)` from the *NIM* implementation +## of `S`. In order to handle the scalar equivalent of `card(P)`, this package +## always returns the scalar *zero* (from the scalar space `S`) for `card(S)`. +## This makes mathematically sense when `P` is seen as a residue class +## isomorpic to a subclass of `S`. +## + +import + "."/[results, sorted_set] + +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} + +export + `isRed=`, + `linkLeft=`, + `linkRight=`, + results + +const + NoisyDebuggingOk = false + +type + IntervalSetError* = enum + ## Used for debugging only, see `verify()` + isNoError = 0 + isErrorBogusInterval ## Illegal interval end points or zero size + isErrorOverlapping ## Overlapping intervals in database + isErrorAdjacent ## Adjacent intervals, should be joined + isErrorTotalMismatch ## Total accumulator register is wrong + isErrorTotalLastHigh ## Total accumulator mismatch counting `high(P)` + + Interval*[P,S] = object + ## Compact interval `[least,last]` + least, last: P + + IntervalRc*[P,S] = ##\ + ## Handy shortcut, used for interval operation results + Result[Interval[P,S],void] + + IntervalSetRef*[P,S] = ref object + ## Set of non-adjacent intervals + ptsCount: S + ## data size covered + + leftPos: SortedSet[P,BlockRef[S]] + ## list of segments, half-open intervals + + lastHigh: bool + ## `true` iff `high(P)` is in the interval set + + # ----- + + Desc[P,S] = ##\ + ## Internal shortcut, interval set + IntervalSetRef[P,S] + + Segm[P,S] = object + ## Half open interval `[start,start+size)` + start: P ## Start point + size: S ## Length of interval + + BlockRef[S] = ref object + ## Internal, interval set database record reference + size: S + + DataRef[P,S] = ##\ + ## Internal, shortcut: The `value` part of a successful `SortedSet` + ## operation, a reference to the stored data record. + SortedSetItemRef[P,BlockRef[S]] + + Rc[P,S] = ##\ + ## Internal shortcut + Result[DataRef[P,S],void] + +# ------------------------------------------------------------------------------ +# Private debugging +# ------------------------------------------------------------------------------ + +when NoisyDebuggingOk: + import std/[sequtils, strutils] + + # Forward declarations + proc verify*[P,S]( + ds: IntervalSetRef[P,S]): Result[void,(RbInfo,IntervalSetError)] + + proc sayImpl(noisy = false; pfx = "***"; args: varargs[string, `$`]) = + if noisy: + if args.len == 0: + echo "*** ", pfx + elif 0 < pfx.len and pfx[^1] != ' ': + echo pfx, " ", args.toSeq.join + else: + echo pfx, args.toSeq.join + + proc pp[P,S](n: S): string = + let + lowS = S.default + highS = S.default + (high(P) - low(P)) + if highS <= n: + return "high(S)" + if (highS - 1) <= n: + return "high(S)-1" + if (highS - 1 - 1) == n: + return "high(S)-2" + if n <= lowS: + return "low(S)" + if n <= (lowS + 1): + return "low(S)+1" + if n <= (lowS + 1 + 1): + return "low(S)+2" + $n + + proc pp[P,S](pt: P): string = + template one: untyped = (S.default + 1) + if high(P) <= pt: + return "high(P)" + if (high(P) - one) <= pt: + return "high(P)-1" + if (high(P) - one - one) == pt: + return "high(P)-2" + if pt <= low(P): + return "low(P)" + if pt <= (low(P) + one): + return "low(P)+1" + if pt <= (low(P) + one + one): + return "low(P)+2" + $pt + + proc pp[P,S](ds: Desc[P,S]): string = + if ds.isNil: + "nil" + else: + cast[pointer](ds).repr.strip + + proc pp[P,S](seg: Segm[P,S]): string = + template one: untyped = (S.default + 1) + "[" & pp[P,S](seg.start) & "," & pp[P,S](seg.start + seg.size) & ")" + + proc pp[P,S](iv: Interval[P,S]): string = + template one: untyped = (S.default + 1) + "[" & pp[P,S](iv.least) & "," & pp[P,S](iv.last) & "]" + + proc pp[P,S](kvp: DataRef[P,S]): string = + Segm[P,S](start: kvp.key, size: kvp.data.size).pp + + proc pp[P,S](p: var SortedSet[P,BlockRef[S]]): string = + template one: untyped = (S.default + 1) + result = "{" + var rc = p.ge(low(P)) + while rc.isOk: + let (key,blk) = (rc.value.key,rc.value.data) + if 1 < result.len: + result &= "," + result &= "[" & pp[P,S](key) & "," & pp[P,S](key + blk.size) & ")" + rc = p.gt(key) + result &= "}" + + var noisy* = false +else: + var noisy = false + +template say(noisy = false; pfx = "***"; v: varargs[untyped]): untyped = + when NoisyDebuggingOk: + sayImpl(noisy,pfx, v) + discard + +# ------------------------------------------------------------------------------ +# Private helpers +# ------------------------------------------------------------------------------ + +template maxSegmSize(): untyped = + (high(P) - low(P)) + +template scalarZero(): untyped = + ## the value `0` from the scalar data type + (S.default) + +template scalarOne(): untyped = + ## the value `1` from the scalar data type + (S.default + 1) + +proc blk[P,S](kvp: DataRef[P,S]): BlockRef[S] = + kvp.data + +proc left[P,S](kvp: DataRef[P,S]): P = + kvp.key + +proc right[P,S](kvp: DataRef[P,S]): P = + kvp.key + kvp.blk.size + +proc len[P,S](kvp: DataRef[P,S]): S = + kvp.data.size + +# ----- + +proc new[P,S](T: type Segm[P,S]; left, right: P): T = + ## Constructor using `[left,right)` points representation + T(start: left, size: right - left) + +proc brew[P,S](T: type Segm[P,S]; left, right: P): Result[T,void] = + ## Constructor providing `[left, max(left,right)-left)` (if any.) + if high(P) <= left: + return err() + let length = + if right <= left: + scalarOne + elif right < high(P): + (right - left) + scalarOne + else: + (high(P) - left) + ok(T(start: left, size: length)) + +proc left[P,S](iv: Segm[P,S]): P = + iv.start + +proc right[P,S](iv: Segm[P,S]): P = + iv.start + iv.size + +proc len[P,S](iv: Segm[P,S]): S = + iv.size + +# ------ + +proc inc[P,S](a: var P; n: S) = + ## Might not be generally available for point `P` and scalar `S` + a = a + n + +proc maxPt[P](a, b: P): P = + ## Instead of max() which might not be generally available + if a < b: b else: a + +proc minPt[P](a, b: P): P = + ## Instead of min() which might not be generally available + if a < b: a else: b + +# ------ + +proc new[P,S](T: type Interval[P,S]; kvp: DataRef[P,S]): T = + T(least: kvp.left, last: kvp.right - scalarOne) + +# ------------------------------------------------------------------------------ +# Private helpers +# ------------------------------------------------------------------------------ + +proc overlapOrLeftJoin[P,S](ds: Desc[P,S]; l, r: P): Rc[P,S] = + ## Find and return + ## * either the rightmost interval `[a,b)` which overlaps `r` + ## * or `[a,b)` with `b==l` + doAssert l <= r + let rc = ds.leftPos.le(r) # search for `max(a) <= r` + if rc.isOk: + # note that `b` is the first point outside right of `[a,b)` + let b = rc.value.right + if l <= b: + return ok(rc.value) + err() + +proc overlapOrLeftJoin[P,S](ds: Desc[P,S]; iv: Segm[P,S]): Rc[P,S] = + ds.overlapOrLeftJoin(iv.left, iv.right) + + +proc overlap[P,S](ds: Desc[P,S]; l, r: P): Rc[P,S] = + ## Find and return the rightmost `[l,r)` overlapping interval `[a,b)`. + doAssert l < r + let rc = ds.leftPos.lt(r) # search for `max(a) < r` + if rc.isOk: + # note that `b` is the first point outside right of `[a,b)` + let b = rc.value.right + if l < b: + return ok(rc.value) + err() + +proc overlap[P,S](ds: Desc[P,S]; iv: Segm[P,S]): Rc[P,S] = + ds.overlap(iv.left, iv.right) + +# ------------------------------------------------------------------------------ +# Private transfer function helpers +# ------------------------------------------------------------------------------ + +proc findInlet[P,S](ds: Desc[P,S]; iv: Segm[P,S]): Segm[P,S] = + ## Find largest sub-segment of `iv` fully contained in another segment + ## of the argument database. + ## + ## If the `src` argument is `nil`, the argument interval `iv` is returned. + ## If there is no overlapping segment, the empty interval + ##`[iv.start,iv.start)` is returned. + + # Handling edge cases + if ds.isNil: + return iv + + let rc = ds.overlap(iv) + if rc.isErr: + return Segm[P,S].new(iv.left, iv.left) + + let p = rc.value + Segm[P,S].new(maxPt(p.left,iv.left), minPt(p.right,iv.right)) + + +proc merge[P,S](ds: Desc[P,S]; iv: Segm[P,S]): Segm[P,S] = + ## Merges argument interval into into database and returns + ## the segment really added (if any) + + if ds.isNil: + return iv + + let p = block: + let rc = ds.overlapOrLeftJoin(iv) + if rc.isErr: + let rx = ds.leftPos.insert(iv.left) + rx.value.data = BlockRef[S](size: iv.len) + ds.ptsCount += iv.len + return iv + rc.value # `rc.value.data` is a reference to the database record + + doAssert p.blk.size <= ds.ptsCount + + if p.right < iv.right: + # + # iv: ...----------------) + # p: ...-----) + # + let extend = iv.right - p.right + p.blk.size += extend # update database + ds.ptsCount += extend # update database + # + # iv: ...----------------) + # p: ...----------------) + # result: [---------) + # + return Segm[P,S].new(p.right - extend, iv.right) + + # now: iv.right <= p.right and p.left <= iv.left: + if p.left <= iv.left: + # + # iv: [--------) + # p: [-------------------) + # result: o + # + return Segm[P,S].new(iv.left, iv.left) # empty interval + + # now: iv.right <= p.right and iv.left < p.left + if p.left < iv.right: + # + # iv: [-----------------) + # p: [--------------) + # result: [------) + # + result = Segm[P,S].new(iv.left, p.left) + else: + # iv: [------) + # p: [--------------) + # result: [------) + # + result = iv + + # No need for interval `p` anymore. + doAssert p.left == result.right + ds.ptsCount -= p.len + discard ds.leftPos.delete(p.left) + + # Check whether there is an `iv` left overlapping interval `q` that can be + # merged. + # + # Note that the deleted `p` was not fully contained in `iv`. So any overlap + # must be a predecessor. Also, the right end point of the `iv` interval is + # not part of any predecessor because it was adjacent to, or overlapping with + # the deleted interval `p`. + let rc = ds.overlapOrLeftJoin(iv.left, iv.right - scalarOne) + if rc.isOk and iv.left <= rc.value.right: + let q = rc.value + # + # iv: [------... + # p: [------) // deleted + # q: [----) + # result: [------) + # + result = Segm[P,S].new(q.right, result.right) + # + # iv: [------... + # p: [------) // deleted + # q: [----) + # result: [---) + # + # extend `q` to join `result` and `p`, now + let exLen = result.len + p.len + q.blk.size += exLen + ds.ptsCount += exLen + # + # iv: [------... + # p: [------) // deleted + # q: [-----------------) + # result: [----) + # + else: + # So `iv` is fully isolated, i.e. there is no join or overlap. And `iv` + # joins or overlaps the deleted `p` but does not exceed its right end. + # + # iv: [-----------) + # p: [------) // deleted + # result: [----) + # + let s = BlockRef[S](size: p.right - iv.left) + ds.leftPos.insert(iv.left).value.data = s + ds.ptsCount += s.size + # + # iv: [------) + # p: [------) // deleted + # result: [----) + # s: [--------------) + + +proc deleteInlet[P,S](ds: Desc[P,S]; iv: Segm[P,S]) = + ## Delete fully contained interval + if not ds.isNil and 0 < iv.len: + + let + p = ds.overlap(iv).value # `p.blk` is a reference into database + right = p.right # fix the right end for later trailer handling + + # [iv) fully contained in [p) + doAssert p.left <= iv.left and iv.right <= p.right + + if p.left == iv.left: + # + # iv: [--------------) + # p: [---------------... // deleting + # + discard ds.leftPos.delete(p.left) + ds.ptsCount -= p.len + else: + # iv: [-------) + # p: [----------------... + # + let chop = p.right - iv.left # positive as iv.left [pfx) + [fromIv) + pfx = Segm[P,S].new(pfx.left, fromIv.left) + + # Move the `fromIv` interval from `src` to `trg` database + while 0 < fromIv.len: + # Merge sub-interval `[fromIv)` into `trg` database + let toIv = trg.merge(fromIv) + + # Chop right end from [fromIv) -> [fromIv) + [toIv) + fromIv = Segm[P,S].new(fromIv.left, toIv.left) + + # Delete merged sub-interval from `src` database (if any) + src.deleteInlet(toIv) + + result += toIv.len + +# ------------------------------------------------------------------------------ +# Private covered() function implementation +# ------------------------------------------------------------------------------ + +proc coveredImpl[P,S](ds: IntervalSetRef[P,S]; start: P; length: S): S = + ## Calulate the accumulated size of the interval `[start,start+length)` + ## covered by intervals in the set `ds`. The result cannot exceed the + ## argument `length` (of course.) + var iv = Segm[P,S](start: start, size: length) + + while 0 < iv.len: + let rc = ds.overlap(iv) + if rc.isErr: + break + + let p = rc.value + + # Now `p` is the right most interval overlapping `iv` + if p.left <= iv.left: + if p.right <= iv.right: + # + # iv: [----------------) + # p: [-------------) + # overlap: <-------> + # + result.inc p.right - iv.left + else: + # iv: [--------) + # p: [--------------------) + # overlap: <-------> + # + result.inc iv.len + break + else: + if iv.right < p.right: + # + # iv: [--------------) + # p: [--------------) + # overlap: <--------> + # + result.inc iv.right - p.left + else: + # iv: [----------------------) + # p: [----------) + # overlap: <---------> + # + result.inc p.len + + iv.size = p.left - iv.left + # iv: [---) + # p: [----------) + +# ------------------------------------------------------------------------------ +# Public constructor, clone, etc. +# ------------------------------------------------------------------------------ + +proc init*[P,S](T: type IntervalSetRef[P,S]): T = + ## Interval set constructor. + new result + result.leftPos.init() + +proc clone*[P,S](ds: IntervalSetRef[P,S]): IntervalSetRef[P,S] = + ## Return a copy of the interval list. Beware, this might be slow as it + ## needs to copy every interval record. + result = Desc[P,S].init() + result.ptsCount = ds.ptsCount + result.lastHigh = ds.lastHigh + + var # using fast traversal + walk = SortedSetWalkRef[P,BlockRef[S]].init(ds.leftPos) + rc = walk.first + while rc.isOk: + result.leftPos.insert(rc.value.key) + .value.data = BlockRef[S](size: rc.value.data.size) + rc = walk.next + # optional clean up, see comments on the destroy() directive + walk.destroy + +proc `==`*[P,S](a, b: IntervalSetRef[P,S]): bool = + ## Compare interval sets for equality. Beware, this can be slow. Every + ## interval record has to be checked. + if a.ptsCount == b.ptsCount and + a.leftPos.len == b.leftPos.len and + a.lastHigh == b.lastHigh: + result = true + if 0 < a.ptsCount and addr(a.leftPos) != addr(b.leftPos): + var # using fast traversal + aWalk = SortedSetWalkRef[P,BlockRef[S]].init(a.leftPos) + aRc = aWalk.first() + while aRc.isOk: + let bRc = b.leftPos.eq(aRc.value.key) + if bRc.isErr or aRc.value.data.size != bRc.value.data.size: + result = false + break + aRc = aWalk.next() + # optional clean up, see comments on the destroy() directive + aWalk.destroy() + +proc clear*[P,S](ds: IntervalSetRef[P,S]) = + ## Clear the interval set. + ds.ptsCount = scalarZero + ds.lastHigh = false + ds.leftPos.clear() + +proc new*[P,S](T: type Interval[P,S]; minPt, maxPt: P): T = + ## Create interval `[minPt,max(minPt,maxPt)]` + Interval[P,S](least: minPt, last: max(minPt, maxPt)) + +# ------------------------------------------------------------------------------ +# Public interval operations add, remove, erc. +# ------------------------------------------------------------------------------ + +proc merge*[P,S](ds: IntervalSetRef[P,S]; minPt, maxPt: P): S = + ## For the argument interval `I` implied as `[minPt,max(minPt,maxPt)]`, + ## merge `I` with the intervals of the argument set `ds`. The function + ## returns the accumulated number of points that were added to some + ## interval (i.e. which were not contained in any interval of `ds`.) + ## + ## If the argument interval `I` is `[low(P),high(P)]` and is fully merged, + ## the scalar *zero* is returned instead of `high(P)-low(P)+1` (which might + ## not exisit in `S`.). + let rc = Segm[P,S].brew(minPt, maxPt) + if rc.isOk: + result = transferImpl[P,S](src=nil, trg=ds, iv=rc.value) + + if not ds.lastHigh and high(P) <= max(minPt,maxPt): + ds.lastHigh = true + if result < maxSegmSize: + result += scalarOne + else: + result = scalarZero + +proc merge*[P,S](ds: IntervalSetRef[P,S]; iv: Interval[P,S]): S = + ## Variant of `merge()` + ds.merge(iv.least, iv.last) + + +proc reduce*[P,S](ds: IntervalSetRef[P,S]; minPt, maxPt: P): S = + ## For the argument interval `I` implied as `[minPt,max(minPt,maxPt)]`, + ## remove the points from `I` from intervals of the argument set `ds`. + ## The function returns the accumulated number of elements removed (i.e. + ## which were previously contained in some interval of `ds`.) + ## + ## If the argument interval `I` is `[low(P),high(P)]` and is fully removed, + ## the scalar *zero* is returned instead of `high(P)-low(P)+1` (which might + ## not exisit in `S`.). + let rc = Segm[P,S].brew(minPt, maxPt) + if rc.isOk: + result = transferImpl[P,S](src=ds, trg=nil, iv=rc.value) + + if ds.lastHigh and high(P) <= max(minPt,maxPt): + ds.lastHigh = false + if result < maxSegmSize: + result += scalarOne + else: + result = scalarZero + +proc reduce*[P,S](ds: IntervalSetRef[P,S]; iv: Interval[P,S]): S = + ## Variant of `reduce()` + ds.reduce(iv.least, iv.last) + + +proc covered*[P,S](ds: IntervalSetRef[P,S]; minPt, maxPt: P): S = + ## For the argument interval `I` implied as `[minPt,max(minPt,maxPt)]`, + ## calulate the accumulated points `I` contained in some interval in the + ## set `ds`. The return value is the same as that for `reduce()` (only + ## that `ds` is left unchanged, here.) + let rc = Segm[P,S].brew(minPt, maxPt) + if rc.isOk: + result = ds.coveredImpl(rc.value.left, rc.value.size) + + if ds.lastHigh and high(P) <= max(minPt,maxPt): + if result < maxSegmSize: + result += scalarOne + else: + result = scalarZero + +proc covered*[P,S](ds: IntervalSetRef[P,S]; iv: Interval[P,S]): S = + ## Variant of `covered()` + ds.covered(iv.least, iv.last) + + +proc ge*[P,S](ds: IntervalSetRef[P,S]; minPt: P): IntervalRc[P,S] = + ## Find smallest interval in the set `ds` with start point (i.e. minimal + ## value in the interval as a set) greater or equal the argument `minPt`. + let rc = ds.leftPos.ge(minPt) + if rc.isOk: + # Check for fringe case intervals [a,b] + [high(P),high(P)] + if high(P) <= rc.value.right and ds.lastHigh: + return ok(Interval[P,S].new(rc.value.left, high(P))) + return ok(Interval[P,S].new(rc.value)) + if ds.lastHigh: + const preHigh = high(P) - scalarOne + if ds.covered(preHigh,preHigh) == scalarZero: + return ok(Interval[P,S].new(high(P),high(P))) + err() + +proc ge*[P,S](ds: IntervalSetRef[P,S]): IntervalRc[P,S] = + ## Find the interval with the least elements of type `P` (if any.) + ds.ge(low(P)) + +proc le*[P,S](ds: IntervalSetRef[P,S]; maxPt: P): IntervalRc[P,S] = + ## Find largest interval in the set `ds` with end point (i.e. maximal + ## value in the interval as a set) smaller or equal to the argument `maxPt`. + let rc = ds.leftPos.le(maxPt) + if rc.isOk: + # only the left end of segment [left,right) is guaranteed to be <= maxPt + if rc.value.right - scalarOne <= maxPt: + if ds.lastHigh: + if high(P) <= maxPt: + # Check for fringe case intervals [a,b] gap [high(P),high(P)] <= maxPt + if rc.value.right < high(P): + return ok(Interval[P,S].new(high(P),high(P))) + # Check for fringe case intervals [a,b] + [high(P),high(P)] <= maxPt + if high(P) <= rc.value.right: + return ok(Interval[P,S].new(rc.value.left,high(P))) + # So maxPt < high(P) + if high(P) <= rc.value.right: + # Now `maxPt` is fully within the inner part of `[left,high(P)]` + return err() + return ok(Interval[P,S].new(rc.value)) + # find the next smaller one + let xc = ds.leftPos.lt(rc.value.key) + if xc.isOk: + return ok(Interval[P,S].new(xc.value)) + # lone interval + if high(P) <= maxPt and ds.lastHigh: + return ok(Interval[P,S].new(high(P),high(P))) + err() + +proc le*[P,S](ds: IntervalSetRef[P,S]): IntervalRc[P,S] = + ## Find the interval with the largest elements of type `P` (if any.) + ds.le(high(P)) + + +proc envelope*[P,S](ds: IntervalSetRef[P,S]; pt: P): IntervalRc[P,S] = + ## Find the interval that contains the argument point `pt` (if any) + let rc = ds.leftPos.le(pt) + if rc.isOk: + if ds.lastHigh and high(P) <= rc.value.right: + # This interval ranges `[left,high(P)]`, so `pt` is certainly contained + return ok(Interval[P,S].new(rc.value.left,high(P))) + if pt < rc.value.right: + return ok(Interval[P,S].new(rc.value)) + # Otherwise: interval `[left,right)` ends before `pt` + if ds.lastHigh and high(P) <= pt: + return ok(Interval[P,S].new(high(P),high(P))) + err() + + +proc delete*[P,S](ds: IntervalSetRef[P,S]; minPt: P): IntervalRc[P,S] = + ## Find the interval `[minPt,maxPt]` for some point `maxPt` in the interval + ## set `ds` and remove it from `ds`. The function returns the deleted + ## interval (if any.) + block: + let rc = ds.leftPos.delete(minPt) + if rc.isOk: + ds.ptsCount -= rc.value.len + # Check for fringe case intervals [a,b]+[high(P),high(P)] + if high(P) <= rc.value.right and ds.lastHigh: + ds.lastHigh = false + return ok(Interval[P,S].new(rc.value.left,high(P))) + return ok(Interval[P,S].new(rc.value)) + if high(P) <= minPt and ds.lastHigh: + # delete isolated point + let rc = ds.leftPos.lt(minPt) + if rc.isErr or rc.value.right < high(P): + ds.lastHigh = false + return ok(Interval[P,S].new(high(P),high(P))) + err() + + +iterator increasing*[P,S]( + ds: IntervalSetRef[P,S]; + minPt = low(P) + ): Interval[P,S] = + ## Iterate in increasing order through intervals with points greater or + ## equal than the argument point `minPt`. + ## + ## :Note: + ## When running in a loop it is *ok* to delete the current interval and + ## any interval already visited. Intervals not visited yet must not be + ## deleted as the loop would become unpredictable. + var rc = ds.leftPos.ge(minPt) + if rc.isErr: + if ds.lastHigh: + yield Interval[P,S].new(high(P),high(P)) + else: + while rc.isOk: + let key = rc.value.key + if high(P) <= rc.value.right and ds.lastHigh: + yield Interval[P,S].new(rc.value.left,high(P)) + else: + yield Interval[P,S].new(rc.value) + rc = ds.leftPos.gt(key) + +iterator decreasing*[P,S]( + ds: IntervalSetRef[P,S]; + maxPt = high(P) + ): Interval[P,S] = + ## Iterate in decreasing order through intervals with points less or equal + ## than the argument point `maxPt`. + ## + ## See the note at the `increasing()` function comment about deleting items. + var rc = ds.leftPos.le(maxPt) + if rc.isErr: + if ds.lastHigh: + yield Interval[P,S].new(high(P),high(P)) + else: + let key = rc.value.key + # last entry: check for additional point + if high(P) <= rc.value.right and ds.lastHigh: + yield Interval[P,S].new(rc.value.left,high(P)) + else: + yield Interval[P,S].new(rc.value) + # find the next smaller one + rc = ds.leftPos.lt(key) + + while rc.isOk: + let key = rc.value.key + yield Interval[P,S].new(rc.value) + rc = ds.leftPos.lt(key) + +# ------------------------------------------------------------------------------ +# Public interval operators +# ------------------------------------------------------------------------------ + +proc `==`*[P,S](iv, jv: Interval[P,S]): bool = + ## Compare intervals for equality + iv.least == jv.least and iv.last == jv.last + +proc `==`*[P,S](iv: IntervalRc[P,S]; jv: Interval[P,S]): bool = + ## Variant of `==` + if iv.isOk: + return iv.value == jv + +proc `==`*[P,S](iv: Interval[P,S]; jv: IntervalRc[P,S]): bool = + ## Variant of `==` + if jv.isOk: + return iv == jv.value + +proc `==`*[P,S](iv, jv: IntervalRc[P,S]): bool = + ## Variant of `==` + if iv.isOk: + if jv.isOk: + return iv.value == jv.value + # false + else: + return jv.isErr + # false + +# ------ + +proc `*`*[P,S](iv, jv: Interval[P,S]): IntervalRc[P,S] = + ## Intersect itervals `iv` and `jv` if this operation results in a + ## non-emty interval. Note that the `*` operation is associative, i.e. + ## :: + ## iv * jv * kv == (iv * jv) * kv == iv * (jv * kv) + ## + if jv.least <= iv.last and iv.least <= jv.last: + # intervals overlap + return ok(Interval[P,S].new( + maxPt(jv.least,iv.least), minPt(jv.last,iv.last))) + err() + +proc `*`*[P,S](iv: IntervalRc[P,S]; jv: Interval[P,S]): IntervalRc[P,S] = + ## Variant of `*` + if iv.isOk: + return iv.value * jv + err() + +proc `*`*[P,S](iv: Interval[P,S]; jv: IntervalRc[P,S]): IntervalRc[P,S] = + ## Variant of `*` + if jv.isOk: + return iv * jv.value + err() + +proc `*`*[P,S](iv, jv: IntervalRc[P,S]): IntervalRc[P,S] = + ## Variant of `*` + if iv.isOk and jv.isOk: + return iv.value * jv.value + err() + +# ------ + +proc `+`*[P,S](iv, jv: Interval[P,S]): IntervalRc[P,S] = + ## Merge intervals `iv` and `jv` if this operation results in an interval. + ## Note that the `+` operation is *not* associative, i.e. + ## :: + ## iv + jv + kv == (iv + jv) + kv is not necessarly iv + (jv + kv) + ## + if iv.least <= jv.least: + if jv.least - scalarOne <= iv.last: + # + # iv: [--------] + # jv: [...[-----... + # + return ok(Interval[P,S].new(iv.least, maxPt(iv.last,jv.last))) + + else: # jv.least < iv.least + if iv.least - scalarOne <= jv.last: + # + # iv: [...[-----... + # jv: [--------] + # + return ok(Interval[P,S].new(jv.least, maxPt(iv.last,jv.last))) + + err() + +proc `+`*[P,S](iv: IntervalRc[P,S]; jv: Interval[P,S]): IntervalRc[P,S] = + ## Variant of `+` + if iv.isOk: + return iv.value + jv + err() + +proc `+`*[P,S](iv: Interval[P,S]; jv: IntervalRc[P,S]): IntervalRc[P,S] = + ## Variant of `+` + if jv.isOk: + return iv + jv.value + err() + +proc `+`*[P,S](iv, jv: IntervalRc[P,S]): IntervalRc[P,S] = + ## Variant of `+` + if iv.isOk and jv.isOk: + return iv.value + jv.value + err() + +# ------ + +proc `-`*[P,S](iv, jv: Interval[P,S]): IntervalRc[P,S] = + ## Return the interval `iv` reduced by elements of `jv` if this operation + ## results in a non-empty interval. + ## Note that the `-` operation is *not* associative, i.e. + ## :: + ## iv - jv - kv == (iv - jv) - kv is not necessarly iv - (jv - kv) + ## + if iv.least <= jv.least: + if jv.least <= iv.last and iv.last <= jv.last: + # + # iv: [--------------] + # jv: [------------] + # + if iv.least < jv.least: + return ok(Interval[P,S].new(iv.least, jv.least - scalarOne)) + # otherwise empty set => error + + elif iv.last < jv.least: + # + # iv: [--------] + # jv: [------------] + # + return ok(iv) + + else: # so jv.least <= iv.last and jv.last < iv.last + # + # iv: [--------------] + # jv: [------] + # + discard # error + + else: # jv.least < iv.least + if iv.least <= jv.last and jv.last <= iv.last: + # + # iv: [------------] + # jv: [--------------] + # + if jv.last < iv.last: + return ok(Interval[P,S].new(jv.last + scalarOne, iv.last)) + # otherwise empty set => error + + elif jv.last < iv.least: + # + # iv: [------------] + # jv: [--------] + # + return ok(iv) + + else: # so iv.least <= jv.last and iv.last < jv.last + # + # iv: [------] + # jv: [--------------] + # + discard # error + + err() + +proc `-`*[P,S](iv: IntervalRc[P,S]; jv: Interval[P,S]): IntervalRc[P,S] = + ## Variant of `-` + if iv.isOk: + return iv.value - jv + err() + +proc `-`*[P,S](iv: Interval[P,S]; jv: IntervalRc[P,S]): IntervalRc[P,S] = + ## Variant of `-` + if jv.isOk: + return iv - jv.value + err() + +proc `-`*[P,S](iv, jv: IntervalRc[P,S]): IntervalRc[P,S] = + ## Variant of `-` + if iv.isOk and jv.isOk: + return iv.value - jv.valu + err() + +# ------------------------------------------------------------------------------ +# Public getters +# ------------------------------------------------------------------------------ + +proc len*[P,S](iv: Interval[P,S]): S = + ## Cardinality (ie. length) of argument interval `iv`. If the argument + ## interval `iv` is `[low(P),high(P)]`, the return value will be the scalar + ## *zero* (there are no empty intervals in this implementation.) + if low(P) == iv.least and high(P) == iv.last: + scalarZero + else: + (iv.last - iv.least) + scalarOne + +proc minPt*[P,S](iv: Interval[P,S]): P = + ## Left end, smallest point of `P` contained in the interval + iv.least + +proc maxPt*[P,S](iv: Interval[P,S]): P = + ## Right end, largest point of `P` contained in the interval + iv.last + +proc total*[P,S](ds: IntervalSetRef[P,S]): S = + ## Accumulated size covered by intervals in the interval set `ds`. + ## + ## In the special case when there is only the single interval + ## `[low(P),high(P)]` in the interval set, the return value will be the + ## scalar *zero* (there are no empty intervals in this implementation.) + if not ds.lastHigh: + ds.ptsCount + elif maxSegmSize <= ds.ptsCount: + scalarZero + else: + ds.ptsCount + scalarOne + +proc chunks*[P,S](ds: IntervalSetRef[P,S]): int = + ## Number of disjunkt intervals (aka chunks) in the interval set `ds`. + result = ds.leftPos.len + if ds.lastHigh: + # check for isolated interval [high(P),high(P)] + if result == 0 or ds.leftPos.le(high(P)).value.right < high(P): + result.inc + +# ------------------------------------------------------------------------------ +# Public debugging functions +# ------------------------------------------------------------------------------ + +proc `$`*[P,S](p: DataRef[P,S]): string = + ## Needed by `ds.verify()` for printing error messages + "[" & $p.left & "," & $p.right & ")" + +proc verify*[P,S]( + ds: IntervalSetRef[P,S] + ): Result[void,(RbInfo,IntervalSetError)] = + ## Verifyn interval set data structure + try: + let rc = ds.leftPos.verify + if rc.isErr: + return err((rc.error[1],isNoError)) + except CatchableError as e: + raiseAssert $e.name & ": " & e.msg + + block: + var + count = scalarZero + maxPt: P + first = true + for iv in ds.increasing: + noisy.say "***", "verify(fwd)", " maxPt=", maxPt, " iv=", iv.pp + if not(low(P) <= iv.least and iv.least <= iv.last and iv.last <= high(P)): + noisy.say "***", "verify(fwd)", " error=", isErrorBogusInterval + return err((rbOk,isErrorBogusInterval)) + if first: + first = false + elif iv.least <= maxPt: + noisy.say "***", "verify(fwd)", " error=", isErrorOverlapping + return err((rbOk,isErrorOverlapping)) + elif iv.least <= maxPt + scalarOne: + noisy.say "***", "verify(fwd)", " error=", isErrorAdjacent + return err((rbOk,isErrorAdjacent)) + maxPt = iv.last + if iv.least == low(P) and iv.last == high(P): + if ds.lastHigh and 0 < count or not ds.lastHigh and count == 0: + return err((rbOk,isErrorTotalLastHigh)) + count += high(P) - low(P) + elif iv.last == high(P) and ds.lastHigh: + count += (iv.len - 1) + else: + count += iv.len + + if count != ds.ptsCount: + noisy.say "***", "verify(fwd)", + " error=", isErrorTotalMismatch, + " count=", pp[P,S](ds.ptsCount), + " expected=", pp[P,S](count) + return err((rbOk,isErrorTotalMismatch)) + + block: + var + count = scalarZero + minPt: P + last = true + for iv in ds.decreasing: + #noisy.say "***", "verify(rev)", " minPt=", minPt, " iv=", iv.pp + if not(low(P) <= iv.least and iv.least <= iv.last and iv.last <= high(P)): + return err((rbOk,isErrorBogusInterval)) + if last: + last = false + elif minPt <= iv.least: + return err((rbOk,isErrorOverlapping)) + elif minPt + scalarOne <= iv.least: + return err((rbOk,isErrorAdjacent)) + minPt = iv.least + if iv.least == low(P) and iv.last == high(P): + if ds.lastHigh and 0 < count or not ds.lastHigh and count == 0: + return err((rbOk,isErrorTotalLastHigh)) + count += high(P) - low(P) + elif iv.last == high(P) and ds.lastHigh: + count += (iv.len - 1) + else: + count += iv.len + + if count != ds.ptsCount: + noisy.say "***", "verify(rev)", + " error=", isErrorTotalMismatch, + " count=", pp[P,S](ds.ptsCount), + " expected=", pp[P,S](count) + return err((rbOk,isErrorTotalMismatch)) + + ok() + +# ------------------------------------------------------------------------------ +# End +# ------------------------------------------------------------------------------ diff --git a/vendor/nim-stew/stew/io2.nim b/vendor/nim-stew/stew/io2.nim index 8c05528af..d8a760092 100644 --- a/vendor/nim-stew/stew/io2.nim +++ b/vendor/nim-stew/stew/io2.nim @@ -1,4 +1,4 @@ -## Copyright (c) 2020 Status Research & Development GmbH +## Copyright (c) 2020-2022 Status Research & Development GmbH ## Licensed under either of ## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) ## * MIT license ([LICENSE-MIT](LICENSE-MIT)) @@ -10,7 +10,10 @@ ## not use exceptions and using Result[T] for error handling. ## -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} import algorithm import results @@ -30,8 +33,10 @@ when defined(windows): TRUNCATE_EXISTING = 5'u32 FILE_FLAG_OVERLAPPED = 0x40000000'u32 + FILE_SHARE_READ = 0x00000001'u32 + FILE_SHARE_WRITE = 0x00000002'u32 + FILE_FLAG_NO_BUFFERING = 0x20000000'u32 - FILE_SHARE_READ = 1'u32 FILE_ATTRIBUTE_READONLY = 0x00000001'u32 FILE_ATTRIBUTE_DIRECTORY = 0x00000010'u32 @@ -97,6 +102,13 @@ when defined(windows): changeTime: uint64 fileAttributes: uint32 + OVERLAPPED* {.pure, inheritable.} = object + internal*: uint + internalHigh*: uint + offset*: uint32 + offsetHigh*: uint32 + hEvent*: IoHandle + proc getLastError(): uint32 {. importc: "GetLastError", stdcall, dynlib: "kernel32", sideEffect.} proc createDirectoryW(pathName: WideCString, @@ -137,35 +149,49 @@ when defined(windows): arguments: pointer): uint32 {. importc: "FormatMessageW", stdcall, dynlib: "kernel32".} proc localFree(p: pointer): uint {. - importc: "LocalFree", stdcall, dynlib: "kernel32".} + importc: "LocalFree", stdcall, dynlib: "kernel32", sideEffect.} proc getLongPathNameW(lpszShortPath: WideCString, lpszLongPath: WideCString, cchBuffer: uint32): uint32 {. - importc: "GetLongPathNameW", dynlib: "kernel32.dll", stdcall.} + importc: "GetLongPathNameW", dynlib: "kernel32.dll", stdcall, + sideEffect.} proc findFirstFileW(lpFileName: WideCString, lpFindFileData: var WIN32_FIND_DATAW): uint {. - importc: "FindFirstFileW", dynlib: "kernel32", stdcall.} + importc: "FindFirstFileW", dynlib: "kernel32", stdcall, sideEffect.} proc findClose(hFindFile: uint): int32 {. - importc: "FindClose", dynlib: "kernel32", stdcall.} + importc: "FindClose", dynlib: "kernel32", stdcall, sideEffect.} proc getFileInformationByHandle(hFile: uint, info: var BY_HANDLE_FILE_INFORMATION): int32 {. - importc: "GetFileInformationByHandle", dynlib: "kernel32", stdcall.} + importc: "GetFileInformationByHandle", dynlib: "kernel32", stdcall, + sideEffect.} proc getFileInformationByHandleEx(hFile: uint, information: uint32, lpFileInformation: pointer, dwBufferSize: uint32): int32 {. - importc: "GetFileInformationByHandleEx", dynlib: "kernel32", stdcall.} + importc: "GetFileInformationByHandleEx", dynlib: "kernel32", stdcall, + sideEffect.} proc setFileInformationByHandle(hFile: uint, information: uint32, lpFileInformation: pointer, dwBufferSize: uint32): int32 {. - importc: "SetFileInformationByHandle", dynlib: "kernel32", stdcall.} + importc: "SetFileInformationByHandle", dynlib: "kernel32", stdcall, + sideEffect.} proc getFileSize(hFile: uint, lpFileSizeHigh: var uint32): uint32 {. - importc: "GetFileSize", dynlib: "kernel32", stdcall.} + importc: "GetFileSize", dynlib: "kernel32", stdcall, sideEffect.} proc setFilePointerEx(hFile: uint, liDistanceToMove: int64, lpNewFilePointer: ptr int64, dwMoveMethod: uint32): int32 {. - importc: "SetFilePointerEx", dynlib: "kernel32", stdcall.} + importc: "SetFilePointerEx", dynlib: "kernel32", stdcall, sideEffect.} + proc lockFileEx(hFile: uint, dwFlags, dwReserved: uint32, + nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh: uint32, + lpOverlapped: pointer): uint32 {. + importc: "LockFileEx", dynlib: "kernel32", stdcall, sideEffect.} + proc unlockFileEx(hFile: uint, dwReserved: uint32, + nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh: uint32, + lpOverlapped: pointer): uint32 {. + importc: "UnlockFileEx", dynlib: "kernel32", stdcall, sideEffect.} const NO_ERROR = IoErrorCode(0) + LOCKFILE_EXCLUSIVE_LOCK = 0x00000002'u32 + LOCKFILE_FAIL_IMMEDIATELY = 0x00000001'u32 proc `==`*(a: IoErrorCode, b: uint32): bool {.inline.} = (uint32(a) == b) @@ -178,6 +204,11 @@ elif defined(posix): AltSep* = '/' BothSeps* = {'/'} + LOCK_SH* = 0x01 + LOCK_EX* = 0x02 + LOCK_NB* = 0x04 + LOCK_UN* = 0x08 + type IoHandle* = distinct cint IoErrorCode* = distinct cint @@ -206,18 +237,28 @@ elif defined(posix): O_CLOEXEC = cint(0x1000000) F_NOCACHE = cint(48) + type + FlockStruct* {.importc: "struct flock", final, pure, + header: "".} = object + ltype* {.importc: "l_type".}: cshort + lwhence* {.importc: "l_whence".}: cshort + start* {.importc: "l_start".}: int + length* {.importc: "l_len".}: int + pid* {.importc: "l_pid".}: int32 + var errno {.importc, header: "".}: cint proc write(a1: cint, a2: pointer, a3: csize_t): int {. - importc, header: "".} + importc, header: "", sideEffect.} proc read(a1: cint, a2: pointer, a3: csize_t): int {. - importc, header: "".} + importc, header: "", sideEffect.} proc c_strerror(errnum: cint): cstring {. - importc: "strerror", header: "".} + importc: "strerror", header: "", sideEffect.} proc c_free(p: pointer) {. - importc: "free", header: "".} + importc: "free", header: "", sideEffect.} proc getcwd(a1: cstring, a2: int): cstring {. importc, header: "", sideEffect.} + proc `==`*(a: IoErrorCode, b: cint): bool {.inline.} = (cint(a) == b) @@ -226,7 +267,7 @@ type OpenFlags* {.pure.} = enum Read, Write, Create, Exclusive, Append, Truncate, - Inherit, NonBlock, Direct + Inherit, NonBlock, Direct, ShareRead, ShareWrite Permission* = enum UserRead, UserWrite, UserExec, @@ -241,6 +282,14 @@ type AccessFlags* {.pure.} = enum Find, Read, Write, Execute + LockType* {.pure.} = enum + Shared, Exclusive + + IoLockHandle* = object + handle*: IoHandle + offset*: int64 + size*: int64 + const NimErrorCode = 100_000 UnsupportedFileSize* = IoErrorCode(NimErrorCode) @@ -1007,6 +1056,11 @@ proc openFile*(pathName: string, flags: set[OpenFlags], ((dwAccess and (GENERIC_READ or GENERIC_WRITE)) == GENERIC_READ): dwShareMode = dwShareMode or FILE_SHARE_READ + if OpenFlags.ShareRead in flags: + dwShareMode = dwShareMode or FILE_SHARE_READ + if OpenFlags.ShareWrite in flags: + dwShareMode = dwShareMode or FILE_SHARE_WRITE + if OpenFlags.NonBlock in flags: dwFlags = dwFlags or FILE_FLAG_OVERLAPPED if OpenFlags.Direct in flags: @@ -1145,6 +1199,8 @@ proc writeFile*(pathName: string, data: openArray[byte], when defined(windows): template makeInt64(a, b: uint32): int64 = (int64(a and 0x7FFF_FFFF'u32) shl 32) or int64(b and 0xFFFF_FFFF'u32) + template makeUint32(a: uint64): tuple[lowPart: uint32, highPart: uint32] = + (uint32(a and 0xFFFF_FFFF'u64), uint32((a shr 32) and 0xFFFF_FFFF'u64)) proc writeFile*(pathName: string, data: openArray[char], createMode: int = 0o644, @@ -1312,3 +1368,160 @@ proc readAllChars*(pathName: string): IoResult[string] = proc readAllFile*(pathName: string): IoResult[seq[byte]] = ## Alias for ``readAllBytes()``. readAllBytes(pathName) + +proc lockFile*(handle: IoHandle, kind: LockType, offset, + size: int64): IoResult[void] = + ## Apply shared or exclusive file segment lock for file handle ``handle`` and + ## range specified by ``offset`` and ``size`` parameters. + ## + ## ``kind`` - type of lock (shared or exclusive). Please note that only + ## exclusive locks have cross-platform compatible behavior. Hovewer, exclusive + ## locks require ``handle`` to be opened for writing. + ## + ## ``offset`` - starting byte offset in the file where the lock should + ## begin. ``offset`` should be always bigger or equal to ``0``. + ## + ## ``size`` - length of the byte range to be locked. ``size`` should be always + ## bigger or equal to ``0``. + ## + ## If ``offset`` and ``size`` are both equal to ``0`` the entire file is locked. + doAssert(offset >= 0) + doAssert(size >= 0) + when defined(posix): + let ltype = + case kind + of LockType.Shared: + cshort(posix.F_RDLCK) + of LockType.Exclusive: + cshort(posix.F_WRLCK) + var flockObj = + when sizeof(int) == 8: + # There is no need to perform overflow check, so we just cast. + FlockStruct(ltype: ltype, lwhence: cshort(posix.SEEK_SET), + start: cast[int](offset), length: cast[int](size)) + else: + # Currently we do not support `__USE_FILE_OFFSET64` or + # `__USE_LARGEFILE64` because its Linux specific #defines, and is not + # present on BSD systems. Therefore, on 32bit systems we do not support + # range locks which exceed `int32` value size. + if offset > int64(high(int)): + return err(IoErrorCode(EFBIG)) + if size > int64(high(int)): + return err(IoErrorCode(EFBIG)) + # We already made overflow check, so we just cast. + FlockStruct(ltype: ltype, lwhence: cshort(posix.SEEK_SET), + start: cast[int](offset), length: cast[int](size)) + while true: + let res = posix.fcntl(cint(handle), posix.F_SETLK, addr flockObj) + if res == -1: + let errCode = ioLastError() + if errCode == EINTR: + continue + else: + return err(errCode) + else: + return ok() + elif defined(windows): + let (lowOffsetPart, highOffsetPart, lowSizePart, highSizePart) = + if offset == 0'i64 and size == 0'i64: + # We try to keep cross-platform behavior on Windows. And we can do it + # because: Locking a region that goes beyond the current end-of-file + # position is not an error. + (0'u32, 0'u32, 0xFFFF_FFFF'u32, 0xFFFF_FFFF'u32) + else: + let offsetTuple = makeUint32(uint64(offset)) + let sizeTuple = makeUint32(uint64(size)) + (offsetTuple[0], offsetTuple[1], sizeTuple[0], sizeTuple[1]) + var ovl = OVERLAPPED(offset: lowOffsetPart, offsetHigh: highOffsetPart) + let + flags = + case kind + of LockType.Shared: + LOCKFILE_FAIL_IMMEDIATELY + of LockType.Exclusive: + LOCKFILE_FAIL_IMMEDIATELY or LOCKFILE_EXCLUSIVE_LOCK + res = lockFileEx(uint(handle), flags, 0'u32, lowSizePart, + highSizePart, addr ovl) + if res == 0: + err(ioLastError()) + else: + ok() + +proc unlockFile*(handle: IoHandle, offset, size: int64): IoResult[void] = + ## Clear shared or exclusive file segment lock for file handle ``handle`` and + ## range specified by ``offset`` and ``size`` parameters. + ## + ## ``offset`` - starting byte offset in the file where the lock placed. + ## ``offset`` should be always bigger or equal to ``0``. + ## + ## ``size`` - length of the byte range to be unlocked. ``size`` should be + ## always bigger or equal to ``0``. + doAssert(offset >= 0) + doAssert(size >= 0) + when defined(posix): + let ltype = cshort(posix.F_UNLCK) + var flockObj = + when sizeof(int) == 8: + # There is no need to perform overflow check, so we just cast. + FlockStruct(ltype: ltype, lwhence: cshort(posix.SEEK_SET), + start: cast[int](offset), length: cast[int](size)) + else: + # Currently we do not support `__USE_FILE_OFFSET64` because its + # Linux specific #define, and it not present in BSD systems. So + # on 32bit systems we do not support range locks which exceed `int32` + # value size. + if offset > int64(high(int)): + return err(IoErrorCode(EFBIG)) + if size > int64(high(int)): + return err(IoErrorCode(EFBIG)) + # We already made overflow check, so we just cast. + FlockStruct(ltype: ltype, lwhence: cshort(posix.SEEK_SET), + start: cast[int](offset), length: cast[int](size)) + while true: + let res = posix.fcntl(cint(handle), F_SETLK, addr flockObj) + if res == -1: + let errCode = ioLastError() + if errCode == EINTR: + continue + else: + return err(errCode) + else: + return ok() + elif defined(windows): + let (lowOffsetPart, highOffsetPart, lowSizePart, highSizePart) = + if offset == 0'i64 and size == 0'i64: + # We try to keep cross-platform behavior on Windows. And we can do it + # because: Locking a region that goes beyond the current end-of-file + # position is not an error. + (0'u32, 0'u32, 0xFFFF_FFFF'u32, 0xFFFF_FFFF'u32) + else: + let offsetTuple = makeUint32(uint64(offset)) + let sizeTuple = makeUint32(uint64(size)) + (offsetTuple[0], offsetTuple[1], sizeTuple[0], sizeTuple[1]) + var ovl = OVERLAPPED(offset: lowOffsetPart, offsetHigh: highOffsetPart) + let res = unlockFileEx(uint(handle), 0'u32, lowSizePart, + highSizePart, addr ovl) + if res == 0: + err(ioLastError()) + else: + ok() + +proc lockFile*(handle: IoHandle, kind: LockType): IoResult[IoLockHandle] = + ## Apply exclusive or shared lock to whole file specified by file handle + ## ``handle``. + ## + ## ``kind`` - type of lock (shared or exclusive). Please note that only + ## exclusive locks have cross-platform compatible behavior. Hovewer, exclusive + ## locks require ``handle`` to be opened for writing. + ## + ## On success returns ``IoLockHandle`` object which could be used for unlock. + ? lockFile(handle, kind, 0'i64, 0'i64) + ok(IoLockHandle(handle: handle, offset: 0'i64, size: 0'i64)) + +proc unlockFile*(lock: IoLockHandle): IoResult[void] = + ## Clear shared or exclusive lock ``lock``. + let res = unlockFile(lock.handle, lock.offset, lock.size) + if res.isErr(): + err(res.error()) + else: + ok() diff --git a/vendor/nim-stew/stew/keyed_queue.nim b/vendor/nim-stew/stew/keyed_queue.nim index 55d07552f..5cf0224c8 100644 --- a/vendor/nim-stew/stew/keyed_queue.nim +++ b/vendor/nim-stew/stew/keyed_queue.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2018 Status Research & Development GmbH +# Copyright (c) 2018-2022 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or # http://www.apache.org/licenses/LICENSE-2.0) @@ -29,7 +29,10 @@ import export results -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} type KeyedQueueItem*[K,V] = object ##\ @@ -380,14 +383,12 @@ proc delete*[K,V](rq: var KeyedQueue[K,V]; key: K): ## Delete the item with key `key` from the queue and returns the key-value ## item pair just deleted (if any). if rq.tab.hasKey(key): - try: + noKeyError("delete"): let kvp = KeyedQueuePair[K,V]( key: key, data: rq.tab[key].data) rq.deleteImpl(key) return ok(kvp) - except KeyError: - raiseAssert "We've checked that the key is present above" err() proc del*[K,V](rq: var KeyedQueue[K,V]; key: K) = @@ -773,7 +774,7 @@ iterator nextKeys*[K,V](rq: var KeyedQueue[K,V]): K = ## :Note: ## When running in a loop it is *ok* to delete the current item and all ## the items already visited. Items not visited yet must not be deleted - ## as the loop would be come unpredictable, then. + ## as the loop would become unpredictable. if 0 < rq.tab.len: var key = rq.kFirst diff --git a/vendor/nim-stew/stew/leb128.nim b/vendor/nim-stew/stew/leb128.nim index fbb11e36d..90737181d 100644 --- a/vendor/nim-stew/stew/leb128.nim +++ b/vendor/nim-stew/stew/leb128.nim @@ -109,6 +109,11 @@ template read7(shift: untyped) = if (shift div 7) >= xlen: return (I(0), 0'i8) # Not enough data - return 0 bytes read + when shift >= sizeof(I) * 8: + # avoid shift overflows: https://github.com/nim-lang/Nim/issues/19983 + if true: + return (I(0), -cast[int8]((shift div 7) + 1)) + let b = x[shift div 7] valb = b and 0x7f'u8 # byte without high bit diff --git a/vendor/nim-stew/stew/objects.nim b/vendor/nim-stew/stew/objects.nim index 3410b583d..cbf561ca3 100644 --- a/vendor/nim-stew/stew/objects.nim +++ b/vendor/nim-stew/stew/objects.nim @@ -1,5 +1,6 @@ import - macros + macros, + sequtils template init*(lvalue: var auto) = mixin init @@ -67,26 +68,28 @@ proc baseType*(obj: RootObj): cstring = proc baseType*(obj: ref RootObj): cstring = obj[].baseType -when false: - # TODO: Implementing this doesn't seem possible at the moment. - # - # When given enum like: - # - # type WithoutHoles2 = enum - # A2 = 2, B2 = 3, C2 = 4 - # - # ...the code below will print: - # - # EnumTy - # Empty - # Sym "A2" - # Sym "B2" - # Sym "C2" - # - macro hasHoles*(T: type[enum]): bool = - let t = getType(T)[1] - echo t.treeRepr - return newLit(true) +macro enumRangeInt64*(a: type[enum]): untyped = + ## This macro returns an array with all the ordinal values of an enum + let + values = a.getType[1][1..^1] + valuesOrded = values.mapIt(newCall("int64", it)) + newNimNode(nnkBracket).add(valuesOrded) + +macro hasHoles*(T: type[enum]): bool = + # As an enum is always sorted, just substract the first and the last ordinal value + # and compare the result to the number of element in it will do the trick. + let len = T.getType[1].len - 2 + + quote: `T`.high.ord - `T`.low.ord != `len` + +proc contains*[I: SomeInteger](e: type[enum], v: I): bool = + when I is uint64: + if v > int.high.uint64: + return false + when e.hasHoles(): + v.int64 in enumRangeInt64(e) + else: + v.int64 in e.low.int64 .. e.high.int64 func checkedEnumAssign*[E: enum, I: SomeInteger](res: var E, value: I): bool = ## This function can be used to safely assign a tainted integer value (coming @@ -94,14 +97,7 @@ func checkedEnumAssign*[E: enum, I: SomeInteger](res: var E, value: I): bool = ## if the integer value is within the acceped values of the enum and `false` ## otherwise. - # TODO: Enums with holes are not supported yet - # static: doAssert(not hasHoles(E)) - - when I is SomeSignedInt or low(E).int > 0: - if value < I(low(E)): - return false - - if value > I(high(E)): + if value notin E: return false res = E value @@ -113,4 +109,3 @@ func isZeroMemory*[T](x: T): bool = if b != 0: return false return true - diff --git a/vendor/nim-stew/stew/ranges/stackarrays.nim b/vendor/nim-stew/stew/ranges/stackarrays.nim index cb178a4a4..2e9646082 100644 --- a/vendor/nim-stew/stew/ranges/stackarrays.nim +++ b/vendor/nim-stew/stew/ranges/stackarrays.nim @@ -37,6 +37,9 @@ ## be reasonable for short-lived allocations. ## +when (NimMajor, NimMinor) < (1, 4): + import ../shims/stddefects + type StackArray*[T] = object bufferLen: int32 @@ -50,7 +53,7 @@ else: proc alloca(n: int): pointer {.importc, header: "".} proc raiseRangeError(s: string) = - raise newException(RangeError, s) + raise newException(RangeDefect, s) proc raiseOutOfRange = raiseRangeError "index out of range" diff --git a/vendor/nim-stew/stew/ranges/typedranges.nim b/vendor/nim-stew/stew/ranges/typedranges.nim index 422c5f7a7..f03671271 100644 --- a/vendor/nim-stew/stew/ranges/typedranges.nim +++ b/vendor/nim-stew/stew/ranges/typedranges.nim @@ -2,6 +2,10 @@ import ../ptrops, typetraits, hashes +when (NimMajor, NimMinor) < (1, 4): + import ../shims/stddefects + + const rangesGCHoldEnabled = not defined(rangesDisableGCHold) const unsafeAPIEnabled* = defined(rangesEnableUnsafeAPI) @@ -159,17 +163,11 @@ proc `[]=`*[T, U, V](r: MutRange[T], s: HSlice[U, V], v: openArray[T]) = if L == v.len: for i in 0..=(0,19,9): - # error message in Nim HEAD 2019-01-02: - # "for a 'var' type a variable needs to be passed, but 'toOpenArray(cast[ptr UncheckedArray[T]](curHash.start), 0, high(curHash))' is immutable" - toOpenArray(cast[ptr UncheckedArray[T]](r.start), 0, r.high) - else: - # NOTE: `0` in `array[0, T]` is irrelevant - toOpenArray(cast[ptr array[0, T]](r.start)[], 0, r.high) + # NOTE: `0` in `array[0, T]` is irrelevant + toOpenArray(cast[ptr array[0, T]](r.start)[], 0, r.high) proc `[]=`*[T, U, V](r: MutRange[T], s: HSlice[U, V], v: Range[T]) {.inline.} = r[s] = toOpenArray(v) @@ -246,7 +244,7 @@ proc tryAdvance*[T](x: var MutRange[T], idx: int): bool {.inline.} = proc advance*[T](x: var Range[T], idx: int) = ## Move internal start offset of range ``x`` by ``idx`` elements forward. let res = x.advanceImpl(idx) - if not res: raise newException(IndexError, "Advance Error") + if not res: raise newException(IndexDefect, "Advance Error") proc advance*[T](x: var MutRange[T], idx: int) {.inline.} = ## Move internal start offset of range ``x`` by ``idx`` elements forward. diff --git a/vendor/nim-stew/stew/results.nim b/vendor/nim-stew/stew/results.nim index 99bb5e278..b3e6a2689 100644 --- a/vendor/nim-stew/stew/results.nim +++ b/vendor/nim-stew/stew/results.nim @@ -884,6 +884,24 @@ func filter*[T]( # Options compatibility +template some*[T](O: type Opt, v: T): Opt[T] = + ## Create an `Opt` set to a value + ## + ## ``` + ## let o = Opt.some(42) + ## assert o.isSome and o.get() == 42 + ## ``` + Opt[T].ok(v) + +template none*(O: type Opt, T: type): Opt[T] = + ## Create an `Opt` set to none + ## + ## ``` + ## let o = Opt.none(int) + ## assert o.isNone + ## ``` + Opt[T].err() + template isSome*(o: Opt): bool = ## Alias for `isOk` isOk o diff --git a/vendor/nim-stew/stew/saturating_arith.nim b/vendor/nim-stew/stew/saturating_arith.nim new file mode 100644 index 000000000..96177fa13 --- /dev/null +++ b/vendor/nim-stew/stew/saturating_arith.nim @@ -0,0 +1,8 @@ +## This module may hold various saturating arithmetic definitions. +## It will be expanded on demand as more definitions are requred. + +func saturate*(T: type int64, u: uint64): T = + if u > high(int64).uint64: + high(int64) + else: + int64(u) diff --git a/vendor/nim-stew/stew/saturation_arith.nim b/vendor/nim-stew/stew/saturation_arith.nim new file mode 100644 index 000000000..f8ce023a8 --- /dev/null +++ b/vendor/nim-stew/stew/saturation_arith.nim @@ -0,0 +1,8 @@ +## This module may hold various saturating arithmetic definitions. +## It will be expanded on demand as Status project require its definition + +func saturate*(T: type int64, u: uint64): T = + if u > high(int64).uint64: + high(int64) + else: + int64(u) diff --git a/vendor/nim-stew/stew/shims/macros.nim b/vendor/nim-stew/stew/shims/macros.nim index 4958bc672..828b3df10 100644 --- a/vendor/nim-stew/stew/shims/macros.nim +++ b/vendor/nim-stew/stew/shims/macros.nim @@ -191,8 +191,14 @@ proc recordFields*(typeImpl: NimNode): seq[FieldDescription] = result.add FieldDescription(typ: typeImpl[i], name: ident("Field" & $(i - 1))) return - typeImpl.expectKind nnkTypeDef - collectFieldsInHierarchy(result, typeImpl[2]) + let objectType = case typeImpl.kind + of nnkObjectTy: typeImpl + of nnkTypeDef: typeImpl[2] + else: + macros.error("object type expected", typeImpl) + return + + collectFieldsInHierarchy(result, objectType) macro field*(obj: typed, fieldName: static string): untyped = newDotExpr(obj, ident fieldName) @@ -412,7 +418,7 @@ macro unpackArgs*(callee: untyped, args: untyped): untyped = for arg in args: let arg = if arg.kind == nnkHiddenStdConv: arg[1] else: arg - if arg.kind == nnkArglist: + if arg.kind == nnkArgList: for subarg in arg: result.add subarg else: diff --git a/vendor/nim-stew/stew/shims/net.nim b/vendor/nim-stew/stew/shims/net.nim index 734963136..6a60eb456 100644 --- a/vendor/nim-stew/stew/shims/net.nim +++ b/vendor/nim-stew/stew/shims/net.nim @@ -5,7 +5,10 @@ type ValidIpAddress* {.requiresInit.} = object value: IpAddress -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} proc ipv4*(address: array[4, byte]): ValidIpAddress = ValidIpAddress(value: IpAddress(family: IPv4, address_v4: address)) diff --git a/vendor/nim-stew/stew/shims/stddefects.nim b/vendor/nim-stew/stew/shims/stddefects.nim new file mode 100644 index 000000000..91f990e93 --- /dev/null +++ b/vendor/nim-stew/stew/shims/stddefects.nim @@ -0,0 +1,23 @@ +when (NimMajor, NimMinor) < (1, 4): + type + AccessViolationDefect* = AccessViolationError + ArithmeticDefect* = ArithmeticError + AssertionDefect* = AssertionError + DeadThreadDefect* = DeadThreadError + DivByZeroDefect* = DivByZeroError + FieldDefect* = FieldError + FloatDivByZeroDefect* = FloatDivByZeroError + FloatInexactDefect* = FloatInexactError + FloatInvalidOpDefect* = FloatInvalidOpError + FloatOverflowDefect* = FloatOverflowError + FloatUnderflowDefect* = FloatUnderflowError + FloatingPointDefect* = FloatingPointError + IndexDefect* = IndexError + NilAccessDefect* = NilAccessError + ObjectAssignmentDefect* = ObjectAssignmentError + ObjectConversionDefect* = ObjectConversionError + OutOfMemDefect* = OutOfMemError + OverflowDefect* = OverflowError + RangeDefect* = RangeError + ReraiseDefect* = ReraiseError + StackOverflowDefect* = StackOverflowError diff --git a/vendor/nim-stew/stew/sorted_set.nim b/vendor/nim-stew/stew/sorted_set.nim index b053c3bc3..88b19063f 100644 --- a/vendor/nim-stew/stew/sorted_set.nim +++ b/vendor/nim-stew/stew/sorted_set.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2018 Status Research & Development GmbH +# Copyright (c) 2018-2022 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or # http://www.apache.org/licenses/LICENSE-2.0) @@ -87,7 +87,10 @@ type ## returned from functions. RbResult[SortedSetItemRef[K,V]] -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} # ------------------------------------------------------------------------------ # Private helpers diff --git a/vendor/nim-stew/stew/sorted_set/rbtree_delete.nim b/vendor/nim-stew/stew/sorted_set/rbtree_delete.nim index c602bc996..9b05123b0 100644 --- a/vendor/nim-stew/stew/sorted_set/rbtree_delete.nim +++ b/vendor/nim-stew/stew/sorted_set/rbtree_delete.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2018 Status Research & Development GmbH +# Copyright (c) 2018-2022 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or # http://www.apache.org/licenses/LICENSE-2.0) @@ -13,7 +13,10 @@ import ./rbtree_rotate, ../results -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} # ------------------------------------------------------------------------------ # Public @@ -119,8 +122,9 @@ proc rbTreeDelete*[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] = dirY = q.linkLeft.isNil.toDir parent.link[dirX] = q.link[dirY]; # clear node cache if this was the one to be deleted - if not rbt.cache.isNil and rbt.cmp(rbt.cache.casket,key) == 0: - rbt.cache = nil + if not rbt.cache.isNil: + if rbt.cmp(rbt.cache.casket,key) == 0: + rbt.cache = nil q = nil # some hint for the GC to recycle that node rbt.size.dec diff --git a/vendor/nim-stew/stew/sorted_set/rbtree_desc.nim b/vendor/nim-stew/stew/sorted_set/rbtree_desc.nim index 7f57e0a28..762ca8762 100644 --- a/vendor/nim-stew/stew/sorted_set/rbtree_desc.nim +++ b/vendor/nim-stew/stew/sorted_set/rbtree_desc.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2018 Status Research & Development GmbH +# Copyright (c) 2018-2022 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or # http://www.apache.org/licenses/LICENSE-2.0) @@ -170,7 +170,10 @@ type start*: bool ## `true` after a rewind operation stop*: bool ## End of traversal -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} # ------------------------------------------------------------------------------ # Public functions, constructor diff --git a/vendor/nim-stew/stew/sorted_set/rbtree_find.nim b/vendor/nim-stew/stew/sorted_set/rbtree_find.nim index f87a3939f..62a39a744 100644 --- a/vendor/nim-stew/stew/sorted_set/rbtree_find.nim +++ b/vendor/nim-stew/stew/sorted_set/rbtree_find.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2018 Status Research & Development GmbH +# Copyright (c) 2018-2022 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or # http://www.apache.org/licenses/LICENSE-2.0) @@ -12,7 +12,10 @@ import ./rbtree_desc, ../results -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} # ----------------------------------------------------------------------- ------ # Public @@ -31,8 +34,9 @@ proc rbTreeFindEq*[C,K](rbt: RbTreeRef[C,K]; key: K): RbResult[C] = if rbt.root.isNil: return err(rbEmptyTree) - if not rbt.cache.isNil and rbt.cmp(rbt.cache.casket,key) == 0: - return ok(rbt.cache.casket) + if not rbt.cache.isNil: + if rbt.cmp(rbt.cache.casket,key) == 0: + return ok(rbt.cache.casket) var q = rbt.root diff --git a/vendor/nim-stew/stew/sorted_set/rbtree_flush.nim b/vendor/nim-stew/stew/sorted_set/rbtree_flush.nim index e268125ce..f823b8721 100644 --- a/vendor/nim-stew/stew/sorted_set/rbtree_flush.nim +++ b/vendor/nim-stew/stew/sorted_set/rbtree_flush.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2018 Status Research & Development GmbH +# Copyright (c) 2018-2022 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or # http://www.apache.org/licenses/LICENSE-2.0) @@ -14,7 +14,10 @@ import type RbTreeFlushDel*[C] = proc(c: var C) {.gcsafe.} -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} # ----------------------------------------------------------------------- ------ # Private diff --git a/vendor/nim-stew/stew/sorted_set/rbtree_insert.nim b/vendor/nim-stew/stew/sorted_set/rbtree_insert.nim index c5223844e..96d55f7ff 100644 --- a/vendor/nim-stew/stew/sorted_set/rbtree_insert.nim +++ b/vendor/nim-stew/stew/sorted_set/rbtree_insert.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2018 Status Research & Development GmbH +# Copyright (c) 2018-2022 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or # http://www.apache.org/licenses/LICENSE-2.0) @@ -13,7 +13,10 @@ import ./rbtree_rotate, ../results -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} # ----------------------------------------------------------------------- ------ # Private functions diff --git a/vendor/nim-stew/stew/sorted_set/rbtree_reset.nim b/vendor/nim-stew/stew/sorted_set/rbtree_reset.nim index a57631957..7d81acda2 100644 --- a/vendor/nim-stew/stew/sorted_set/rbtree_reset.nim +++ b/vendor/nim-stew/stew/sorted_set/rbtree_reset.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2018 Status Research & Development GmbH +# Copyright (c) 2018-2022 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or # http://www.apache.org/licenses/LICENSE-2.0) @@ -13,7 +13,10 @@ import ./rbtree_flush, ./rbtree_walk -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} # ----------------------------------------------------------------------- ------ # Public diff --git a/vendor/nim-stew/stew/sorted_set/rbtree_rotate.nim b/vendor/nim-stew/stew/sorted_set/rbtree_rotate.nim index 82763c16e..1910edb7c 100644 --- a/vendor/nim-stew/stew/sorted_set/rbtree_rotate.nim +++ b/vendor/nim-stew/stew/sorted_set/rbtree_rotate.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2018 Status Research & Development GmbH +# Copyright (c) 2018-2022 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or # http://www.apache.org/licenses/LICENSE-2.0) @@ -11,7 +11,10 @@ import ./rbtree_desc -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} proc rbTreeRotateSingle*[C](node: RbNodeRef[C]; dir: RbDir): RbNodeRef[C] = ## Perform a single red-black tree rotation in the specified direction. diff --git a/vendor/nim-stew/stew/sorted_set/rbtree_verify.nim b/vendor/nim-stew/stew/sorted_set/rbtree_verify.nim index 15c4c531e..bf596e8d5 100644 --- a/vendor/nim-stew/stew/sorted_set/rbtree_verify.nim +++ b/vendor/nim-stew/stew/sorted_set/rbtree_verify.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2018 Status Research & Development GmbH +# Copyright (c) 2018-2022 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or # http://www.apache.org/licenses/LICENSE-2.0) @@ -33,7 +33,10 @@ type pr: RbPrnFn msg: string ## collect data -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} # ----------------------------------------------------------------------- ------ # Private diff --git a/vendor/nim-stew/stew/sorted_set/rbtree_walk.nim b/vendor/nim-stew/stew/sorted_set/rbtree_walk.nim index 8da4bcc01..bcd9b0c0a 100644 --- a/vendor/nim-stew/stew/sorted_set/rbtree_walk.nim +++ b/vendor/nim-stew/stew/sorted_set/rbtree_walk.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2018 Status Research & Development GmbH +# Copyright (c) 2018-2022 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or # http://www.apache.org/licenses/LICENSE-2.0) @@ -13,7 +13,10 @@ import ./rbtree_desc, ../results -{.push raises: [Defect].} +when (NimMajor, NimMinor) < (1, 4): + {.push raises: [Defect].} +else: + {.push raises: [].} # ----------------------------------------------------------------------- ------ # Priv diff --git a/vendor/nim-stew/tests/all_tests.nim b/vendor/nim-stew/tests/all_tests.nim index ff73e45b5..818b76a4e 100644 --- a/vendor/nim-stew/tests/all_tests.nim +++ b/vendor/nim-stew/tests/all_tests.nim @@ -1,5 +1,5 @@ # stew -# Copyright 2018-2019 Status Research & Development GmbH +# Copyright 2018-2022 Status Research & Development GmbH # Licensed under either of # # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) @@ -22,11 +22,12 @@ import test_endians2, test_io2, test_keyed_queue, + test_sorted_set, + test_interval_set, test_macros, test_objects, test_ptrops, test_sequtils2, - test_sorted_set, test_sets, test_templateutils, test_results, diff --git a/vendor/nim-stew/tests/ranges/all.nim b/vendor/nim-stew/tests/ranges/all.nim index fc19e3489..735b9dd04 100644 --- a/vendor/nim-stew/tests/ranges/all.nim +++ b/vendor/nim-stew/tests/ranges/all.nim @@ -1,2 +1,4 @@ +{.used.} + import ttypedranges, tstackarrays, tbitranges diff --git a/vendor/nim-stew/tests/ranges/tbitranges.nim b/vendor/nim-stew/tests/ranges/tbitranges.nim index 3589b61de..06eddef67 100644 --- a/vendor/nim-stew/tests/ranges/tbitranges.nim +++ b/vendor/nim-stew/tests/ranges/tbitranges.nim @@ -1,5 +1,13 @@ +# Copyright (c) 2019-2022 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license: http://opensource.org/licenses/MIT +# * Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +{.used.} + import - random, unittest, + random, unittest2, ../../stew/ranges/bitranges, ../../stew/bitseqs proc randomBytes(n: int): seq[byte] = diff --git a/vendor/nim-stew/tests/ranges/tstackarrays.nim b/vendor/nim-stew/tests/ranges/tstackarrays.nim index 45c89669a..ff75a94a3 100644 --- a/vendor/nim-stew/tests/ranges/tstackarrays.nim +++ b/vendor/nim-stew/tests/ranges/tstackarrays.nim @@ -1,8 +1,19 @@ +# Copyright (c) 2019-2022 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license: http://opensource.org/licenses/MIT +# * Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +{.used.} + import - unittest, math, + unittest2, math, ../../stew/ptrops, ../../stew/ranges/[stackarrays] +when (NimMajor, NimMinor) < (1, 4): + import ../../stew/shims/stddefects + suite "Stack arrays": test "Basic operations work as expected": var arr = allocStackArray(int, 10) @@ -25,14 +36,14 @@ suite "Stack arrays": cast[ptr int](offset(addr arr[0], 5))[] == 10 test "Allocating with a negative size throws a RangeError": - expect RangeError: + expect RangeDefect: discard allocStackArray(string, -1) test "The array access is bounds-checked": var arr = allocStackArray(string, 3) arr[2] = "test" check arr[2] == "test" - expect RangeError: + expect RangeDefect: arr[3] = "another test" test "proof of stack allocation": diff --git a/vendor/nim-stew/tests/ranges/ttypedranges.nim b/vendor/nim-stew/tests/ranges/ttypedranges.nim index d99c0b343..87318d869 100644 --- a/vendor/nim-stew/tests/ranges/ttypedranges.nim +++ b/vendor/nim-stew/tests/ranges/ttypedranges.nim @@ -1,7 +1,19 @@ +# Copyright (c) 2019-2022 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license: http://opensource.org/licenses/MIT +# * Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +{.used.} + import - unittest, sets, + unittest2, sets, ../../stew/ranges/[typedranges, ptr_arith] +when (NimMajor, NimMinor) < (1, 4): + import ../../stew/shims/stddefects + + suite "Typed ranges": test "basic stuff": var r = newRange[int](5) @@ -161,7 +173,7 @@ suite "Typed ranges": try: a.advance(b) res = 1 - except IndexError: + except IndexDefect: res = 2 res @@ -213,7 +225,7 @@ suite "Typed ranges": try: a.advance(b) res = 1 - except IndexError: + except IndexDefect: res = 2 res diff --git a/vendor/nim-stew/tests/test_arrayops.nim b/vendor/nim-stew/tests/test_arrayops.nim index ccc8f2f5b..f1d7dc507 100644 --- a/vendor/nim-stew/tests/test_arrayops.nim +++ b/vendor/nim-stew/tests/test_arrayops.nim @@ -10,7 +10,7 @@ {.used.} import - std/unittest, + unittest2, ../stew/arrayops suite "arrayops": diff --git a/vendor/nim-stew/tests/test_assign2.nim b/vendor/nim-stew/tests/test_assign2.nim index f5ebe2684..0c61e2b22 100644 --- a/vendor/nim-stew/tests/test_assign2.nim +++ b/vendor/nim-stew/tests/test_assign2.nim @@ -1,5 +1,13 @@ +# Copyright (c) 2020-2022 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license: http://opensource.org/licenses/MIT +# * Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +{.used.} + import - std/unittest, + unittest2, ../stew/assign2 suite "assign2": diff --git a/vendor/nim-stew/tests/test_base10.nim b/vendor/nim-stew/tests/test_base10.nim index 81a3ba203..2593b82f9 100644 --- a/vendor/nim-stew/tests/test_base10.nim +++ b/vendor/nim-stew/tests/test_base10.nim @@ -1,4 +1,4 @@ -import unittest +import unittest2 import ../stew/base10 when defined(nimHasUsed): {.used.} diff --git a/vendor/nim-stew/tests/test_base32.nim b/vendor/nim-stew/tests/test_base32.nim index 7d34dfd4e..362166584 100644 --- a/vendor/nim-stew/tests/test_base32.nim +++ b/vendor/nim-stew/tests/test_base32.nim @@ -1,4 +1,4 @@ -import unittest +import unittest2 import ../stew/base32 when defined(nimHasUsed): {.used.} diff --git a/vendor/nim-stew/tests/test_base58.nim b/vendor/nim-stew/tests/test_base58.nim index 8309cb386..ab0fbe3f4 100644 --- a/vendor/nim-stew/tests/test_base58.nim +++ b/vendor/nim-stew/tests/test_base58.nim @@ -1,4 +1,4 @@ -import unittest +import unittest2 import ../stew/base58 when defined(nimHasUsed): {.used.} diff --git a/vendor/nim-stew/tests/test_base64.nim b/vendor/nim-stew/tests/test_base64.nim index 34d37c271..21e9a44e8 100644 --- a/vendor/nim-stew/tests/test_base64.nim +++ b/vendor/nim-stew/tests/test_base64.nim @@ -1,4 +1,4 @@ -import unittest +import unittest2 import ../stew/[base64, byteutils] when defined(nimHasUsed): {.used.} diff --git a/vendor/nim-stew/tests/test_bitops2.nim b/vendor/nim-stew/tests/test_bitops2.nim index 1f81217cf..278008189 100644 --- a/vendor/nim-stew/tests/test_bitops2.nim +++ b/vendor/nim-stew/tests/test_bitops2.nim @@ -1,4 +1,12 @@ -import unittest +# Copyright (c) 2019-2022 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license: http://opensource.org/licenses/MIT +# * Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +{.used.} + +import unittest2 import ../stew/bitops2 diff --git a/vendor/nim-stew/tests/test_bitseqs.nim b/vendor/nim-stew/tests/test_bitseqs.nim index bbc06b98e..51188c126 100644 --- a/vendor/nim-stew/tests/test_bitseqs.nim +++ b/vendor/nim-stew/tests/test_bitseqs.nim @@ -1,5 +1,13 @@ +# Copyright (c) 2019-2022 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license: http://opensource.org/licenses/MIT +# * Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +{.used.} + import - unittest, strformat, + unittest2, strformat, ../stew/[bitseqs] suite "Bit fields": diff --git a/vendor/nim-stew/tests/test_byteutils.nim b/vendor/nim-stew/tests/test_byteutils.nim index 5707af08d..e9c413c73 100644 --- a/vendor/nim-stew/tests/test_byteutils.nim +++ b/vendor/nim-stew/tests/test_byteutils.nim @@ -1,12 +1,14 @@ # byteutils -# Copyright (c) 2018 Status Research & Development GmbH +# Copyright (c) 2018-2022 Status Research & Development GmbH # Licensed and distributed under either of # * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT). # * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0). # at your option. This file may not be copied, modified, or distributed except according to those terms. +{.used.} + import - std/unittest, + unittest2, ../stew/byteutils proc compilationTest {.exportc: "compilationTest".} = @@ -28,6 +30,32 @@ suite "Byte utils": hexToByteArray(s, a) check a == [255.byte, 255, 255, 255] + test "hexToByteArrayStrict": + let + short0 = "" + short1 = "0x" + short2 = "0x00" + short3 = "0xffffff" + short4 = "0xfffffff" + correct = "0xffffffff" + long1 = "0xfffffffff" + long2 = "0xffffffffff" + + var a: array[4, byte] + hexToByteArrayStrict(correct, a) + check a == [255.byte, 255, 255, 255] + + template reject(val: string) = + expect ValueError: hexToByteArrayStrict(val, a) + + reject short0 + reject short1 + reject short2 + reject short3 + reject short4 + reject long1 + reject long2 + test "hexToByteArray: Return array": let s = "0x12345678" @@ -115,6 +143,7 @@ suite "Byte utils": string.fromBytes([]) == "" @[byte(ord('a'))] == static("a".toBytes()) "a" == static(string.fromBytes([byte(ord('a'))])) + test "slices": var a: array[4, byte] a[0..<2] = [2'u8, 3] diff --git a/vendor/nim-stew/tests/test_ctops.nim b/vendor/nim-stew/tests/test_ctops.nim index f44d74613..4efa8b95e 100644 --- a/vendor/nim-stew/tests/test_ctops.nim +++ b/vendor/nim-stew/tests/test_ctops.nim @@ -1,4 +1,12 @@ -import unittest +# Copyright (c) 2020-2022 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license: http://opensource.org/licenses/MIT +# * Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +{.used.} + +import unittest2 import ../stew/ctops suite "Constant-time operations test suite": diff --git a/vendor/nim-stew/tests/test_endians2.nim b/vendor/nim-stew/tests/test_endians2.nim index 5971f30a8..9f5cb03b1 100644 --- a/vendor/nim-stew/tests/test_endians2.nim +++ b/vendor/nim-stew/tests/test_endians2.nim @@ -1,4 +1,12 @@ -import unittest +# Copyright (c) 2019-2022 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license: http://opensource.org/licenses/MIT +# * Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +{.used.} + +import unittest2 import ../stew/endians2 diff --git a/vendor/nim-stew/tests/test_helper.nim b/vendor/nim-stew/tests/test_helper.nim new file mode 100644 index 000000000..dfc017399 --- /dev/null +++ b/vendor/nim-stew/tests/test_helper.nim @@ -0,0 +1,47 @@ +# Copyright (c) 2020-2022 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license: http://opensource.org/licenses/MIT +# * Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +import std/[os, strutils] +import ../stew/io2, ../stew/results + +proc lockFileFlags(path: string, flags: set[OpenFlags], + lockType: LockType): IoResult[void] = + let handle = ? openFile(path, flags) + let info = ? lockFile(handle, lockType) + ? unlockFile(info) + ? closeFile(handle) + ok() + +when isMainModule: + if paramCount() != 1: + echo "Not enough parameters" + else: + const TestFlags = [ + ({OpenFlags.Read}, LockType.Shared), + ({OpenFlags.Write}, LockType.Exclusive), + + ({OpenFlags.Read, OpenFlags.Write}, LockType.Shared), + ({OpenFlags.Read, OpenFlags.Write}, LockType.Exclusive), + + ({OpenFlags.Read, OpenFlags.ShareRead}, LockType.Shared), + ({OpenFlags.Write, OpenFlags.ShareWrite}, LockType.Exclusive), + + ({OpenFlags.Read, OpenFlags.Write, + OpenFlags.ShareRead, OpenFlags.ShareWrite}, LockType.Shared), + ({OpenFlags.Read, OpenFlags.Write, + OpenFlags.ShareRead, OpenFlags.ShareWrite}, LockType.Exclusive), + ] + let pathName = paramStr(1) + let response = + block: + var res: seq[string] + for test in TestFlags: + let + lres = lockFileFlags(pathName, test[0], test[1]) + data = if lres.isOk(): "OK" else: "E" & $int(lres.error()) + res.add(data) + res.join(":") + echo response diff --git a/vendor/nim-stew/tests/test_interval_set.nim b/vendor/nim-stew/tests/test_interval_set.nim new file mode 100644 index 000000000..7747c7d7b --- /dev/null +++ b/vendor/nim-stew/tests/test_interval_set.nim @@ -0,0 +1,390 @@ +# Nimbus - Types, data structures and shared utilities used in network sync +# +# Copyright (c) 2018-2022 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or +# http://www.apache.org/licenses/LICENSE-2.0) +# * MIT license ([LICENSE-MIT](LICENSE-MIT) or +# http://opensource.org/licenses/MIT) +# at your option. This file may not be copied, modified, or +# distributed except according to those terms. + +{.used.} + +import + unittest2, + ../stew/interval_set + +const + # needs additional import, so this is not standard + TestFrBlockBNumberAlikeOk = false + +when TestFrBlockBNumberAlikeOk: + import stint + type FancyScalar = UInt256 # instead of BlockNumber +else: + type FancyScalar = uint64 + + +type + FancyPoint = distinct FancyScalar + FancyRanges = IntervalSetRef[FancyPoint,FancyScalar] + FancyInterval = Interval[FancyPoint,FancyScalar] + +const + uHigh = high(uint64) + uLow = low(uint64) + +let + ivError = IntervalRc[FancyPoint,FancyScalar].err() + +# ------------------------------------------------------------------------------ +# Private data type cast helpers +# ------------------------------------------------------------------------------ + +when 8 < sizeof(FancyScalar): # assuming UInt256: + proc to(num: uint64; T: type FancyScalar): T = num.u256.T + proc to(num: uint64; T: type FancyPoint): T = num.to(FancyScalar).T +else: + proc to(num: uint64; T: type FancyPoint): T = num.T + proc to(num: uint64; T: type FancyScalar): T = num.T + proc truncate(num: FancyScalar; T: type uint64): T = num + +# ------------------------------------------------------------------------------ +# Private data type interface for `IntervalSet` implementation +# ------------------------------------------------------------------------------ + +# use a sub-range for `FancyPoint` elements +proc high(T: type FancyPoint): T = uHigh.to(FancyPoint) +proc low(T: type FancyPoint): T = uLow.to(FancyPoint) + +proc to(num: FancyPoint; T: type FancyScalar): T = num.T +proc `$`(num: FancyPoint): string = $num.to(FancyScalar) + +proc `+`*(a: FancyPoint; b: FancyScalar): FancyPoint = + (a.to(FancyScalar) + b).FancyPoint + +proc `-`*(a: FancyPoint; b: FancyScalar): FancyPoint = + (a.to(FancyScalar) - b).FancyPoint + +proc `-`*(a, b: FancyPoint): FancyScalar = + (a.to(FancyScalar) - b.to(FancyScalar)) + +proc `==`*(a, b: FancyPoint): bool = a.to(FancyScalar) == b.to(FancyScalar) +proc `<=`*(a, b: FancyPoint): bool = a.to(FancyScalar) <= b.to(FancyScalar) +proc `<`*(a, b: FancyPoint): bool = a.to(FancyScalar) < b.to(FancyScalar) + +# ------------------------------------------------------------------------------ +# Private functions +# ------------------------------------------------------------------------------ + +proc truncate(num: FancyPoint; T: type uint64): uint64 = + num.to(FancyScalar).truncate(uint64) + +proc merge(br: FancyRanges; left, right: uint64): uint64 = + let (a, b) = (left.to(FancyPoint), right.to(FancyPoint)) + br.merge(a, b).truncate(uint64) + +proc reduce(br: FancyRanges; left, right: uint64): uint64 = + let (a, b) = (left.to(FancyPoint), right.to(FancyPoint)) + br.reduce(a, b).truncate(uint64) + +proc covered(br: FancyRanges; left, right: uint64): uint64 = + let (a, b) = (left.to(FancyPoint), right.to(FancyPoint)) + br.covered(a, b).truncate(uint64) + +proc delete(br: FancyRanges; start: uint64): Result[FancyInterval,void] = + br.delete(start.to(FancyPoint)) + +proc le(br: FancyRanges; start: uint64): Result[FancyInterval,void] = + br.le(start.to(FancyPoint)) + +proc ge(br: FancyRanges; start: uint64): Result[FancyInterval,void] = + br.ge(start.to(FancyPoint)) + +proc envelope(br: FancyRanges; start: uint64): Result[FancyInterval,void] = + br.envelope(start.to(FancyPoint)) + +proc iv(left, right: uint64): FancyInterval = + FancyInterval.new(left.to(FancyPoint), right.to(FancyPoint)) + +# ------------------------------------------------------------------------------ +# Test Runner +# ------------------------------------------------------------------------------ + +suite "IntervalSet: Intervals of FancyPoint entries over FancyScalar": + let br = FancyRanges.init() + var dup: FancyRanges + + test "Verify max interval handling": + br.clear() + check br.merge(0,uHigh) == 0 + check br.chunks == 1 + check br.total == 0 + check br.verify.isOk + + check br.reduce(uHigh,uHigh) == 1 + check br.chunks == 1 + check br.total == uHigh.to(FancyScalar) + check br.verify.isOk + + test "Verify handling of maximal interval points (edge cases)": + br.clear() + check br.merge(0,uHigh) == 0 + check br.reduce(uHigh-1,uHigh-1) == 1 + check br.verify.isOk + check br.chunks == 2 + check br.total == uHigh.to(FancyScalar) + + check br.le(uHigh) == iv(uHigh,uHigh) + check br.le(uHigh-1) == iv(0,uHigh-2) + check br.le(uHigh-2) == iv(0,uHigh-2) + check br.le(uHigh-3) == ivError + + check br.ge(0) == iv(0,uHigh-2) + check br.ge(1) == iv(uHigh,uHigh) + check br.ge(uHigh-3) == iv(uHigh,uHigh) + check br.ge(uHigh-2) == iv(uHigh,uHigh) + check br.ge(uHigh-3) == iv(uHigh,uHigh) + check br.ge(uHigh) == iv(uHigh,uHigh) + + check br.reduce(0,uHigh-2) == uHigh-1 + check br.verify.isOk + check br.chunks == 1 + check br.total == 1.to(FancyScalar) + + check br.le(uHigh) == iv(uHigh,uHigh) + check br.le(uHigh-1) == ivError + check br.le(uHigh-2) == ivError + check br.le(0) == ivError + + check br.ge(uHigh) == iv(uHigh,uHigh) + check br.ge(uHigh-1) == iv(uHigh,uHigh) + check br.ge(uHigh-2) == iv(uHigh,uHigh) + check br.ge(0) == iv(uHigh,uHigh) + + br.clear() + check br.total == 0 and br.chunks == 0 + check br.merge(0,uHigh) == 0 + check br.reduce(0,9999999) == 10000000 + check br.total.truncate(uint64) == (uHigh - 10000000) + 1 + check br.verify.isOk + + check br.merge(uHigh,uHigh) == 0 + check br.verify.isOk + + check br.reduce(uHigh,uHigh-1) == 1 # same as reduce(uHigh,uHigh) + check br.total.truncate(uint64) == (uHigh - 10000000) + check br.verify.isOk + check br.merge(uHigh,uHigh-1) == 1 # same as merge(uHigh,uHigh) + check br.total.truncate(uint64) == (uHigh - 10000000) + 1 + check br.verify.isOk + + test "More edge cases detected and fixed": + br.clear() + check br.total == 0 and br.chunks == 0 + check br.merge(uHigh,uHigh) == 1 + + block: + var (ivVal, ivSet) = (iv(0,0), false) + for iv in br.increasing: + check ivSet == false + (ivVal, ivSet) = (iv, true) + check ivVal == iv(uHigh,uHigh) + block: + var (ivVal, ivSet) = (iv(0,0), false) + for iv in br.decreasing: + check ivSet == false + (ivVal, ivSet) = (iv, true) + check ivVal == iv(uHigh,uHigh) + + br.clear() # from blockchain sync crash + check br.total == 0 and br.chunks == 0 + check br.merge(1477152,uHigh) == uHigh - 1477151 + check br.merge(1477151,1477151) == 1 + + br.clear() # from blockchain snap sync odd behaviour + check br.merge(0,uHigh) == 0 + check br.ge(1000) == ivError + check 0 < br.reduce(99999,uHigh-1) + check br.ge(1000) == iv(uHigh,uHigh) + + br.clear() + check br.merge(0,uHigh) == 0 + check br.le(uHigh) == iv(0,uHigh) + check br.le(uHigh-1) == ivError + check 0 < br.reduce(99999,uHigh-1) + check br.le(uHigh) == iv(uHigh,uHigh) + check br.le(uHigh-1) == iv(0,99998) + check br.le(uHigh-2) == iv(0,99998) + + test "Interval envelopes": + br.clear() + check br.merge(0,uHigh) == 0 + check br.ge(1000) == ivError + check br.le(1000) == ivError + check br.envelope(1000) == iv(0,uHigh) + + check 0 < br.reduce(1000,1000) + check br.envelope(1000) == ivError + + check 0 < br.reduce(uHigh,uHigh) + check br.envelope(2000) == iv(1001,uHigh-1) + check br.envelope(uHigh-1) == iv(1001,uHigh-1) + + check 0 < br.merge(0,uHigh) # actually == 2 + check 0 < br.reduce(uHigh-1,uHigh-1) + check br.envelope(uHigh-1) == ivError + check br.envelope(uHigh-2) == iv(0,uHigh-2) + check br.ge(uHigh) == iv(uHigh,uHigh) + check br.envelope(uHigh) == iv(uHigh,uHigh) + + test "Merge overlapping intervals": + br.clear() + check br.merge(100, 199) == 100 + check br.merge(150, 200) == 1 + check br.total == 101 + check br.chunks == 1 + check br.verify.isOk + check br.merge( 99, 150) == 1 + check br.total == 102 + check br.chunks == 1 + check br.verify.isOk + + test "Merge disjunct intervals on 1st set": + br.clear() + check br.merge( 0, 99) == 100 + check br.merge(200, 299) == 100 + check br.merge(400, 499) == 100 + check br.merge(600, 699) == 100 + check br.merge(800, 899) == 100 + check br.total == 500 + check br.chunks == 5 + check br.verify.isOk + + test "Reduce non overlapping intervals on 1st set": + check br.reduce(100, 199) == 0 + check br.reduce(300, 399) == 0 + check br.reduce(500, 599) == 0 + check br.reduce(700, 799) == 0 + check br.verify.isOk + + test "Clone a 2nd set and verify covered data ranges": + dup = br.clone + check dup.covered( 0, 99) == 100 + check dup.covered(100, 199) == 0 + check dup.covered(200, 299) == 100 + check dup.covered(300, 399) == 0 + check dup.covered(400, 499) == 100 + check dup.covered(500, 599) == 0 + check dup.covered(600, 699) == 100 + check dup.covered(700, 799) == 0 + check dup.covered(800, 899) == 100 + check dup.covered(900, uint64.high) == 0 + + check dup.covered(200, 599) == 200 + check dup.covered(200, 799) == 300 + check dup.total == 500 + check dup.chunks == 5 + check dup.verify.isOk + + test "Merge overlapping intervals on 2nd set": + check dup.merge( 50, 250) == 100 + check dup.merge(450, 850) == 200 + check dup.verify.isOk + + test "Verify covered data ranges on 2nd set": + check dup.covered( 0, 299) == 300 + check dup.covered(300, 399) == 0 + check dup.covered(400, 899) == 500 + check dup.covered(900, uint64.high) == 0 + check dup.total == 800 + check dup.chunks == 2 + check dup.verify.isOk + + test "Verify 1st and 2nd set differ": + check br != dup + + test "Reduce overlapping intervals on 2nd set": + check dup.reduce(100, 199) == 100 + check dup.reduce(500, 599) == 100 + check dup.reduce(700, 799) == 100 + check dup.verify.isOk + + test "Verify 1st and 2nd set equal": + check br == dup + check br == br + check dup == dup + + test "Find intervals in the 1st set": + check br.le(100) == iv( 0, 99) + check br.le(199) == iv( 0, 99) + check br.le(200) == iv( 0, 99) + check br.le(299) == iv(200, 299) + check br.le(999) == iv(800, 899) + check br.le(50) == ivError + + check br.ge( 0) == iv( 0, 99) + check br.ge( 1) == iv(200, 299) + check br.ge(800) == iv(800, 899) + check br.ge(801) == ivError + + test "Delete intervals from the 2nd set": + check dup.delete(200) == iv(200, 299) + check dup.delete(800) == iv(800, 899) + check dup.verify.isOk + + test "Interval intersections": + check iv(100, 199) * iv(150, 249) == iv(150, 199) + check iv(150, 249) * iv(100, 199) == iv(150, 199) + + check iv(100, 199) * iv(200, 299) == ivError + check iv(200, 299) * iv(100, 199) == ivError + + check iv(200, uHigh) * iv(uHigh,uHigh) == iv(uHigh,uHigh) + check iv(uHigh, uHigh) * iv(200,uHigh) == iv(uHigh,uHigh) + + check iv(100, 199) * iv(150, 249) * iv(100, 170) == iv(150, 170) + check (iv(100, 199) * iv(150, 249)) * iv(100, 170) == iv(150, 170) + check iv(100, 199) * (iv(150, 249) * iv(100, 170)) == iv(150, 170) + + test "Join intervals": + check iv(100, 199) + iv(150, 249) == iv(100, 249) + check iv(150, 249) + iv(100, 199) == iv(100, 249) + + check iv(100, 198) + iv(202, 299) == ivError + check iv(100, 199) + iv(200, 299) == iv(100, 299) + check iv(100, 200) + iv(200, 299) == iv(100, 299) + check iv(100, 201) + iv(200, 299) == iv(100, 299) + + check iv(200, 299) + iv(100, 198) == ivError + check iv(200, 299) + iv(100, 199) == iv(100, 299) + check iv(200, 299) + iv(100, 200) == iv(100, 299) + check iv(200, 299) + iv(100, 201) == iv(100, 299) + + check iv(200, uHigh) + iv(uHigh,uHigh) == iv(200,uHigh) + check iv(uHigh, uHigh) + iv(200,uHigh) == iv(200,uHigh) + + check iv(150, 249) + iv(100, 149) + iv(200, 299) == iv(100, 299) + check (iv(150, 249) + iv(100, 149)) + iv(200, 299) == iv(100, 299) + check iv(150, 249) + (iv(100, 149) + iv(200, 299)) == ivError + + test "Cut off intervals by other intervals": + check iv(100, 199) - iv(150, 249) == iv(100, 149) + check iv(150, 249) - iv(100, 199) == iv(200, 249) + check iv(100, 199) - iv(200, 299) == iv(100, 199) + check iv(200, 299) - iv(100, 199) == iv(200, 299) + + check iv(200, 399) - iv(250, 349) == ivError + check iv(200, 299) - iv(200, 299) == ivError + check iv(200, 299) - iv(200, 399) == ivError + check iv(200, 299) - iv(100, 299) == ivError + check iv(200, 299) - iv(100, 399) == ivError + + check iv(200, 299) - iv(100, 199) - iv(150, 249) == iv(250, 299) + check (iv(200, 299) - iv(100, 199)) - iv(150, 249) == iv(250, 299) + check iv(200, 299) - (iv(100, 199) - iv(150, 249)) == iv(200, 299) + +# ------------------------------------------------------------------------------ +# End +# ------------------------------------------------------------------------------ diff --git a/vendor/nim-stew/tests/test_io2.nim b/vendor/nim-stew/tests/test_io2.nim index c943fc78c..488f06b4b 100644 --- a/vendor/nim-stew/tests/test_io2.nim +++ b/vendor/nim-stew/tests/test_io2.nim @@ -1,6 +1,18 @@ -import unittest +# Copyright (c) 2020-2022 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license: http://opensource.org/licenses/MIT +# * Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +{.used.} + +import unittest2 +import std/[osproc, strutils] import ../stew/io2 +when defined(posix): + from std/posix import EAGAIN + suite "OS Input/Output procedures test suite": test "getCurrentDir() test": let res = getCurrentDir() @@ -513,3 +525,213 @@ suite "OS Input/Output procedures test suite": positions[2] == 0'i64 positions[3] == 10'i64 positions[4] == 20'i64 + + test "lockFile(handle)/unlockFile(handle) test": + type + TestResult = object + output: string + status: int + + proc createLockFile(path: string): IoResult[void] = + io2.writeFile(path, "LOCKFILEDATA") + + proc removeLockFile(path: string): IoResult[void] = + io2.removeFile(path) + + proc lockTest(path: string, flags: set[OpenFlags], + lockType: LockType): IoResult[array[3, TestResult]] = + const HelperPath = + when defined(windows): + "test_helper " + else: + "tests/test_helper " + let + handle = ? openFile(path, flags) + lock = ? lockFile(handle, lockType) + let res1 = + try: + execCmdEx(HelperPath & path) + except CatchableError as exc: + echo "Exception happens [", $exc.name, "]: ", $exc.msg + ("", -1) + ? unlockFile(lock) + let res2 = + try: + execCmdEx(HelperPath & path) + except CatchableError as exc: + echo "Exception happens [", $exc.name, "]: ", $exc.msg + ("", -1) + ? closeFile(handle) + let res3 = + try: + execCmdEx(HelperPath & path) + except CatchableError as exc: + echo "Exception happens [", $exc.name, "]: ", $exc.msg + ("", -1) + ok([ + TestResult(output: strip(res1.output), status: res1.exitCode), + TestResult(output: strip(res2.output), status: res2.exitCode), + TestResult(output: strip(res3.output), status: res3.exitCode), + ]) + + proc performTest(): IoResult[void] = + let path1 = "testfile.lock" + + when defined(windows): + const + ERROR_LOCK_VIOLATION = 33 + ERROR_SHARING_VIOLATION = 32 + let + LockTests = [ + ( + {OpenFlags.Read}, + LockType.Shared, + "OK:E$1:E$1:E$1:OK:E$1:E$1:E$1" % + [$ERROR_SHARING_VIOLATION], + "OK:E$1:E$1:E$1:OK:E$1:E$1:E$1" % + [$ERROR_SHARING_VIOLATION], + "OK:OK:OK:OK:OK:OK:OK:OK" + ), + ( + {OpenFlags.Write}, + LockType.Exclusive, + "E$1:E$1:E$1:E$1:E$1:E$1:E$1:E$1" % + [$ERROR_SHARING_VIOLATION], + "E$1:E$1:E$1:E$1:E$1:E$1:E$1:E$1" % + [$ERROR_SHARING_VIOLATION], + "OK:OK:OK:OK:OK:OK:OK:OK" + ), + ( + {OpenFlags.Read, OpenFlags.Write}, + LockType.Shared, + "E$1:E$1:E$1:E$1:E$1:E$1:E$1:E$1" % + [$ERROR_SHARING_VIOLATION], + "E$1:E$1:E$1:E$1:E$1:E$1:E$1:E$1" % + [$ERROR_SHARING_VIOLATION], + "OK:OK:OK:OK:OK:OK:OK:OK" + ), + ( + {OpenFlags.Read, OpenFlags.Write}, + LockType.Exclusive, + "E$1:E$1:E$1:E$1:E$1:E$1:E$1:E$1" % + [$ERROR_SHARING_VIOLATION], + "E$1:E$1:E$1:E$1:E$1:E$1:E$1:E$1" % + [$ERROR_SHARING_VIOLATION], + "OK:OK:OK:OK:OK:OK:OK:OK" + ), + ( + {OpenFlags.Read, OpenFlags.ShareRead}, + LockType.Shared, + "OK:E$1:E$1:E$1:OK:E$1:E$1:E$1" % + [$ERROR_SHARING_VIOLATION], + "OK:E$1:E$1:E$1:OK:E$1:E$1:E$1" % + [$ERROR_SHARING_VIOLATION], + "OK:OK:OK:OK:OK:OK:OK:OK" + ), + ( + {OpenFlags.Write, OpenFlags.ShareWrite}, + LockType.Exclusive, + "E$1:E$1:E$1:E$1:E$1:E$2:E$1:E$1" % + [$ERROR_SHARING_VIOLATION, $ERROR_LOCK_VIOLATION], + "E$1:E$1:E$1:E$1:E$1:OK:E$1:E$1" % + [$ERROR_SHARING_VIOLATION], + "OK:OK:OK:OK:OK:OK:OK:OK" + ), + ( + {OpenFlags.Read, OpenFlags.Write, OpenFlags.ShareRead, + OpenFlags.ShareWrite}, + LockType.Shared, + "E$1:E$1:E$1:E$1:E$1:E$1:OK:E$2" % + [$ERROR_SHARING_VIOLATION, $ERROR_LOCK_VIOLATION], + "E$1:E$1:E$1:E$1:E$1:E$1:OK:OK" % + [$ERROR_SHARING_VIOLATION], + "OK:OK:OK:OK:OK:OK:OK:OK" + ), + ( + {OpenFlags.Read, OpenFlags.Write, OpenFlags.ShareRead, + OpenFlags.ShareWrite}, + LockType.Exclusive, + "E$1:E$1:E$1:E$1:E$1:E$1:E$2:E$2" % + [$ERROR_SHARING_VIOLATION, $ERROR_LOCK_VIOLATION], + "E$1:E$1:E$1:E$1:E$1:E$1:OK:OK" % + [$ERROR_SHARING_VIOLATION], + "OK:OK:OK:OK:OK:OK:OK:OK" + ), + ] + else: + let + LockTests = [ + ( + {OpenFlags.Read}, + LockType.Shared, + "OK:E$1:OK:E$1:OK:E$1:OK:E$1" % [$EAGAIN], + "OK:OK:OK:OK:OK:OK:OK:OK", + "OK:OK:OK:OK:OK:OK:OK:OK" + ), + ( + {OpenFlags.Write}, + LockType.Exclusive, + "E$1:E$1:E$1:E$1:E$1:E$1:E$1:E$1" % [$EAGAIN], + "OK:OK:OK:OK:OK:OK:OK:OK", + "OK:OK:OK:OK:OK:OK:OK:OK" + ), + ( + {OpenFlags.Read, OpenFlags.Write}, + LockType.Shared, + "OK:E$1:OK:E$1:OK:E$1:OK:E$1" % [$EAGAIN], + "OK:OK:OK:OK:OK:OK:OK:OK", + "OK:OK:OK:OK:OK:OK:OK:OK" + ), + ( + {OpenFlags.Read, OpenFlags.Write}, + LockType.Exclusive, + "E$1:E$1:E$1:E$1:E$1:E$1:E$1:E$1" % [$EAGAIN], + "OK:OK:OK:OK:OK:OK:OK:OK", + "OK:OK:OK:OK:OK:OK:OK:OK" + ), + ( + {OpenFlags.Read, OpenFlags.ShareRead}, + LockType.Shared, + "OK:E$1:OK:E$1:OK:E$1:OK:E$1" % [$EAGAIN], + "OK:OK:OK:OK:OK:OK:OK:OK", + "OK:OK:OK:OK:OK:OK:OK:OK" + ), + ( + {OpenFlags.Write, OpenFlags.ShareWrite}, + LockType.Exclusive, + "E$1:E$1:E$1:E$1:E$1:E$1:E$1:E$1" % [$EAGAIN], + "OK:OK:OK:OK:OK:OK:OK:OK", + "OK:OK:OK:OK:OK:OK:OK:OK" + ), + ( + {OpenFlags.Read, OpenFlags.Write, OpenFlags.ShareRead, + OpenFlags.ShareWrite}, + LockType.Shared, + "OK:E$1:OK:E$1:OK:E$1:OK:E$1" % [$EAGAIN], + "OK:OK:OK:OK:OK:OK:OK:OK", + "OK:OK:OK:OK:OK:OK:OK:OK", + ), + ( + {OpenFlags.Read, OpenFlags.Write, OpenFlags.ShareRead, + OpenFlags.ShareWrite}, + LockType.Exclusive, + "E$1:E$1:E$1:E$1:E$1:E$1:E$1:E$1" % [$EAGAIN], + "OK:OK:OK:OK:OK:OK:OK:OK", + "OK:OK:OK:OK:OK:OK:OK:OK" + ), + ] + + ? createLockFile(path1) + for item in LockTests: + let res = ? lockTest(path1, item[0], item[1]) + check: + res[0].status == 0 + res[1].status == 0 + res[2].status == 0 + res[0].output == item[2] + res[1].output == item[3] + res[2].output == item[4] + ? removeLockFile(path1) + ok() + + check performTest().isOk() diff --git a/vendor/nim-stew/tests/test_keyed_queue.nim b/vendor/nim-stew/tests/test_keyed_queue.nim index 10ce3f89c..bb677fc71 100644 --- a/vendor/nim-stew/tests/test_keyed_queue.nim +++ b/vendor/nim-stew/tests/test_keyed_queue.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2018-2019 Status Research & Development GmbH +# Copyright (c) 2018-2022 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or # http://www.apache.org/licenses/LICENSE-2.0) @@ -8,11 +8,13 @@ # at your option. This file may not be copied, modified, or distributed except # according to those terms. +{.used.} + import std/[algorithm, sequtils, strformat, strutils, tables], + unittest2, ../stew/keyed_queue, - ../stew/keyed_queue/kq_debug, - unittest + ../stew/keyed_queue/kq_debug const usedStrutils = newSeq[string]().join(" ") diff --git a/vendor/nim-stew/tests/test_leb128.nim b/vendor/nim-stew/tests/test_leb128.nim index 0f7d11a1b..0fe569f43 100644 --- a/vendor/nim-stew/tests/test_leb128.nim +++ b/vendor/nim-stew/tests/test_leb128.nim @@ -1,5 +1,5 @@ import - unittest, random, + unittest2, random, ../stew/[byteutils, leb128, results] const edgeValues = { diff --git a/vendor/nim-stew/tests/test_macros.nim b/vendor/nim-stew/tests/test_macros.nim index b7d2c8814..c1110c59b 100644 --- a/vendor/nim-stew/tests/test_macros.nim +++ b/vendor/nim-stew/tests/test_macros.nim @@ -1,7 +1,14 @@ -import - unittest, - ../stew/shims/macros +# Copyright (c) 2020-2022 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license: http://opensource.org/licenses/MIT +# * Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 +# at your option. This file may not be copied, modified, or distributed except according to those terms. +{.used.} + +import + unittest2, + ../stew/shims/macros template unknown() {.pragma.} template zero() {.pragma.} diff --git a/vendor/nim-stew/tests/test_objects.nim b/vendor/nim-stew/tests/test_objects.nim index b64a854a8..a043ea7ff 100644 --- a/vendor/nim-stew/tests/test_objects.nim +++ b/vendor/nim-stew/tests/test_objects.nim @@ -1,5 +1,5 @@ import - unittest, typetraits, + unittest2, typetraits, ../stew/objects when defined(nimHasUsed): @@ -70,23 +70,81 @@ suite "Objects": T6 is DistinctBar T6 isnot Bar - when false: - # TODO: Not possible yet (see objects.nim) - test "hasHoles": - type - WithoutHoles = enum - A1, B1, C1 + test "enumRangeInt64": + type + WithoutHoles = enum + A1, A2, A3 + WithoutHoles2 = enum + B1 = 4, B2 = 5, B3 = 6 + WithHoles = enum + C1 = 1, C2 = 3, C3 = 5 - WithoutHoles2 = enum - A2 = 2, B2 = 3, C2 = 4 + check: + enumRangeInt64(WithoutHoles) == [ 0'i64, 1, 2 ] + enumRangeInt64(WithoutHoles2) == [ 4'i64, 5, 6 ] + enumRangeInt64(WithHoles) == [ 1'i64, 3, 5 ] - WithHoles = enum - A3, B3 = 2, C3 - check: - hasHoles(WithoutHoles2) == false - hasHoles(WithoutHoles) == false - hasHoles(WithHoles) == true + test "contains": + type + WithoutHoles = enum + A1, A2, A3 + WithoutHoles2 = enum + B1 = 4, B2 = 5, B3 = 6 + WithHoles = enum + C1 = 1, C2 = 3, C3 = 5 + WithoutHoles3 = enum + D1 = -1, D2 = 0, D3 = 1 + WithHoles2 = enum + E1 = -5, E2 = 0, E3 = 5 + + check: + 1 in WithoutHoles + 5 notin WithoutHoles + 1 notin WithoutHoles2 + 5 in WithoutHoles2 + 1 in WithHoles + 2 notin WithHoles + 6 notin WithHoles + 5 in WithHoles + 1.byte in WithoutHoles + 4294967295'u32 notin WithoutHoles3 + -1.int8 in WithoutHoles3 + -4.int16 notin WithoutHoles3 + -5.int16 in WithHoles2 + 5.uint64 in WithHoles2 + -12.int8 notin WithHoles2 + int64.high notin WithoutHoles + int64.high notin WithHoles + int64.low notin WithoutHoles + int64.low notin WithHoles + int64.high.uint64 * 2 notin WithoutHoles + int64.high.uint64 * 2 notin WithHoles + + + test "hasHoles": + type + EnumWithOneValue = enum + A0 + + WithoutHoles = enum + A1, B1, C1 + + WithoutHoles2 = enum + A2 = 2, B2 = 3, C2 = 4 + + WithHoles = enum + A3, B3 = 2, C3 + + WithBigHoles = enum + A4 = 0, B4 = 2000, C4 = 4000 + + check: + hasHoles(EnumWithOneValue) == false + hasHoles(WithoutHoles) == false + hasHoles(WithoutHoles2) == false + hasHoles(WithHoles) == true + hasHoles(WithBigHoles) == true test "checkedEnumAssign": type @@ -96,42 +154,41 @@ suite "Objects": AnotherEnum = enum A2 = 2, B2, C2 + EnumWithHoles = enum + A3, B3 = 3, C3 var e1 = A1 e2 = A2 + e3 = A3 check: checkedEnumAssign(e1, 2) e1 == C1 - - check: not checkedEnumAssign(e1, 5) e1 == C1 - - check: checkedEnumAssign(e1, 0) e1 == A1 - - check: not checkedEnumAssign(e1, -1) e1 == A1 - check: checkedEnumAssign(e2, 2) e2 == A2 - - check: not checkedEnumAssign(e2, 5) e2 == A2 - - check: checkedEnumAssign(e2, 4) e2 == C2 - - check: not checkedEnumAssign(e2, 1) e2 == C2 + checkedEnumAssign(e3, 4) + e3 == C3 + not checkedEnumAssign(e3, 1) + e3 == C3 + checkedEnumAssign(e3, 0) + e3 == A3 + not checkedEnumAssign(e3, -1) + e3 == A3 + test "isZeroMemory": type Foo = object diff --git a/vendor/nim-stew/tests/test_ptrops.nim b/vendor/nim-stew/tests/test_ptrops.nim index f78da613b..55106e2f8 100644 --- a/vendor/nim-stew/tests/test_ptrops.nim +++ b/vendor/nim-stew/tests/test_ptrops.nim @@ -1,5 +1,5 @@ # stew -# Copyright 2018-2019 Status Research & Development GmbH +# Copyright 2018-2022 Status Research & Development GmbH # Licensed under either of # # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) @@ -7,7 +7,9 @@ # # at your option. This file may not be copied, modified, or distributed except according to those terms. -import unittest +{.used.} + +import unittest2 import ../stew/ptrops diff --git a/vendor/nim-stew/tests/test_results.nim b/vendor/nim-stew/tests/test_results.nim index 7d5734e8e..857b88182 100644 --- a/vendor/nim-stew/tests/test_results.nim +++ b/vendor/nim-stew/tests/test_results.nim @@ -1,3 +1,5 @@ +{.used.} + # nim-result is also available stand-alone from https://github.com/arnetheduck/nim-result/ import ../stew/results @@ -351,6 +353,9 @@ block: # Result[T, void] aka `Opt` doAssert oOk.filter(proc(x: int): bool = false).isErr() doAssert oErr.filter(proc(x: int): bool = true) == oErr + doAssert Opt.some(42).get() == 42 + doAssert Opt.none(int).isNone() + block: # `cstring` dangling reference protection type CSRes = Result[void, cstring] @@ -398,4 +403,3 @@ block: # Experiments counter2 += 1 doAssert counter2 == 1, "one-item collection when set" - diff --git a/vendor/nim-stew/tests/test_sequtils2.nim b/vendor/nim-stew/tests/test_sequtils2.nim index 3c52f106e..038eaf26b 100644 --- a/vendor/nim-stew/tests/test_sequtils2.nim +++ b/vendor/nim-stew/tests/test_sequtils2.nim @@ -1,12 +1,14 @@ # byteutils -# Copyright (c) 2018 Status Research & Development GmbH +# Copyright (c) 2018-2022 Status Research & Development GmbH # Licensed and distributed under either of # * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT). # * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0). # at your option. This file may not be copied, modified, or distributed except according to those terms. +{.used.} + import - std/unittest, + unittest2, ../stew/sequtils2 suite "sequtils2": diff --git a/vendor/nim-stew/tests/test_sets.nim b/vendor/nim-stew/tests/test_sets.nim index 5ee673503..eb7d53106 100644 --- a/vendor/nim-stew/tests/test_sets.nim +++ b/vendor/nim-stew/tests/test_sets.nim @@ -1,5 +1,13 @@ +# Copyright (c) 2021-2022 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license: http://opensource.org/licenses/MIT +# * Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +{.used.} + import - unittest, + unittest2, ../stew/shims/sets suite "shims/sets": diff --git a/vendor/nim-stew/tests/test_sorted_set.nim b/vendor/nim-stew/tests/test_sorted_set.nim index 7583f67a7..89ce66b04 100644 --- a/vendor/nim-stew/tests/test_sorted_set.nim +++ b/vendor/nim-stew/tests/test_sorted_set.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2018-2019 Status Research & Development GmbH +# Copyright (c) 2018-2022 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or # http://www.apache.org/licenses/LICENSE-2.0) @@ -8,10 +8,12 @@ # at your option. This file may not be copied, modified, or distributed except # according to those terms. +{.used.} + import std/[algorithm, sequtils, strformat, tables], ../stew/sorted_set, - unittest + unittest2 const keyList = [ diff --git a/vendor/nim-stew/tests/test_templateutils.nim b/vendor/nim-stew/tests/test_templateutils.nim index b59773986..96682c657 100644 --- a/vendor/nim-stew/tests/test_templateutils.nim +++ b/vendor/nim-stew/tests/test_templateutils.nim @@ -1,5 +1,13 @@ +# Copyright (c) 2021-2022 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license: http://opensource.org/licenses/MIT +# * Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +{.used.} + import - unittest, + unittest2, ../stew/templateutils var computations = newSeq[string]() diff --git a/vendor/nim-stew/tests/test_varints.nim b/vendor/nim-stew/tests/test_varints.nim index fd4b0ab11..c1a13eb03 100644 --- a/vendor/nim-stew/tests/test_varints.nim +++ b/vendor/nim-stew/tests/test_varints.nim @@ -1,5 +1,13 @@ +# Copyright (c) 2019-2022 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license: http://opensource.org/licenses/MIT +# * Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +{.used.} + import - unittest, random, + unittest2, random, ../stew/[varints, byteutils] const edgeValues = { diff --git a/vendor/nim-stew/tests/test_winacl.nim b/vendor/nim-stew/tests/test_winacl.nim index a86852c5e..612a75896 100644 --- a/vendor/nim-stew/tests/test_winacl.nim +++ b/vendor/nim-stew/tests/test_winacl.nim @@ -1,5 +1,12 @@ -import std/unittest -import ../stew/io2 +# Copyright (c) 2020-2022 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license: http://opensource.org/licenses/MIT +# * Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +{.used.} + +import unittest2 when defined(windows): import ../stew/windows/acl diff --git a/vendor/nim-stint/.github/workflows/ci.yml b/vendor/nim-stint/.github/workflows/ci.yml index ce720f3d6..d4cd1607e 100644 --- a/vendor/nim-stint/.github/workflows/ci.yml +++ b/vendor/nim-stint/.github/workflows/ci.yml @@ -26,11 +26,11 @@ jobs: include: - target: os: linux - builder: ubuntu-18.04 + builder: ubuntu-20.04 shell: bash - target: os: macos - builder: macos-10.15 + builder: macos-11 shell: bash - target: os: windows diff --git a/vendor/nim-stint/stint.nimble b/vendor/nim-stint/stint.nimble index 2586ff460..d18f94c4b 100644 --- a/vendor/nim-stint/stint.nimble +++ b/vendor/nim-stint/stint.nimble @@ -14,9 +14,14 @@ requires "nim >= 0.19", proc test(args, path: string) = if not dirExists "build": mkDir "build" + let styleCheckStyle = + if (NimMajor, NimMinor) < (1, 6): + "hint" + else: + "error" exec "nim " & getEnv("TEST_LANG", "c") & " " & getEnv("NIMFLAGS") & " " & args & " --outdir:build -r --hints:off --warnings:off --skipParentCfg" & - " --styleCheck:usages --styleCheck:error " & path + " --styleCheck:usages --styleCheck:" & styleCheckStyle & " " & path task test, "Run all tests - test and production implementation": # Run tests for internal procs - test implementation (StUint[64] = 2x uint32 diff --git a/vendor/nim-testutils/.github/workflows/ci.yml b/vendor/nim-testutils/.github/workflows/ci.yml index 63e2c4c43..4632bf212 100644 --- a/vendor/nim-testutils/.github/workflows/ci.yml +++ b/vendor/nim-testutils/.github/workflows/ci.yml @@ -26,11 +26,11 @@ jobs: include: - target: os: linux - builder: ubuntu-18.04 + builder: ubuntu-20.04 shell: bash - target: os: macos - builder: macos-10.15 + builder: macos-11 shell: bash - target: os: windows diff --git a/vendor/nim-testutils/tests/hello/hello_size.test b/vendor/nim-testutils/tests/hello/hello_size.test index de7f7aa47..592d40ae9 100644 --- a/vendor/nim-testutils/tests/hello/hello_size.test +++ b/vendor/nim-testutils/tests/hello/hello_size.test @@ -1,5 +1,5 @@ program = "../hello" -max_size = 100000 +max_size = 102000 release --opt:size os = "linux,macosx" diff --git a/vendor/nim-testutils/testutils.nimble b/vendor/nim-testutils/testutils.nimble index dfd1e4206..c0bf8fea3 100644 --- a/vendor/nim-testutils/testutils.nimble +++ b/vendor/nim-testutils/testutils.nimble @@ -1,7 +1,7 @@ mode = ScriptMode.Verbose packageName = "testutils" -version = "0.4.2" +version = "0.5.0" author = "Status Research & Development GmbH" description = "A unittest framework" license = "Apache License 2.0" @@ -10,7 +10,7 @@ bin = @["ntu"] #srcDir = "testutils" requires "nim >= 1.2.0", - "https://github.com/status-im/nim-unittest2.git#head" + "unittest2" proc execCmd(cmd: string) = echo "execCmd: " & cmd diff --git a/vendor/nim-toml-serialization/.github/workflows/ci.yml b/vendor/nim-toml-serialization/.github/workflows/ci.yml index c24bd2f42..6093776eb 100644 --- a/vendor/nim-toml-serialization/.github/workflows/ci.yml +++ b/vendor/nim-toml-serialization/.github/workflows/ci.yml @@ -8,6 +8,7 @@ jobs: max-parallel: 20 matrix: test_lang: [c, cpp] + branch: [version-1-2, version-1-4, version-1-6, devel] target: - os: linux cpu: amd64 @@ -30,7 +31,7 @@ jobs: os: windows builder: windows-latest - name: '${{ matrix.target.os }}-${{ matrix.target.cpu }}-${{ matrix.test_lang }}' + name: '${{ matrix.target.os }}-${{ matrix.target.cpu }}-${{ matrix.test_lang }}-(Nim ${{ matrix.branch }})' runs-on: ${{ matrix.builder }} steps: - name: Checkout nim-toml-serialization @@ -143,7 +144,9 @@ jobs: else MAKE_CMD="make" fi - env MAKE="$MAKE_CMD -j2" ARCH_OVERRIDE=$PLATFORM CC=gcc bash build_nim.sh nim csources dist/nimble NimBinaries + env MAKE="$MAKE_CMD -j2" ARCH_OVERRIDE=$PLATFORM NIM_COMMIT=${{ matrix.branch }} \ + QUICK_AND_DIRTY_COMPILER=1 QUICK_AND_DIRTY_NIMBLE=1 CC=gcc \ + bash build_nim.sh nim csources dist/nimble NimBinaries echo '${{ github.workspace }}/nim/bin' >> $GITHUB_PATH - name: Run nim-toml-serialization tests @@ -152,4 +155,5 @@ jobs: run: | nimble install -y --depsOnly nimble install -y stint + nimble install -y "https://github.com/status-im/nim-unittest2" env TEST_LANG="${{ matrix.test_lang }}" nimble test diff --git a/vendor/nim-toml-serialization/.gitignore b/vendor/nim-toml-serialization/.gitignore index a49b439c3..c9faf0709 100644 --- a/vendor/nim-toml-serialization/.gitignore +++ b/vendor/nim-toml-serialization/.gitignore @@ -2,3 +2,5 @@ nimcache *.exe node_modules package-lock.json +nimble.develop +nimble.paths diff --git a/vendor/nim-toml-serialization/README.md b/vendor/nim-toml-serialization/README.md index 728176d25..28650de5c 100644 --- a/vendor/nim-toml-serialization/README.md +++ b/vendor/nim-toml-serialization/README.md @@ -2,7 +2,7 @@ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![License: Apache](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) -[![TOML](assets/badge-TOML.svg)](https://github.com/toml-lang/toml/releases/tag/1.0.0-rc.2) +[![TOML](assets/badge-TOML.svg)](https://github.com/toml-lang/toml/releases/tag/1.0.0) ![Stability: experimental](https://img.shields.io/badge/stability-experimental-orange.svg) ![nimble](https://img.shields.io/badge/available%20on-nimble-yellow.svg?style=flat-square) ![Github action](https://github.com/status-im/nim-toml-serialization/workflows/CI/badge.svg) @@ -26,6 +26,10 @@ family and provides several operation modes: - Allow skipping unknown fields using `TomlUnknownFields` flag. - Skipping unknown fields also done efficiently, no token produced. But skipped fields should contains valid TOML value or the parser will raise exception. + - Since v0.2.1 you can choose to use `OrderedTable` instead of `Table` when parsing into `TomlValueRef` + using `-d:tomlOrderedTable` compile time switch. + - Since v0.2.3, compile time decode/loadFile are allowed. It means you can initialize const value using + `decode` or `loadFile`. It also ok to use it inside static block or other nim VM code. ## Spec compliance nim-toml-serialization implements [v1.0.0](https://github.com/toml-lang/toml/releases/tag/1.0.0) @@ -344,7 +348,7 @@ TomlTime contains subsecond field. The spec says the precision is implementation In nim-toml-serialization the default is 6 digits precision. Longer precision will be truncated by the parser. -You can override this using compiler switch `-d:subsecondPrecision=numDigits`. +You can override this using compiler switch `-d:tomlSubsecondPrecision=numDigits`. ## Installation diff --git a/vendor/nim-toml-serialization/config.nims b/vendor/nim-toml-serialization/config.nims new file mode 100644 index 000000000..7c9db3205 --- /dev/null +++ b/vendor/nim-toml-serialization/config.nims @@ -0,0 +1,4 @@ +# begin Nimble config (version 1) +when fileExists("nimble.paths"): + include "nimble.paths" +# end Nimble config diff --git a/vendor/nim-toml-serialization/nimble.lock b/vendor/nim-toml-serialization/nimble.lock new file mode 100644 index 000000000..6d48a98d2 --- /dev/null +++ b/vendor/nim-toml-serialization/nimble.lock @@ -0,0 +1,105 @@ +{ + "version": 1, + "packages": { + "unittest2": { + "version": "0.0.4", + "vcsRevision": "f180f596c88dfd266f746ed6f8dbebce39c824db", + "url": "https://github.com/status-im/nim-unittest2.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "fa309c41eaf6ef57895b9e603f2620a2f6e11780" + } + }, + "stew": { + "version": "0.1.0", + "vcsRevision": "6ad35b876fb6ebe0dfee0f697af173acc47906ee", + "url": "https://github.com/status-im/nim-stew.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "46d58c4feb457f3241e3347778334e325dce5268" + } + }, + "httputils": { + "version": "0.3.0", + "vcsRevision": "689da19e9e9cfff4ced85e2b25c6b2b5598ed079", + "url": "https://github.com/status-im/nim-http-utils.git", + "downloadMethod": "git", + "dependencies": [ + "stew" + ], + "checksums": { + "sha1": "4ad3ad68d13c50184180ab4b2eacc0bd7ed2ed44" + } + }, + "bearssl": { + "version": "0.1.5", + "vcsRevision": "ba80e2a0d7ae8aab666cee013e38ff8d33a3e5e7", + "url": "https://github.com/status-im/nim-bearssl", + "downloadMethod": "git", + "dependencies": [ + "unittest2" + ], + "checksums": { + "sha1": "383abd5becc77bf8e365b780a29d20529e1d9c4c" + } + }, + "chronos": { + "version": "3.0.11", + "vcsRevision": "17fed89c99beac5a92d3668d0d3e9b0e4ac13936", + "url": "https://github.com/status-im/nim-chronos.git", + "downloadMethod": "git", + "dependencies": [ + "stew", + "bearssl", + "httputils", + "unittest2" + ], + "checksums": { + "sha1": "f6fffc87571e5f76af2a77c4ebcc0e00909ced4e" + } + }, + "testutils": { + "version": "0.4.2", + "vcsRevision": "aa6e5216f4b4ab5aa971cdcdd70e1ec1203cedf2", + "url": "https://github.com/status-im/nim-testutils", + "downloadMethod": "git", + "dependencies": [ + "unittest2" + ], + "checksums": { + "sha1": "94427e0cce0e0c5841edcd3a6530b4e6b857a3cb" + } + }, + "faststreams": { + "version": "0.3.0", + "vcsRevision": "1b561a9e71b6bdad1c1cdff753418906037e9d09", + "url": "https://github.com/status-im/nim-faststreams.git", + "downloadMethod": "git", + "dependencies": [ + "stew", + "testutils", + "chronos", + "unittest2" + ], + "checksums": { + "sha1": "97edf9797924af48566a0af8267203dc21d80c77" + } + }, + "serialization": { + "version": "0.1.0", + "vcsRevision": "fcd0eadadde0ee000a63df8ab21dc4e9f015a790", + "url": "https://github.com/status-im/nim-serialization.git", + "downloadMethod": "git", + "dependencies": [ + "faststreams", + "unittest2", + "stew" + ], + "checksums": { + "sha1": "fef59519892cac70cccd81b612085caaa5e3e6cf" + } + } + } +} \ No newline at end of file diff --git a/vendor/nim-toml-serialization/tests/test_all.nim b/vendor/nim-toml-serialization/tests/test_all.nim index b972a269f..7950ecc59 100644 --- a/vendor/nim-toml-serialization/tests/test_all.nim +++ b/vendor/nim-toml-serialization/tests/test_all.nim @@ -14,4 +14,6 @@ import test_features, test_encoder, test_value_ops, - test_lexer + test_lexer, + test_lexer_float, + test_compile_time diff --git a/vendor/nim-toml-serialization/tests/test_compile_time.nim b/vendor/nim-toml-serialization/tests/test_compile_time.nim new file mode 100644 index 000000000..d6df920f9 --- /dev/null +++ b/vendor/nim-toml-serialization/tests/test_compile_time.nim @@ -0,0 +1,43 @@ +# toml-serialization +# Copyright (c) 2020 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license: [LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT +# * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +import + unittest2, + ../toml_serialization + +type + Fruits = object + fruit1: string + fruit2: int + fruit3: string + +proc toBlob(x: string): seq[byte] = + result = newSeq[byte](x.len) + for i, c in x: result[i] = c.byte + +const + fruitFile = "tomls/fruits.toml" + toml = staticRead fruitFile + xx = Toml.loadFile("tests/" & fruitFile, Fruits) + yy = Toml.decode(toml, Fruits) + zz = Toml.decode(toml.toBlob, Fruits) + +suite "compile time decoder": + test "compile time loadFile": + check xx.fruit1 == "Apple" + check xx.fruit2 == 1 + check xx.fruit3 == "Orange" + + test "compile time decode string": + check yy.fruit1 == "Apple" + check yy.fruit2 == 1 + check yy.fruit3 == "Orange" + + test "compile time decode blob": + check zz.fruit1 == "Apple" + check zz.fruit2 == 1 + check zz.fruit3 == "Orange" diff --git a/vendor/nim-toml-serialization/tests/test_decoder.nim b/vendor/nim-toml-serialization/tests/test_decoder.nim index 6785a1fdc..07f75010b 100644 --- a/vendor/nim-toml-serialization/tests/test_decoder.nim +++ b/vendor/nim-toml-serialization/tests/test_decoder.nim @@ -6,7 +6,8 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. import - unittest2, os, options, + std/[os, options, tables], + unittest2, ../toml_serialization, ../toml_serialization/[lexer, value_ops] @@ -54,6 +55,10 @@ type child: ChildObject son: GrandChild +proc readValue(r: var TomlReader, table: var Table[string, int]) = + parseTable(r, key): + table[key] = r.parseInt(int) + suite "test decoder": let rawToml = readFile("tests" / "tomls" / "example.toml") var ex = Toml.decode(rawToml, Example) @@ -145,6 +150,13 @@ suite "test decoder": XX = array[3, int] YY = seq[int] + TrailingComma = object + x: seq[int] + y: array[3, int] + w: TomlValueRef + s: string + z: string + let x = Toml.decode("x = [1, 2, 3]", XX, "x") check x == [1, 2, 3] @@ -157,6 +169,55 @@ suite "test decoder": let yy = Toml.decode("x = [1, 2, 3, ]", YY, "x") check yy == @[1, 2, 3] + let ww = Toml.decode("x = [7, 8, 9, ]", TomlValueRef, "x") + + const doc = """ + x = [1, 2, 3, ] + y = [4,5,6,] + w = [7,8,9,] + s = [10 , 11 , 12 , ] + z = "ok" # this last entry is to make sure we parse past last entry ']' + """ + + let zz = Toml.decode(doc, TrailingComma) + check zz.x == @[1, 2, 3] + check zz.y == [4, 5, 6] + check zz.w == ww + check zz.s == "[10,11,12]" + check zz.z == "ok" + + test "Trailing comma in inline table": + type + AbcTC = object + a: int + b: int + c: int + + TrailingCommaIT = object + x: TomlValueRef + y: string + z: AbcTC + w: Table[string, int] + s: string + + const doc = """ + x = {a=1, b=2, c=3, } + y = {a=1, b=2, c=3, } + z = {a=1, b=2, c=3, } + w = {a=1, b=2, c=3, } + s = "ok" + """ + + let xx = Toml.decode("x = {a=1, b=2, c=3, }", TomlValueRef, "x", {TomlInlineTableTrailingComma}) + let r = Toml.decode(doc, TrailingCommaIT, {TomlInlineTableTrailingComma}) + check r.x == xx + check r.y == "{a=1,b=2,c=3}" + check r.z == AbcTC(a:1,b:2,c:3) + check r.w["a"] == 1 + check r.w["b"] == 2 + check r.w["c"] == 3 + check r.s == "ok" + test "case object": type CaseObject = object diff --git a/vendor/nim-toml-serialization/tests/test_lexer.nim b/vendor/nim-toml-serialization/tests/test_lexer.nim index c534b5313..a27e7e625 100644 --- a/vendor/nim-toml-serialization/tests/test_lexer.nim +++ b/vendor/nim-toml-serialization/tests/test_lexer.nim @@ -94,42 +94,6 @@ template testScanBool(input: string, expectedOutput: untyped) = check: lex.scanBool() == expectedOutput -template testDecimalPart(input: string, expectedOutput: untyped) = - var stream = unsafeMemoryInput(input) - var lex = init(TomlLexer, stream) - var value: type expectedOutput - lex.scanDecimalPart(value, Sign.None) - check: - when (type value) is string: - value == expectedOutput - else: - abs(value - expectedOutput) < 1E-7 - -template testScanFrac(input: string, expectedOutput: untyped) = - var stream = unsafeMemoryInput(input) - var lex = init(TomlLexer, stream) - var value: type expectedOutput - lex.scanFrac(value, Sign.None) - check: - when (type value) is string: - value == expectedOutput - else: - abs(value - expectedOutput) < 1E-7 - -template testScanFloat(input: string, expectedOutput: untyped, special: static[bool] = false) = - var stream = unsafeMemoryInput(input) - var lex = init(TomlLexer, stream) - var value: type expectedOutput - discard lex.scanFloat(value) - when not special: - check: - when (type value) is string: - value == expectedOutput - else: - abs(value - expectedOutput) < 1E-7 - else: - check $value == $expectedOutput - template testDateTime(input: string, expectedOutput: untyped, zeroLead = false) = var stream = unsafeMemoryInput(input) var lex = init(TomlLexer, stream) @@ -574,214 +538,6 @@ suite "name test suite": expect TomlError: testTableName("family.genus]] x", @["family", "genus"]) -suite "float test suite 1": - test "scanDecimalPart": - testDecimalPart("123", 0.123'f64) - testDecimalPart("123", 0.123'f32) - testDecimalPart("123", "123") - - testDecimalPart("1_2_3", 0.123'f64) - testDecimalPart("1_2_3", 0.123'f32) - testDecimalPart("1_2_3", "123") - - expect TomlError: - testDecimalPart("1__2_3", 0.123'f64) - - expect TomlError: - testDecimalPart("1__2_3", 0.123'f32) - - expect TomlError: - testDecimalPart("1__2_3", "123") - - expect TomlError: - testDecimalPart("_1_2_3", 0.123'f64) - - expect TomlError: - testDecimalPart("_1_2_3", 0.123'f32) - - expect TomlError: - testDecimalPart("_1_2_3", "123") - - expect TomlError: - testDecimalPart("1_2_3_", 0.123'f64) - - expect TomlError: - testDecimalPart("1_2_3_", 0.123'f32) - - expect TomlError: - testDecimalPart("1_2_3_", "123") - - test "scanFrac string": - testScanFrac("123", "123") - testScanFrac("123e1", "123e1") - testScanFrac("123e+1", "123e+1") - testScanFrac("123e-1", "123e-1") - testScanFrac("123e+0", "123e+0") - testScanFrac("123e-0", "123e-0") - testScanFrac("123e06", "123e06") - - testScanFrac("123E1", "123E1") - testScanFrac("123E+1", "123E+1") - testScanFrac("123E06", "123E06") - testScanFrac("123E+0", "123E+0") - testScanFrac("123E-0", "123E-0") - testScanFrac("123E-1", "123E-1") - - expect TomlError: - testScanFrac("123e", "123e") - - expect TomlError: - testScanFrac("123e+", "123e+") - - expect TomlError: - testScanFrac("123e-", "123e-") - - test "scanFrac float": - testScanFrac("123", 0.123'f64) - testScanFrac("123e1", 0.123e1'f64) - testScanFrac("123e+1", 0.123e1'f64) - testScanFrac("123e-1", 0.123e-1'f64) - testScanFrac("123e+0", 0.123e+0'f64) - testScanFrac("123e-0", 0.123e-0'f64) - testScanFrac("123e06", 0.123e06'f64) - - testScanFrac("123E1", 0.123E1'f64) - testScanFrac("123E+1", 0.123E+1'f64) - testScanFrac("123E-1", 0.123E-1'f64) - testScanFrac("123E06", 0.123E06'f64) - testScanFrac("123E+0", 0.123E+0'f64) - testScanFrac("123E-0", 0.123E-0'f64) - - testScanFrac("123", 0.123'f32) - testScanFrac("123e1", 0.123e1'f32) - testScanFrac("123e+1", 0.123e1'f32) - testScanFrac("123e-1", 0.123e-1'f32) - testScanFrac("123e+0", 0.123e+0'f32) - testScanFrac("123e-0", 0.123e-0'f32) - testScanFrac("123e06", 0.123e06'f32) - - testScanFrac("123E1", 0.123E1'f32) - testScanFrac("123E+1", 0.123E+1'f32) - testScanFrac("123E-1", 0.123E-1'f32) - testScanFrac("123E06", 0.123E06'f32) - testScanFrac("123E+0", 0.123E+0'f32) - testScanFrac("123E-0", 0.123E-0'f32) - - expect TomlError: - testScanFrac("123e", 0.123e0) - - expect TomlError: - testScanFrac("123e+", 0.123e+0) - - expect TomlError: - testScanFrac("123e-", 0.123e-0) - -suite "float test suite 2": - test "scanFloat string": - testScanFloat("123", "123") - testScanFloat("+123", "+123") - testScanFloat("-123", "-123") - - testScanFloat("+inf", "+inf") - testScanFloat("-inf", "-inf") - testScanFloat("+nan", "+nan") - testScanFloat("-nan", "-nan") - - testScanFloat("123E1", "123E1") - testScanFloat("-123E1", "-123E1") - testScanFloat("+123E1", "+123E1") - - testScanFloat("123E+1", "123E+1") - testScanFloat("-123E+1", "-123E+1") - testScanFloat("+123E+1", "+123E+1") - - testScanFloat("123E-1", "123E-1") - testScanFloat("-123E-1", "-123E-1") - testScanFloat("+123E-1", "+123E-1") - - expect TomlError: - testScanFloat("+", "+0") - - expect TomlError: - testScanFloat("-", "-0") - - testScanFloat("-123.123", "-123.123") - testScanFloat("123.123", "123.123") - - testScanFloat("-123.123E+1", "-123.123E+1") - testScanFloat("-123.123E-1", "-123.123E-1") - testScanFloat("123.123E-1", "123.123E-1") - testScanFloat("123.123E+1", "123.123E+1") - - expect TomlError: - testScanFloat("123.a", "123.") - - testScanFloat("0e0", "0e0") - testScanFloat("-0e0", "-0e0") - testScanFloat("+0e0", "+0e0") - -suite "float test suite 3": - test "scanFloat float": - testScanFloat("123", 123'f64) - testScanFloat("+123", 123'f64) - testScanFloat("-123", -123'f64) - - testScanFloat("+inf", Inf, true) - testScanFloat("-inf", -Inf, true) - testScanFloat("+nan", NaN, true) - testScanFloat("-nan", -NaN, true) - - testScanFloat("123E1", 123E1) - testScanFloat("-123E1", -123E1) - testScanFloat("+123E1", 123E1) - - testScanFloat("123E+1", 123E+1) - testScanFloat("-123E+1", -123E+1) - testScanFloat("+123E+1", 123E+1) - - testScanFloat("123E-1", 123E-1) - testScanFloat("-123E-1", -123E-1) - testScanFloat("+123E-1", 123E-1) - - expect TomlError: - testScanFloat("+", 0'f64) - - expect TomlError: - testScanFloat("-", -0'f64) - - testScanFloat("-123.123", -123.123'f64) - testScanFloat("123.123", 123.123'f64) - -suite "float test suite 4": - test "scanFloat float": - expect TomlError: - testScanFloat("123.a", 123.0'f64) - - testScanFloat("123", 123'f32) - testScanFloat("+123", 123'f32) - testScanFloat("-123", -123'f32) - - expect TomlError: - testScanFloat("+", 0'f32) - - expect TomlError: - testScanFloat("-", -0'f32) - - testScanFloat("-123.123", -123.123'f32) - testScanFloat("123.123", 123.123'f32) - - testScanFloat("-123.123E+1", -123.123E+1'f64) - testScanFloat("-123.123E-1", -123.123E-1) - testScanFloat("123.123E-1", 123.123E-1) - testScanFloat("123.123E+1", 123.123E+1) - - expect TomlError: - testScanFloat("123.a", 123.0'f32) - - testScanFloat("0e0", 0e0) - testScanFloat("-0e0", -0e0) - testScanFloat("+0e0", 0e0) - suite "date time test suite 1": test "scanDateTime string": testDateTime("07:32:01.999", "07:32:01.999") @@ -929,11 +685,6 @@ suite "date time test suite 3": testDateTime("979-05-27 07:32:00", x, zeroLead = true) suite "test toml v1.0.0-rc.2": - test "zero leading exponent": - testScanFloat("123E01", 123E1) - testScanFloat("-123.123E+01", -123.123E+1'f64) - testScanFloat("-123.123E-01", -123.123E-1) - test "raw tab in string": testLiteralString("\t\'", "\t") testLiteralString("\'\'\t\'\'\'", "\t") diff --git a/vendor/nim-toml-serialization/tests/test_lexer_float.nim b/vendor/nim-toml-serialization/tests/test_lexer_float.nim new file mode 100644 index 000000000..5e07c7883 --- /dev/null +++ b/vendor/nim-toml-serialization/tests/test_lexer_float.nim @@ -0,0 +1,269 @@ +# toml-serialization +# Copyright (c) 2020 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license: [LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT +# * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +import + faststreams, unittest2 + +# we want to test lexer internals +include + ../toml_serialization/lexer + +proc scanDecimalPart[T](input: string): T = + var stream = unsafeMemoryInput(input) + var lex = init(TomlLexer, stream) + lex.scanDecimalPart(result, Sign.None) + +template testDecimalPart(input: string, expectedOutput: untyped) = + let value = scanDecimalPart[type expectedOutput](input) + check: + when (type value) is string: + value == expectedOutput + else: + abs(value - expectedOutput) < 1E-7 + +proc scanFrac[T](input: string): T = + var stream = unsafeMemoryInput(input) + var lex = init(TomlLexer, stream) + lex.scanFrac(result, Sign.None) + +template testScanFrac(input: string, expectedOutput: untyped) = + let value = scanFrac[type expectedOutput](input) + check: + when (type value) is string: + value == expectedOutput + else: + abs(value - expectedOutput) < 1E-7 + +proc scanFloat[T](input: string): T = + var stream = unsafeMemoryInput(input) + var lex = init(TomlLexer, stream) + discard lex.scanFloat(result) + +template testScanFloat(input: string, expectedOutput: untyped, special: static[bool] = false) = + let value = scanFloat[type expectedOutput](input) + when not special: + check: + when (type value) is string: + value == expectedOutput + else: + abs(value - expectedOutput) < 1E-7 + else: + check $value == $expectedOutput + +suite "float test suite 1": + test "scanDecimalPart": + testDecimalPart("123", 0.123'f64) + testDecimalPart("123", 0.123'f32) + testDecimalPart("123", "123") + + testDecimalPart("1_2_3", 0.123'f64) + testDecimalPart("1_2_3", 0.123'f32) + testDecimalPart("1_2_3", "123") + + expect TomlError: + testDecimalPart("1__2_3", 0.123'f64) + + expect TomlError: + testDecimalPart("1__2_3", 0.123'f32) + + expect TomlError: + testDecimalPart("1__2_3", "123") + + expect TomlError: + testDecimalPart("_1_2_3", 0.123'f64) + + expect TomlError: + testDecimalPart("_1_2_3", 0.123'f32) + + expect TomlError: + testDecimalPart("_1_2_3", "123") + + expect TomlError: + testDecimalPart("1_2_3_", 0.123'f64) + + expect TomlError: + testDecimalPart("1_2_3_", 0.123'f32) + + expect TomlError: + testDecimalPart("1_2_3_", "123") + + test "scanFrac string": + testScanFrac("123", "123") + testScanFrac("123e1", "123e1") + testScanFrac("123e+1", "123e+1") + testScanFrac("123e-1", "123e-1") + testScanFrac("123e+0", "123e+0") + testScanFrac("123e-0", "123e-0") + testScanFrac("123e06", "123e06") + + testScanFrac("123E1", "123E1") + testScanFrac("123E+1", "123E+1") + testScanFrac("123E06", "123E06") + testScanFrac("123E+0", "123E+0") + testScanFrac("123E-0", "123E-0") + testScanFrac("123E-1", "123E-1") + + expect TomlError: + testScanFrac("123e", "123e") + + expect TomlError: + testScanFrac("123e+", "123e+") + + expect TomlError: + testScanFrac("123e-", "123e-") + + test "scanFrac float": + testScanFrac("123", 0.123'f64) + testScanFrac("123e1", 0.123e1'f64) + testScanFrac("123e+1", 0.123e1'f64) + testScanFrac("123e-1", 0.123e-1'f64) + testScanFrac("123e+0", 0.123e+0'f64) + testScanFrac("123e-0", 0.123e-0'f64) + testScanFrac("123e06", 0.123e06'f64) + + testScanFrac("123E1", 0.123E1'f64) + testScanFrac("123E+1", 0.123E+1'f64) + testScanFrac("123E-1", 0.123E-1'f64) + testScanFrac("123E06", 0.123E06'f64) + testScanFrac("123E+0", 0.123E+0'f64) + testScanFrac("123E-0", 0.123E-0'f64) + + testScanFrac("123", 0.123'f32) + testScanFrac("123e1", 0.123e1'f32) + testScanFrac("123e+1", 0.123e1'f32) + testScanFrac("123e-1", 0.123e-1'f32) + testScanFrac("123e+0", 0.123e+0'f32) + testScanFrac("123e-0", 0.123e-0'f32) + testScanFrac("123e06", 0.123e06'f32) + + testScanFrac("123E1", 0.123E1'f32) + testScanFrac("123E+1", 0.123E+1'f32) + testScanFrac("123E-1", 0.123E-1'f32) + testScanFrac("123E06", 0.123E06'f32) + testScanFrac("123E+0", 0.123E+0'f32) + testScanFrac("123E-0", 0.123E-0'f32) + + expect TomlError: + testScanFrac("123e", 0.123e0) + + expect TomlError: + testScanFrac("123e+", 0.123e+0) + + expect TomlError: + testScanFrac("123e-", 0.123e-0) + +suite "float test suite 2": + test "scanFloat string": + testScanFloat("123", "123") + testScanFloat("+123", "+123") + testScanFloat("-123", "-123") + + testScanFloat("+inf", "+inf") + testScanFloat("-inf", "-inf") + testScanFloat("+nan", "+nan") + testScanFloat("-nan", "-nan") + + testScanFloat("123E1", "123E1") + testScanFloat("-123E1", "-123E1") + testScanFloat("+123E1", "+123E1") + + testScanFloat("123E+1", "123E+1") + testScanFloat("-123E+1", "-123E+1") + testScanFloat("+123E+1", "+123E+1") + + testScanFloat("123E-1", "123E-1") + testScanFloat("-123E-1", "-123E-1") + testScanFloat("+123E-1", "+123E-1") + + expect TomlError: + testScanFloat("+", "+0") + + expect TomlError: + testScanFloat("-", "-0") + + testScanFloat("-123.123", "-123.123") + testScanFloat("123.123", "123.123") + + testScanFloat("-123.123E+1", "-123.123E+1") + testScanFloat("-123.123E-1", "-123.123E-1") + testScanFloat("123.123E-1", "123.123E-1") + testScanFloat("123.123E+1", "123.123E+1") + + expect TomlError: + testScanFloat("123.a", "123.") + + testScanFloat("0e0", "0e0") + testScanFloat("-0e0", "-0e0") + testScanFloat("+0e0", "+0e0") + +suite "float test suite 3": + test "scanFloat float": + testScanFloat("123", 123'f64) + testScanFloat("+123", 123'f64) + testScanFloat("-123", -123'f64) + + testScanFloat("+inf", Inf, true) + testScanFloat("-inf", -Inf, true) + testScanFloat("+nan", NaN, true) + testScanFloat("-nan", -NaN, true) + + testScanFloat("123E1", 123E1) + testScanFloat("-123E1", -123E1) + testScanFloat("+123E1", 123E1) + + testScanFloat("123E+1", 123E+1) + testScanFloat("-123E+1", -123E+1) + testScanFloat("+123E+1", 123E+1) + + testScanFloat("123E-1", 123E-1) + testScanFloat("-123E-1", -123E-1) + testScanFloat("+123E-1", 123E-1) + + testScanFloat("-123.123", -123.123'f64) + testScanFloat("123.123", 123.123'f64) + + expect TomlError: + testScanFloat("+", 0'f64) + + expect TomlError: + testScanFloat("-", -0'f64) + +suite "float test suite 4": + test "scanFloat float": + testScanFloat("123", 123'f32) + testScanFloat("+123", 123'f32) + testScanFloat("-123", -123'f32) + + testScanFloat("-123.123", -123.123'f32) + testScanFloat("123.123", 123.123'f32) + + testScanFloat("-123.123E+1", -123.123E+1'f64) + testScanFloat("-123.123E-1", -123.123E-1) + testScanFloat("123.123E-1", 123.123E-1) + testScanFloat("123.123E+1", 123.123E+1) + + testScanFloat("0e0", 0e0) + testScanFloat("-0e0", -0e0) + testScanFloat("+0e0", 0e0) + + expect TomlError: + testScanFloat("123.a", 123.0'f32) + + expect TomlError: + testScanFloat("+", 0'f32) + + expect TomlError: + testScanFloat("-", -0'f32) + + expect TomlError: + testScanFloat("123.a", 123.0'f64) + +suite "test toml v1.0.0-rc.2": + test "zero leading exponent": + testScanFloat("123E01", 123E1) + testScanFloat("-123.123E+01", -123.123E+1'f64) + testScanFloat("-123.123E-01", -123.123E-1) diff --git a/vendor/nim-toml-serialization/tests/test_spec.nim b/vendor/nim-toml-serialization/tests/test_spec.nim index 19b17508a..0c7b1d894 100644 --- a/vendor/nim-toml-serialization/tests/test_spec.nim +++ b/vendor/nim-toml-serialization/tests/test_spec.nim @@ -60,28 +60,32 @@ template roundTripTest(inputFolder: string) = if failed > 0: debugEcho "failed: ", failed - validInputTest("iarna") validInputTest("burntsushi") invalidInputTest("iarna") invalidInputTest("burntsushi") -roundTripTest("iarna") -roundTripTest("burntsushi") +when not tomlOrderedTable: + # TODO: + # the encoder/writer still cannot produce + # ordered result correctly -suite "toml-serialization test suite": - test "case.toml": - check roundTrip("tests" / "tomls" / "case.toml") + roundTripTest("iarna") + roundTripTest("burntsushi") - test "example.toml": - check roundTrip("tests" / "tomls" / "example.toml") + suite "toml-serialization test suite": + test "case.toml": + check roundTrip("tests" / "tomls" / "case.toml") - test "nested_object.toml": - check roundTrip("tests" / "tomls" / "nested_object.toml") + test "example.toml": + check roundTrip("tests" / "tomls" / "example.toml") - test "spec.toml": - check roundTrip("tests" / "tomls" / "spec.toml") + test "nested_object.toml": + check roundTrip("tests" / "tomls" / "nested_object.toml") - test "inline-table-newline.toml": - check roundTrip("tests" / "tomls" / "inline-table-newline.toml", flags = {TomlInlineTableNewline}) + test "spec.toml": + check roundTrip("tests" / "tomls" / "spec.toml") + + test "inline-table-newline.toml": + check roundTrip("tests" / "tomls" / "inline-table-newline.toml", flags = {TomlInlineTableNewline}) diff --git a/vendor/nim-toml-serialization/tests/test_value_ops.nim b/vendor/nim-toml-serialization/tests/test_value_ops.nim index 9c8a2b21b..e818fa58e 100644 --- a/vendor/nim-toml-serialization/tests/test_value_ops.nim +++ b/vendor/nim-toml-serialization/tests/test_value_ops.nim @@ -8,7 +8,7 @@ import unittest2, os, options, tables, ../toml_serialization, - ../toml_serialization/value_ops + ../toml_serialization/[value_ops, types] template roundTrip(fileName: string, params: varargs[untyped]): untyped = let @@ -33,3 +33,28 @@ template copyRoundTripTest(inputFolder: string) = copyRoundTripTest("iarna") copyRoundTripTest("burntsushi") + +suite "table comparison": + let a = TomlValueRef(kind: TomlKind.Int, intVal: 1) + let b = TomlValueRef(kind: TomlKind.Int, intVal: 2) + let x = TomlValueRef(kind: TomlKind.Table, tableVal: TomlTableRef()) + let y = TomlValueRef(kind: TomlKind.Table, tableVal: TomlTableRef()) + let z = TomlValueRef(kind: TomlKind.Table, tableVal: TomlTableRef()) + + x.tableVal["b"] = b + x.tableVal["a"] = a + + y.tableVal["a"] = a + y.tableVal["b"] = b + + z.tableVal["b"] = b + z.tableVal["a"] = a + + test "different insertion order": + when tomlOrderedTable: + check x != y + else: + check x == y + + test "same insertion order": + check x == z diff --git a/vendor/nim-toml-serialization/toml_serialization.nim b/vendor/nim-toml-serialization/toml_serialization.nim index 53391c282..5f7d3e8fb 100644 --- a/vendor/nim-toml-serialization/toml_serialization.nim +++ b/vendor/nim-toml-serialization/toml_serialization.nim @@ -39,6 +39,14 @@ template tomlFatalImpl(fn, R: untyped) = "\' not allowed at top level Toml, called from" & $instantiationInfo().} +template toVMString*(x: openArray[byte]): string = + var z = newString(x.len) + for i, c in x: z[i] = char(c) + z + +template toVMString*(x: string): string = + x + template decode*(_: type Toml, input: string, RecordType: type TomlNotTopLevel, @@ -91,7 +99,11 @@ template tomlDecodeImpl*(input: untyped, # from the fact that the dynamic dispatch mechanisms used in # faststreams may be reading from a file or a network device. try: - var stream = unsafeMemoryInput(input) + var stream: InputStream + when nimvm: + stream = VMInputStream(pos: 0, data: toVMString(input)) + else: + stream = unsafeMemoryInput(input) var reader = unpackArgs(init, [TomlReader, stream, tomlCase, params]) when RecordType is (seq or array) and uTypeIsRecord(RecordType): reader.readTableArray(RecordType, key, tomlCase) @@ -123,6 +135,17 @@ template decode*(_: type Toml, input: openArray[byte], key: string, params: varargs[untyped]): auto = tomlDecodeImpl(input, RecordType, key, TomlCaseSensitive, params) +template decode*(_: type Toml, + input: string, + RecordType: distinct type, + params: varargs[untyped]): auto = + tomlDecodeImpl(input, RecordType, "", TomlCaseSensitive, params) + +template decode*(_: type Toml, + input: openArray[byte], + RecordType: distinct type, + params: varargs[untyped]): auto = + tomlDecodeImpl(input, RecordType, "", TomlCaseSensitive, params) template tomlLoadImpl*(filename: string, RecordType: distinct type, @@ -131,7 +154,12 @@ template tomlLoadImpl*(filename: string, mixin init, ReaderType, readValue - var stream = memFileInput(filename) + var stream: InputStream + when nimvm: + let input = staticRead(filename) + stream = VMInputStream(pos: 0, data: toVMString(input)) + else: + stream = memFileInput(filename) try: var reader = unpackArgs(init, [TomlReader, stream, params]) when RecordType is (seq or array) and uTypeIsRecord(RecordType): @@ -152,3 +180,14 @@ template loadFile*(_: type Toml, filename: string, RecordType: distinct type, key: string, params: varargs[untyped]): auto = tomlLoadImpl(filename, RecordType, key, TomlCaseSensitive, params) + +template loadFile*(_: type Toml, filename: string, + RecordType: distinct type, + tomlCase: TomlCase, + params: varargs[untyped]): auto = + tomlLoadImpl(filename, RecordType, "", tomlCase, params) + +template loadFile*(_: type Toml, filename: string, + RecordType: distinct type, + params: varargs[untyped]): auto = + tomlLoadImpl(filename, RecordType, "", TomlCaseSensitive, params) diff --git a/vendor/nim-toml-serialization/toml_serialization.nimble b/vendor/nim-toml-serialization/toml_serialization.nimble index aebbdddfc..4736f4ad9 100644 --- a/vendor/nim-toml-serialization/toml_serialization.nimble +++ b/vendor/nim-toml-serialization/toml_serialization.nimble @@ -1,7 +1,7 @@ mode = ScriptMode.Verbose packageName = "toml_serialization" -version = "0.2.0" +version = "0.2.3" author = "Status Research & Development GmbH" description = "Flexible TOML serialization [not] relying on run-time type information" license = "Apache License 2.0" @@ -9,11 +9,19 @@ skipDirs = @["tests", "assets"] requires "nim >= 1.1.2", "serialization", - "stew", - "https://github.com/status-im/nim-unittest2" + "stew" ### Helper functions proc test(env, path: string) = + # nnkArglist was changed to nnkArgList, so can't always use --styleCheck:error + # https://github.com/nim-lang/Nim/pull/17529 + # https://github.com/nim-lang/Nim/pull/19822 + let styleCheckStyle = + if (NimMajor, NimMinor) < (1, 6): + "hint" + else: + "error" + # Compilation language is controlled by TEST_LANG var lang = "c" if existsEnv"TEST_LANG": @@ -33,7 +41,8 @@ proc test(env, path: string) = mkDir "build" exec "nim " & lang & " " & env & " --outdir:build -r --hints:off --skipParentCfg" & - " --styleCheck:usages --styleCheck:error " & path + " --styleCheck:usages --styleCheck:" & styleCheckStyle & + " " & path task test, "Run all tests": exec "nim -v" diff --git a/vendor/nim-toml-serialization/toml_serialization/lexer.nim b/vendor/nim-toml-serialization/toml_serialization/lexer.nim index 5b629a41b..4b4a6dca8 100644 --- a/vendor/nim-toml-serialization/toml_serialization/lexer.nim +++ b/vendor/nim-toml-serialization/toml_serialization/lexer.nim @@ -63,8 +63,23 @@ const SPC = ' ' invalidCommentChar = {'\x00'..'\x08', '\x0A'..'\x1F', '\x7F'} -template readChar(s: InputStream): char = - char inputs.read(s) +template readChar*(lex: TomlLexer): char = + when nimvm: + read(VMInputStream(lex.stream)) + else: + char inputs.read(lex.stream) + +template readable*(lex: TomlLexer): bool = + when nimvm: + readable(VMInputStream(lex.stream)) + else: + lex.stream.readable() + +template peekChar*(lex: TomlLexer): char = + when nimvm: + peekChar(VMInputStream(lex.stream)) + else: + lex.stream.peek().char proc lineInfo(lex: TomlLexer): (int, int) {.inline.} = (lex.line, lex.col) @@ -149,10 +164,10 @@ proc init*(T: type TomlLexer, stream: InputStream, flags: TomlFlags = {}): T = proc next*(lex: var TomlLexer): char = ## Return the next available char from the stream associate with ## the parser lex, or EOF if there are no characters left. - if not lex.stream.readable(): + if not lex.readable(): return EOF - result = lex.stream.readChar() + result = lex.readChar() # Update the line and col number if result == LF: @@ -162,7 +177,7 @@ proc next*(lex: var TomlLexer): char = inc(lex.col) template peek(): char = - if not lex.stream.readable(): EOF else: lex.stream.peek().char + if not lex.readable(): EOF else: lex.peekChar() template advance() = discard lex.next @@ -202,7 +217,7 @@ proc nonws*(lex: var TomlLexer, skip: static[LfSkipMode]): char = next = advancePeek - if not lex.stream.readable: + if not lex.readable: # rase case break @@ -287,7 +302,7 @@ proc scanDigits*[T](lex: var TomlLexer, value: var T, var next: char - when T is int: + when T is SomeInteger: let baseNum = (case base of base2: 2 of base8: 8 @@ -307,12 +322,12 @@ proc scanDigits*[T](lex: var TomlLexer, value: var T, when T is string: value.add next - elif T is int: + elif T is SomeInteger: value = value * baseNum + charTo(T, next) elif T is TomlVoid: discard else: - {.fatal: "`scanDigits` only accepts `string` or `int` or `TomlVoid`".} + {.fatal: "`scanDigits` only accepts `string` or `SomeInteger` or `TomlVoid`".} if result == maxDigits: # consume the rest of digits @@ -342,7 +357,7 @@ proc scanUnicode[T](lex: var TomlLexer, kind: char, res: var T) = when T isnot (string or TomlVoid): {.fatal: "`scanUnicode` only accepts `string` or `TomlVoid`".} - var code: int + var code: int64 let col = scanDigits(lex, code, base16) if kind == 'u' and col != 4: @@ -1009,9 +1024,9 @@ proc scanMinuteSecond*[T](lex: var TomlLexer, value: var T) = # Toml spec says additional subsecond precision # should be truncated and not rounded when T is (string or TomlVoid): - discard scanDigits(lex, value, base10, subsecondPrecision) + discard scanDigits(lex, value, base10, tomlSubsecondPrecision) elif T is TomlTime: - discard scanDigits(lex, value.subsecond, base10, subsecondPrecision) + discard scanDigits(lex, value.subsecond, base10, tomlSubsecondPrecision) proc scanTime*[T](lex: var TomlLexer, value: var T) = var line = lex.line @@ -1226,6 +1241,14 @@ proc scanDateTime*[T](lex: var TomlLexer, value: var T, zeroLead = false) = else: raiseTomlErr(lex, errInvalidDateTime) +proc toSigned(x: uint64): int64 = + # special case to prevent min-int overflow conversion + # while letting true overflow happen + if x == 9_223_372_036_854_775_808'u64: + low(int64) + else: + -x.int64 + proc parseNumOrDate*[T](lex: var TomlLexer, value: var T) = when T isnot (TomlValueRef or string or TomlVoid): {.fatal: "`parseNumOrDate` only accepts `TomlValueRef' or string or `TomlVoid`".} @@ -1249,7 +1272,7 @@ proc parseNumOrDate*[T](lex: var TomlLexer, value: var T) = else: value = TomlValueRef(kind: TomlKind.Int) discard scanEncoding(lex, uintVal) - value.intVal = uintVal.int + value.intVal = uintVal.int64 else: # This must now be a float or a date/time, or a sole 0 case next: @@ -1353,7 +1376,7 @@ proc parseNumOrDate*[T](lex: var TomlLexer, value: var T) = when T is string: value.add next elif T is TomlValueRef: - var curSum = int64(next) - int64('0') + var curSum = uint64(next) - uint64('0') while true: next = peek @@ -1413,7 +1436,7 @@ proc parseNumOrDate*[T](lex: var TomlLexer, value: var T) = inc digits else: try: - curSum = curSum * 10'i64 + int64(next) - int64('0') + curSum = curSum * 10'u64 + (uint64(next) - uint64('0')) inc digits except OverflowError: raiseTomlErr(lex, errIntegerOverflow) @@ -1427,14 +1450,14 @@ proc parseNumOrDate*[T](lex: var TomlLexer, value: var T) = when T is TomlValueRef: value = TomlValueRef( kind: TomlKind.Int, - intVal: if sign == Neg: -curSum else: curSum + intVal: if sign == Neg: toSigned(curSum) else: curSum.int64 ) return else: when T is TomlValueRef: value = TomlValueRef( kind: TomlKind.Int, - intVal: if sign == Neg: -curSum else: curSum + intVal: if sign == Neg: toSigned(curSum) else: curSum.int64 ) return break @@ -1546,12 +1569,18 @@ proc parseInlineTable[T](lex: var TomlLexer, value: var T) = if firstComma: raiseTomlErr(lex, errMissingFirstElement) - when T is string: - value.add ',' - next = lex.nonws(skipNoLf) if next == '}': - raiseIllegalChar(lex, '}') + if TomlInlineTableTrailingComma in lex.flags: + advance + when T is string: + value.add '}' + return + else: + raiseIllegalChar(lex, '}') + else: + when T is string: + value.add ',' of '\n': if TomlInlineTableNewline in lex.flags: advance diff --git a/vendor/nim-toml-serialization/toml_serialization/reader.nim b/vendor/nim-toml-serialization/toml_serialization/reader.nim index f15e4a008..0f851eb7e 100644 --- a/vendor/nim-toml-serialization/toml_serialization/reader.nim +++ b/vendor/nim-toml-serialization/toml_serialization/reader.nim @@ -52,7 +52,8 @@ proc init*(T: type TomlReader, TomlReader.init(stream, TomlCaseSensitive, flags) proc moveToKey*(r: var TomlReader, key: string, tomlCase: TomlCase) = - r.state = r.lex.parseToml(key, tomlCase) + if key.len > 0: + r.state = r.lex.parseToml(key, tomlCase) proc setParsed[T: enum](e: var T, s: string) = e = parseEnum[T](s) @@ -151,7 +152,11 @@ template parseInlineTable(r: var TomlReader, key: untyped, body: untyped) = next = nonws(r.lex, skipNoLf) if next == '}': - raiseIllegalChar(r.lex, ',') + if TomlInlineTableTrailingComma in r.lex.flags: + eatChar + break + else: + raiseIllegalChar(r.lex, ',') of '\n': if TomlInlineTableNewline in r.lex.flags: eatChar @@ -211,6 +216,7 @@ template parseListImpl*(r: var TomlReader, index, body: untyped) = # "[b,]") next = nonws(r.lex, skipLf) if next == ']': + eatChar break else: body @@ -371,7 +377,11 @@ proc decodeInlineTable[T](r: var TomlReader, value: var T) = next = nonws(r.lex, skipNoLf) if next == '}': - raiseIllegalChar(r.lex, ',') + if TomlInlineTableTrailingComma in r.lex.flags: + eatChar + break + else: + raiseIllegalChar(r.lex, ',') of '\n': if TomlInlineTableNewline in r.lex.flags: eatChar diff --git a/vendor/nim-toml-serialization/toml_serialization/types.nim b/vendor/nim-toml-serialization/toml_serialization/types.nim index 634ac087f..d8ee38714 100644 --- a/vendor/nim-toml-serialization/toml_serialization/types.nim +++ b/vendor/nim-toml-serialization/toml_serialization/types.nim @@ -7,14 +7,22 @@ import tables, options, math, - serialization/errors + serialization/errors, + faststreams/inputs export errors const defaultStringCapacity* = 256 - subsecondPrecision* {.intdefine.} = 6 + tomlSubsecondPrecision* {.intdefine.} = 6 + tomlOrderedTable* {.booldefine.} = false + +template TableForToml(A, B: type): type = + when tomlOrderedTable: + OrderedTable[A, B] + else: + Table[A, B] type TomlError* = object of SerializationError @@ -37,6 +45,7 @@ type TomlFlag* = enum TomlInlineTableNewline + TomlInlineTableTrailingComma TomlHexEscape # allow \xHH escape sequence TomlHourMinute # allow HH:MM format TomlUnknownFields # allow unknow fields @@ -80,7 +89,7 @@ type time*: Option[TomlTime] zone*: Option[TomlTimeZone] - TomlTable* = Table[string, TomlValueRef] + TomlTable* = TableForToml(string, TomlValueRef) TomlTableRef* = ref TomlTable TomlValueRef* = ref TomlValue @@ -107,19 +116,32 @@ type of TomlKind.Table, TomlKind.InlineTable: tableVal*: TomlTableRef +when tomlOrderedTable: + template withValue*(x: TomlTable, key: string, + value, body1, body2: untyped) = + var valx = x.getOrDefault(key, nil) + if valx.isNil: + body2 + else: + let value {.inject.} = addr(valx) + body1 + proc `==`*(a, b: TomlValueRef): bool proc `==`*(a, b: TomlTableRef): bool = result = true if a.len != b.len: return false - for key, val in a: - b[].withValue(key, node) do: - result = node[] == val - do: - result = false -proc `==`(a, b: TomlValueRef): bool = + when tomlOrderedTable and (NimMajor,NimMinor,NimPatch) < (1,6,0): + # https://github.com/nim-lang/Nim/issues/15750 + # workaround for Nim 1.2.0 and 1.4.0 or less + if a.len == 0 and b.len == 0: + return true + + result = a[] == b[] + +proc `==`*(a, b: TomlValueRef): bool = const tableKind = {TomlKind.Table, TomlKind.InlineTable} @@ -161,3 +183,69 @@ proc `==`(a, b: TomlValueRef): bool = method formatMsg*(err: ref TomlError, filename: string): string {.gcsafe, raises: [Defect].} = filename & err.msg + +proc `$`*(p: TomlDateTime): string = + if p.date.isSome: result.add $p.date.get() + if p.time.isSome: result.add $p.time.get() + if p.zone.isSome: result.add $p.zone.get() + +proc toUgly*(result: var string, p: TomlValueRef) + +proc toUgly*(result: var string, p: TomlTableRef) = + var comma = false + result.add "{" + for key, val in p: + if comma: result.add "," + else: comma = true + result.add key + result.add ":" + result.toUgly val + result.add "}" + +proc toUgly(result: var string, p: TomlValueRef) = + var comma = false + case p.kind + of TomlKind.String: + result.add p.stringVal + of TomlKind.Int: + result.add $p.intVal + of TomlKind.Float: + result.add $p.floatVal + of TomlKind.Bool: + result.add $p.boolVal + of TomlKind.Table, TomlKind.InlineTable: + result.toUgly p.tableVal + of TomlKind.Array: + result.add "[" + for child in p.arrayVal: + if comma: result.add "," + else: comma = true + result.toUgly child + result.add "]" + of TomlKind.DateTime: + result.add $p.dateTime + of TomlKind.Tables: + result.add "[[" + for child in p.tablesVal: + if comma: result.add "," + else: comma = true + result.toUgly child + result.add "]]" + +proc `$`*(p: TomlValueRef): string = + toUgly(result, p) + +type + VMInputStream* = ref object of InputStream + pos*: int + data*: string + +proc read*(s: VMInputStream): char = + result = s.data[s.pos] + inc s.pos + +proc readable*(s: VMInputStream): bool = + s.pos < s.data.len + +proc peekChar*(s: VMInputStream): char = + s.data[s.pos] \ No newline at end of file diff --git a/vendor/nim-toml-serialization/toml_serialization/writer.nim b/vendor/nim-toml-serialization/toml_serialization/writer.nim index a1790e85b..4d5f17202 100644 --- a/vendor/nim-toml-serialization/toml_serialization/writer.nim +++ b/vendor/nim-toml-serialization/toml_serialization/writer.nim @@ -374,7 +374,7 @@ proc writeValue*(w: var TomlWriter, value: auto) = template regularFieldWriter() = inc w.level - w.writeFieldIMPL(FieldTag[RecordType, fieldName, FieldType], field, value) + w.writeFieldIMPL(FieldTag[RecordType, fieldName], field, value) dec w.level w.state = prevState @@ -418,7 +418,7 @@ proc writeValue*(w: var TomlWriter, value: auto) = w.writeFieldName(fieldName) inc w.level - w.writeFieldIMPL(FieldTag[RecordType, fieldName, FieldType], field, value) + w.writeFieldIMPL(FieldTag[RecordType, fieldName], field, value) dec w.level firstField = false @@ -428,7 +428,7 @@ proc writeValue*(w: var TomlWriter, value: auto) = w.state = ExpectValue w.writeFieldName(fieldName) inc w.level - w.writeFieldIMPL(FieldTag[RecordType, fieldName, FieldType], field, value) + w.writeFieldIMPL(FieldTag[RecordType, fieldName], field, value) dec w.level w.state = prevState append '\n' diff --git a/vendor/nim-unittest2/.github/workflows/ci.yml b/vendor/nim-unittest2/.github/workflows/ci.yml index 6c133f0da..5991ee89e 100644 --- a/vendor/nim-unittest2/.github/workflows/ci.yml +++ b/vendor/nim-unittest2/.github/workflows/ci.yml @@ -155,10 +155,6 @@ jobs: - name: Run tests run: | - if [[ "${{ matrix.target.os }}" == "windows" ]]; then - # https://github.com/status-im/nimbus-eth2/issues/3121 - export NIMFLAGS="-d:nimRawSetjmp" - fi nim --version env TEST_LANG="c" nim --hints:off --verbosity:0 test env TEST_LANG="cpp" nim --hints:off --verbosity:0 test diff --git a/vendor/nim-unittest2/.gitignore b/vendor/nim-unittest2/.gitignore index 81e765e6e..971c4f75e 100644 --- a/vendor/nim-unittest2/.gitignore +++ b/vendor/nim-unittest2/.gitignore @@ -1,2 +1,3 @@ nimcache/ docs/ +/nimble.develop diff --git a/vendor/nim-unittest2/nim.cfg b/vendor/nim-unittest2/nim.cfg index 23b72e21a..c2c79f594 100644 --- a/vendor/nim-unittest2/nim.cfg +++ b/vendor/nim-unittest2/nim.cfg @@ -6,3 +6,8 @@ --threads:on +# Avoid some rare stack corruption while using exceptions with a SEH-enabled +# toolchain: https://github.com/status-im/nimbus-eth2/issues/3121 +@if windows and not vcc: + --define:nimRawSetjmp +@end diff --git a/vendor/nim-unittest2/nimble.lock b/vendor/nim-unittest2/nimble.lock new file mode 100644 index 000000000..a05d20dd3 --- /dev/null +++ b/vendor/nim-unittest2/nimble.lock @@ -0,0 +1,4 @@ +{ + "version": 1, + "packages": {} +} \ No newline at end of file diff --git a/vendor/nim-unittest2/unittest2.nim b/vendor/nim-unittest2/unittest2.nim index a44e94236..3308a9f19 100644 --- a/vendor/nim-unittest2/unittest2.nim +++ b/vendor/nim-unittest2/unittest2.nim @@ -277,7 +277,7 @@ method suiteStarted*(formatter: OutputFormatter, suiteName: string) {.base, gcsa method testStarted*(formatter: OutputFormatter, testName: string) {.base, gcsafe.} = discard method failureOccurred*(formatter: OutputFormatter, checkpoints: seq[string], - stackTrace: string) {.base, gcsafe.} = + stackTrace: string) {.base, gcsafe, raises: [Defect].} = ## ``stackTrace`` is provided only if the failure occurred due to an exception. ## ``checkpoints`` is never ``nil``. discard diff --git a/vendor/nim-web3/.github/workflows/ci.yml b/vendor/nim-web3/.github/workflows/ci.yml index b0c44f003..48d5f0d3d 100644 --- a/vendor/nim-web3/.github/workflows/ci.yml +++ b/vendor/nim-web3/.github/workflows/ci.yml @@ -26,11 +26,11 @@ jobs: include: - target: os: linux - builder: ubuntu-18.04 + builder: ubuntu-20.04 shell: bash - target: os: macos - builder: macos-10.15 + builder: macos-11 shell: bash - target: os: windows @@ -148,10 +148,6 @@ jobs: - name: Run tests run: | - if [[ "${{ matrix.target.os }}" == "windows" ]]; then - # https://github.com/status-im/nimbus-eth2/issues/3121 - export NIMFLAGS="-d:nimRawSetjmp" - fi nim --version nimble --version ./ci-test.sh diff --git a/vendor/nim-web3/nim.cfg b/vendor/nim-web3/nim.cfg index f8e9c30e0..11938a8bf 100644 --- a/vendor/nim-web3/nim.cfg +++ b/vendor/nim-web3/nim.cfg @@ -2,3 +2,9 @@ @if nimHasWarningObservableStores: warning[ObservableStores]: off @end + +# Avoid some rare stack corruption while using exceptions with a SEH-enabled +# toolchain: https://github.com/status-im/nimbus-eth2/issues/3121 +@if windows and not vcc: + --define:nimRawSetjmp +@end diff --git a/vendor/nim-web3/tests/all_tests.nim b/vendor/nim-web3/tests/all_tests.nim index 8a6dc3f06..3c87d7f28 100644 --- a/vendor/nim-web3/tests/all_tests.nim +++ b/vendor/nim-web3/tests/all_tests.nim @@ -1,5 +1,5 @@ # web3 -# Copyright (c) 2018 Status Research & Development GmbH +# Copyright (c) 2018-2022 Status Research & Development GmbH # Licensed and distributed under either of # * MIT license: [LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT # * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) @@ -10,6 +10,7 @@ import test, test_deposit_contract, + test_ethhexstrings, test_logs, - test_signed_tx, - test_ethhexstrings + test_quantity, + test_signed_tx diff --git a/vendor/nim-web3/tests/nim.cfg b/vendor/nim-web3/tests/nim.cfg new file mode 100644 index 000000000..371f6d79d --- /dev/null +++ b/vendor/nim-web3/tests/nim.cfg @@ -0,0 +1,5 @@ +# Avoid some rare stack corruption while using exceptions with a SEH-enabled +# toolchain: https://github.com/status-im/nimbus-eth2/issues/3121 +@if windows and not vcc: + --define:nimRawSetjmp +@end diff --git a/vendor/nim-web3/tests/test.nim b/vendor/nim-web3/tests/test.nim index f202c69e6..0179462de 100644 --- a/vendor/nim-web3/tests/test.nim +++ b/vendor/nim-web3/tests/test.nim @@ -82,11 +82,10 @@ const MetaCoinCode = "608060405234801561001057600080fd5b503260009081526020819052 suite "Contracts": - - var web3: Web3 - var accounts: seq[Address] - setup: + var web3: Web3 + var accounts: seq[Address] + proc asyncsetup {.async.} = web3 = await newWeb3("ws://127.0.0.1:8545/") accounts = await web3.provider.eth_accounts() diff --git a/vendor/nim-web3/tests/test_ethhexstrings.nim b/vendor/nim-web3/tests/test_ethhexstrings.nim index e934335c3..3da97de15 100644 --- a/vendor/nim-web3/tests/test_ethhexstrings.nim +++ b/vendor/nim-web3/tests/test_ethhexstrings.nim @@ -35,6 +35,11 @@ suite "Hex quantity": source = "x1234" x = hexQuantityStr source check %x != %source + test "Hex encoded 0x0": + let + source = "0x0" + x = hexQuantityStr"0x0" + check %x == %source suite "Hex data": test "Even length": diff --git a/vendor/nim-web3/tests/test_quantity.nim b/vendor/nim-web3/tests/test_quantity.nim new file mode 100644 index 000000000..e29fcdbea --- /dev/null +++ b/vendor/nim-web3/tests/test_quantity.nim @@ -0,0 +1,43 @@ +import + unittest, std/json, + stint, + ../web3/[conversions, ethtypes] + +proc `==`(x, y: Quantity): bool {.borrow, noSideEffect.} + +suite "JSON-RPC Quantity": + test "Valid": + for (validQuantityStr, validQuantity) in [ + ("0x0", 0), + ("0x123", 291), + ("0x1234", 4660)]: + var resQuantity: Quantity + var resUInt256: UInt256 + var resUInt256Ref: ref UInt256 + fromJson(%validQuantityStr, "", resQuantity) + fromJson(%validQuantityStr, "", resUInt256) + fromJson(%validQuantityStr, "", resUInt256Ref) + check: + resQuantity == validQuantity.Quantity + resUInt256 == validQuantity.u256 + resUInt256Ref[] == validQuantity.u256 + + test "Invalid Quantity/UInt256/ref UInt256": + # TODO once https://github.com/status-im/nimbus-eth2/pull/3850 addressed, + # re-add "0x0400" test case as invalid. + for invalidStr in [ + "", "1234", "01234", "x1234", "0x", "ff"]: + template checkInvalids(typeName: untyped) = + var resQuantity: `typeName` + try: + fromJson(%invalidStr, "", resQuantity) + echo `typeName`, invalidStr + check: false + except ValueError: + check: true + except CatchableError: + check: false + + checkInvalids(Quantity) + checkInvalids(UInt256) + checkInvalids(ref UInt256) diff --git a/vendor/nim-web3/tests/test_utils.nim b/vendor/nim-web3/tests/test_utils.nim index fd0655d87..bac0a496e 100644 --- a/vendor/nim-web3/tests/test_utils.nim +++ b/vendor/nim-web3/tests/test_utils.nim @@ -17,5 +17,5 @@ proc deployContract*(web3: Web3, code: string, gasPrice = 0): Future[ReceiptObje let r = await web3.send(tr) return await web3.getMinedTransactionReceipt(r) -proc ethToWei*(eth: UInt256): UInt256 = +func ethToWei*(eth: UInt256): UInt256 = eth * 1000000000000000000.u256 diff --git a/vendor/nim-web3/web3.nim b/vendor/nim-web3/web3.nim index e1907d52f..905866647 100644 --- a/vendor/nim-web3/web3.nim +++ b/vendor/nim-web3/web3.nim @@ -485,7 +485,7 @@ macro contract*(cname: untyped, body: untyped): untyped = procTyWithRawData[1] = pragmas result.add quote do: - type `cbident` = object + type `cbident`* = object template eventTopic*(T: type `cbident`): string = "0x" & toLowerAscii($keccak256.digest(`signature`)) diff --git a/vendor/nim-web3/web3.nimble b/vendor/nim-web3/web3.nimble index cc34c056e..10f36bbb6 100644 --- a/vendor/nim-web3/web3.nimble +++ b/vendor/nim-web3/web3.nimble @@ -21,10 +21,17 @@ requires "stint" proc test(args, path: string) = if not dirExists "build": mkDir "build" + + let styleCheckStyle = + if (NimMajor, NimMinor) < (1, 6): + "hint" + else: + "error" + exec "nim " & getEnv("TEST_LANG", "c") & " " & getEnv("NIMFLAGS") & " " & args & " --outdir:build -r --skipParentCfg" & " --warning[ObservableStores]:off --warning[GcUnsafe2]:off" & - " --styleCheck:usages --styleCheck:hint" & + " --styleCheck:usages --styleCheck:" & styleCheckStyle & " --hint[XDeclaredButNotUsed]:off --hint[Processing]:off " & path diff --git a/vendor/nim-web3/web3/confutils_defs.nim b/vendor/nim-web3/web3/confutils_defs.nim index 2f4fc5049..dd30fb807 100644 --- a/vendor/nim-web3/web3/confutils_defs.nim +++ b/vendor/nim-web3/web3/confutils_defs.nim @@ -6,12 +6,11 @@ func parseCmdArg*(T: type Address, input: TaintedString): T fromHex(T, string input) func completeCmdArg*(T: type Address, input: TaintedString): seq[string] = - return @[] + @[] func parseCmdArg*(T: type BlockHash, input: TaintedString): T {.raises: [ValueError, Defect].} = fromHex(T, string input) func completeCmdArg*(T: type BlockHash, input: TaintedString): seq[string] = - return @[] - + @[] diff --git a/vendor/nim-web3/web3/conversions.nim b/vendor/nim-web3/web3/conversions.nim index 5028d0e65..609a9fa62 100644 --- a/vendor/nim-web3/web3/conversions.nim +++ b/vendor/nim-web3/web3/conversions.nim @@ -1,3 +1,9 @@ +# Copyright (c) 2019-2022 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + import std/[json, options, strutils, strformat, tables, typetraits], stint, stew/byteutils, json_serialization, faststreams/textio, @@ -6,47 +12,71 @@ import from json_rpc/rpcserver import expect -proc `%`*(n: Int256|UInt256): JsonNode = %("0x" & n.toHex) +template invalidQuantityPrefix(s: string): bool = + # https://ethereum.org/en/developers/docs/apis/json-rpc/#hex-value-encoding + # https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.1/src/engine/specification.md#structures + # "When encoding quantities (integers, numbers): encode as hex, prefix with + # "0x", the most compact representation (slight exception: zero should be + # represented as "0x0")." + # + # strutils.parseHexStr treats 0x as optional otherwise. UInt256.parse treats + # standalone "0x" as valid input. + + # TODO https://github.com/status-im/nimbus-eth2/pull/3850 + # requiring 0x prefis is okay, but can't yet enforce no-leading-zeros + when false: + (not s.startsWith "0x") or s == "0x" or (s != "0x0" and s.startsWith "0x0") + else: + (not s.startsWith "0x") or s == "0x" + +func `%`*(n: Int256|UInt256): JsonNode = %("0x" & n.toHex) # allows UInt256 to be passed as a json string -proc fromJson*(n: JsonNode, argName: string, result: var UInt256) = +func fromJson*(n: JsonNode, argName: string, result: var UInt256) = # expects base 16 string, starting with "0x" n.kind.expect(JString, argName) let hexStr = n.getStr() if hexStr.len > 64 + 2: # including "0x" raise newException(ValueError, "Parameter \"" & argName & "\" value too long for UInt256: " & $hexStr.len) + if hexStr.invalidQuantityPrefix: + raise newException(ValueError, "Parameter \"" & argName & "\" value has invalid leading 0") result = hexStr.parse(StUint[256], 16) # TODO: Handle errors # allows ref UInt256 to be passed as a json string -proc fromJson*(n: JsonNode, argName: string, result: var ref UInt256) = +func fromJson*(n: JsonNode, argName: string, result: var ref UInt256) = # expects base 16 string, starting with "0x" n.kind.expect(JString, argName) let hexStr = n.getStr() if hexStr.len > 64 + 2: # including "0x" raise newException(ValueError, "Parameter \"" & argName & "\" value too long for UInt256: " & $hexStr.len) + if hexStr.invalidQuantityPrefix: + raise newException(ValueError, "Parameter \"" & argName & "\" value has invalid leading 0") new result result[] = hexStr.parse(StUint[256], 16) # TODO: Handle errors -proc bytesFromJson(n: JsonNode, argName: string, result: var openArray[byte]) = +func bytesFromJson(n: JsonNode, argName: string, result: var openArray[byte]) = n.kind.expect(JString, argName) let hexStr = n.getStr() if hexStr.len != result.len * 2 + 2: # including "0x" raise newException(ValueError, "Parameter \"" & argName & "\" value wrong length: " & $hexStr.len) hexToByteArray(hexStr, result) -proc fromJson*[N](n: JsonNode, argName: string, result: var FixedBytes[N]) {.inline.} = +func fromJson*[N](n: JsonNode, argName: string, result: var FixedBytes[N]) + {.inline.} = # expects base 16 string, starting with "0x" bytesFromJson(n, argName, array[N, byte](result)) -proc fromJson*(n: JsonNode, argName: string, result: var DynamicBytes) {.inline.} = +func fromJson*(n: JsonNode, argName: string, result: var DynamicBytes) + {.inline.} = n.kind.expect(JString, argName) result = fromHex(type result, n.getStr()) -proc fromJson*(n: JsonNode, argName: string, result: var Address) {.inline.} = +func fromJson*(n: JsonNode, argName: string, result: var Address) {.inline.} = # expects base 16 string, starting with "0x" bytesFromJson(n, argName, array[20, byte](result)) -proc fromJson*(n: JsonNode, argName: string, result: var TypedTransaction) {.inline.} = +func fromJson*(n: JsonNode, argName: string, result: var TypedTransaction) + {.inline.} = let hexStrLen = n.getStr().len if hexStrLen < 2: # "0x" prefix @@ -58,14 +88,28 @@ proc fromJson*(n: JsonNode, argName: string, result: var TypedTransaction) {.inl distinctBase(result).setLen((hexStrLen - 2) div 2) bytesFromJson(n, argName, distinctBase(result)) -proc fromJson*(n: JsonNode, argName: string, result: var Quantity) {.inline.} = - if n.kind == JInt: - result = Quantity(n.getBiggestInt) - else: - n.kind.expect(JString, argName) - result = Quantity(parseHexInt(n.getStr)) +func fromJson*(n: JsonNode, argName: string, result: var RlpEncodedBytes) + {.inline.} = + let hexStrLen = n.getStr().len + if hexStrLen < 2: + # "0x" prefix + raise newException(ValueError, "Parameter \"" & argName & "\" value too short:" & $hexStrLen) + if hexStrLen mod 2 != 0: + # Spare nibble + raise newException(ValueError, "Parameter \"" & argName & "\" value not byte-aligned:" & $hexStrLen) -func getEnumStringTable(enumType: typedesc): Table[string, enumType] {.compileTime.} = + distinctBase(result).setLen((hexStrLen - 2) div 2) + bytesFromJson(n, argName, distinctBase(result)) + +func fromJson*(n: JsonNode, argName: string, result: var Quantity) {.inline.} = + n.kind.expect(JString, argName) + let hexStr = n.getStr + if hexStr.invalidQuantityPrefix: + raise newException(ValueError, "Parameter \"" & argName & "\" value has invalid leading 0") + result = Quantity(parseHexInt(hexStr)) + +func getEnumStringTable(enumType: typedesc): Table[string, enumType] + {.compileTime.} = var res: Table[string, enumType] # Not intended for enums with ordinal holes or repeated stringification # strings. @@ -73,8 +117,9 @@ func getEnumStringTable(enumType: typedesc): Table[string, enumType] {.compileTi res[$value] = value res -proc fromJson*( - n: JsonNode, argName: string, result: var PayloadExecutionStatus) {.inline.} = +func fromJson*( + n: JsonNode, argName: string, result: var PayloadExecutionStatus) + {.inline.} = n.kind.expect(JString, argName) const enumStrings = static: getEnumStringTable(type(result)) try: @@ -83,20 +128,23 @@ proc fromJson*( raise newException( ValueError, "Parameter \"" & argName & "\" value invalid: " & n.getStr) -proc `%`*(v: Quantity): JsonNode = - result = %encodeQuantity(v.uint64) +func `%`*(v: Quantity): JsonNode = + %encodeQuantity(v.uint64) -proc `%`*[N](v: FixedBytes[N]): JsonNode = - result = %("0x" & array[N, byte](v).toHex) +func `%`*[N](v: FixedBytes[N]): JsonNode = + %("0x" & array[N, byte](v).toHex) -proc `%`*(v: DynamicBytes): JsonNode = - result = %("0x" & toHex(v)) +func `%`*(v: DynamicBytes): JsonNode = + %("0x" & toHex(v)) -proc `%`*(v: Address): JsonNode = - result = %("0x" & array[20, byte](v).toHex) +func `%`*(v: Address): JsonNode = + %("0x" & array[20, byte](v).toHex) -proc `%`*(v: TypedTransaction): JsonNode = - result = %("0x" & distinctBase(v).toHex) +func `%`*(v: TypedTransaction): JsonNode = + %("0x" & distinctBase(v).toHex) + +func `%`*(v: RlpEncodedBytes): JsonNode = + %("0x" & distinctBase(v).toHex) proc writeHexValue(w: JsonWriter, v: openArray[byte]) = w.stream.write "\"0x" @@ -115,6 +163,9 @@ proc writeValue*(w: var JsonWriter, v: Address) = proc writeValue*(w: var JsonWriter, v: TypedTransaction) = writeHexValue w, distinctBase(v) +proc writeValue*(w: var JsonWriter, v: RlpEncodedBytes) = + writeHexValue w, distinctBase(v) + proc readValue*(r: var JsonReader, T: type DynamicBytes): T = fromHex(T, r.readValue(string)) @@ -127,19 +178,28 @@ proc readValue*(r: var JsonReader, T: type Address): T = proc readValue*(r: var JsonReader, T: type TypedTransaction): T = T fromHex(seq[byte], r.readValue(string)) -proc `$`*[N](v: FixedBytes[N]): string {.inline.} = +proc readValue*(r: var JsonReader, T: type RlpEncodedBytes): T = + T fromHex(seq[byte], r.readValue(string)) + +func `$`*(v: Quantity): string {.inline.} = + encodeQuantity(v.uint64) + +func `$`*[N](v: FixedBytes[N]): string {.inline.} = "0x" & array[N, byte](v).toHex -proc `$`*(v: Address): string {.inline.} = +func `$`*(v: Address): string {.inline.} = "0x" & array[20, byte](v).toHex -proc `$`*(v: TypedTransaction): string {.inline.} = +func `$`*(v: TypedTransaction): string {.inline.} = "0x" & distinctBase(v).toHex -proc `$`*(v: DynamicBytes): string {.inline.} = +func `$`*(v: RlpEncodedBytes): string {.inline.} = + "0x" & distinctBase(v).toHex + +func `$`*(v: DynamicBytes): string {.inline.} = "0x" & toHex(v) -proc `%`*(x: EthSend): JsonNode = +func `%`*(x: EthSend): JsonNode = result = newJObject() result["from"] = %x.source if x.to.isSome: @@ -155,7 +215,7 @@ proc `%`*(x: EthSend): JsonNode = if x.nonce.isSome: result["nonce"] = %x.nonce.unsafeGet -proc `%`*(x: EthCall): JsonNode = +func `%`*(x: EthCall): JsonNode = result = newJObject() result["to"] = %x.to if x.source.isSome: @@ -169,10 +229,10 @@ proc `%`*(x: EthCall): JsonNode = if x.data.isSome: result["data"] = %x.data.unsafeGet -proc `%`*(x: byte): JsonNode = +func `%`*(x: byte): JsonNode = %x.int -proc `%`*(x: FilterOptions): JsonNode = +func `%`*(x: FilterOptions): JsonNode = result = newJObject() if x.fromBlock.isSome: result["fromBlock"] = %x.fromBlock.unsafeGet @@ -183,8 +243,7 @@ proc `%`*(x: FilterOptions): JsonNode = if x.topics.isSome: result["topics"] = %x.topics.unsafeGet -proc `%`*(x: RtBlockIdentifier): JsonNode = +func `%`*(x: RtBlockIdentifier): JsonNode = case x.kind of bidNumber: %(&"0x{x.number:X}") of bidAlias: %x.alias - diff --git a/vendor/nim-web3/web3/encoding.nim b/vendor/nim-web3/web3/encoding.nim index 21e42f972..dd54e7f95 100644 --- a/vendor/nim-web3/web3/encoding.nim +++ b/vendor/nim-web3/web3/encoding.nim @@ -152,11 +152,11 @@ macro makeTypeEnum(): untyped = makeTypeEnum() -proc parse*(T: type Bool, val: bool): T = +func parse*(T: type Bool, val: bool): T = let i = if val: 1 else: 0 T i.i256 -proc `==`*(a: Bool, b: Bool): bool = +func `==`*(a: Bool, b: Bool): bool = Int256(a) == Int256(b) func encode*(x: Bool): EncodeResult = encode(Int256(x)) diff --git a/vendor/nim-web3/web3/engine_api.nim b/vendor/nim-web3/web3/engine_api.nim index 75980f669..117e42c4e 100644 --- a/vendor/nim-web3/web3/engine_api.nim +++ b/vendor/nim-web3/web3/engine_api.nim @@ -11,4 +11,3 @@ from os import DirSep, AltSep template sourceDir: string = currentSourcePath.rsplit({DirSep, AltSep}, 1)[0] createRpcSigs(RpcClient, sourceDir & "/engine_api_callsigs.nim") - diff --git a/vendor/nim-web3/web3/engine_api_types.nim b/vendor/nim-web3/web3/engine_api_types.nim index 812bfd30c..5ad17605a 100644 --- a/vendor/nim-web3/web3/engine_api_types.nim +++ b/vendor/nim-web3/web3/engine_api_types.nim @@ -7,46 +7,46 @@ export ethtypes type - # https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.9/src/engine/specification.md#payloadattributesv1 + # https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.1/src/engine/specification.md#payloadattributesv1 PayloadAttributesV1* = object timestamp*: Quantity prevRandao*: FixedBytes[32] suggestedFeeRecipient*: Address - # https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.9/src/engine/specification.md#payloadstatusv1 + # https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.1/src/engine/specification.md#payloadstatusv1 PayloadExecutionStatus* {.pure.} = enum - valid = "VALID" - invalid = "INVALID" - syncing = "SYNCING" - accepted = "ACCEPTED" - invalid_block_hash = "INVALID_BLOCK_HASH" + syncing = "SYNCING" + valid = "VALID" + invalid = "INVALID" + accepted = "ACCEPTED" + invalid_block_hash = "INVALID_BLOCK_HASH" PayloadStatusV1* = object status*: PayloadExecutionStatus latestValidHash*: Option[BlockHash] validationError*: Option[string] - # https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.9/src/engine/specification.md#forkchoicestatev1 + # https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.1/src/engine/specification.md#forkchoicestatev1 ForkchoiceStateV1* = object headBlockHash*: BlockHash safeBlockHash*: BlockHash finalizedBlockHash*: BlockHash - # https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.9/src/engine/specification.md#response-1 + # https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.1/src/engine/specification.md#response-1 PayloadID* = FixedBytes[8] ForkchoiceUpdatedResponse* = object payloadStatus*: PayloadStatusV1 payloadId*: Option[PayloadID] - # https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.9/src/engine/specification.md#transitionconfigurationv1 + # https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.1/src/engine/specification.md#transitionconfigurationv1 TransitionConfigurationV1* = object terminalTotalDifficulty*: UInt256 terminalBlockHash*: BlockHash terminalBlockNumber*: Quantity const - # https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.9/src/engine/specification.md#errors + # https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.1/src/engine/specification.md#errors engineApiParseError* = - 32700 engineApiInvalidRequest* = -32600 engineApiMethodNotFound* = -32601 @@ -54,5 +54,4 @@ const engineApiInternalError* = -32603 engineApiServerError* = -32000 engineApiUnknownPayload* = -38001 - engineApiInvalidForkchoiceState* = -38002 - engineApiInvalidPayloadAttributes* = -38003 + engineApiInvalidPayloadAttributes* = -38002 diff --git a/vendor/nim-web3/web3/ethcallsigs.nim b/vendor/nim-web3/web3/ethcallsigs.nim index e90b61461..f42af907f 100644 --- a/vendor/nim-web3/web3/ethcallsigs.nim +++ b/vendor/nim-web3/web3/ethcallsigs.nim @@ -49,6 +49,7 @@ proc eth_getFilterChanges(filterId: string): JsonNode proc eth_getFilterLogs(filterId: string): JsonNode proc eth_getLogs(filterOptions: FilterOptions): seq[LogObject] proc eth_getLogs(filterOptions: JsonNode): JsonNode +proc eth_chainId(): Quantity proc eth_getWork(): seq[UInt256] proc eth_submitWork(nonce: int64, powHash: Uint256, mixDigest: Uint256): bool @@ -57,6 +58,11 @@ proc eth_subscribe(name: string, options: JsonNode): string proc eth_subscribe(name: string): string proc eth_unsubscribe(id: string) +proc eth_getProof( + address: Address, + slots: seq[UInt256], + blockId: BlockIdentifier): ProofResponse + proc shh_post(): string proc shh_version(message: WhisperPost): bool proc shh_newIdentity(): array[60, byte] diff --git a/vendor/nim-web3/web3/ethhexstrings.nim b/vendor/nim-web3/web3/ethhexstrings.nim index 2bf02e555..559e20ed0 100644 --- a/vendor/nim-web3/web3/ethhexstrings.nim +++ b/vendor/nim-web3/web3/ethhexstrings.nim @@ -1,4 +1,4 @@ -import strutils +import std/strutils type HexQuantityStr* = distinct string @@ -13,7 +13,7 @@ template stripLeadingZeros(value: string): string = cidx.inc value[cidx .. ^1] -proc encodeQuantity*(value: SomeUnsignedInt): string = +func encodeQuantity*(value: SomeUnsignedInt): string = var hValue = value.toHex.stripLeadingZeros result = "0x" & hValue @@ -30,19 +30,19 @@ func isHexChar*(c: char): bool = c notin {'A'..'F'}: false else: true -proc validate*(value: HexQuantityStr): bool = +func validate*(value: HexQuantityStr): bool = template strVal: untyped = value.string if not value.hasHexHeader: return false - # No leading zeros - if strVal[2] == '0': return false + # No leading zeros (but allow 0x0) + if strVal.len < 3 or (strVal.len > 3 and strVal[2] == '0'): return false for i in 2.. 1 and hexStr[0] == '0' and hexStr[1] in {'x', 'X'}: 2 else: 0 -proc strip0xPrefix*(s: string): string = +func strip0xPrefix*(s: string): string = let prefixLen = skip0xPrefix(s) if prefixLen != 0: s[prefixLen .. ^1] @@ -281,7 +299,7 @@ func fromHex*[minLen, maxLen](T: type DynamicBytes[minLen, maxLen], hexStr: stri template fromHex*[N](T: type FixedBytes[N], hexStr: string): T = T fromHex(distinctBase(T), hexStr) -proc toArray*[N](data: DynamicBytes[N, N]): array[N, byte] = +func toArray*[N](data: DynamicBytes[N, N]): array[N, byte] = copyMem(addr result[0], unsafeAddr distinctBase(data)[0], N) template bytes*(data: DynamicBytes): seq[byte] = diff --git a/vendor/nim-web3/web3/transaction_signing.nim b/vendor/nim-web3/web3/transaction_signing.nim index b9dea67d2..c71c9a0b5 100644 --- a/vendor/nim-web3/web3/transaction_signing.nim +++ b/vendor/nim-web3/web3/transaction_signing.nim @@ -3,7 +3,7 @@ import ethtypes, stew/byteutils, stint, eth/[common, keys, rlp], eth/common/transaction -proc signTransaction(tr: var Transaction, pk: PrivateKey) = +func signTransaction(tr: var Transaction, pk: PrivateKey) = let h = tr.txHashNoSignature let s = sign(pk, SkMessage(h.data)) @@ -15,7 +15,7 @@ proc signTransaction(tr: var Transaction, pk: PrivateKey) = tr.V = int64(v) + 27 # TODO! Complete this -proc encodeTransaction*(s: EthSend, pk: PrivateKey): string = +func encodeTransaction*(s: EthSend, pk: PrivateKey): string = var tr = Transaction(txType: TxLegacy) tr.gasLimit = GasInt(s.gas.get.uint64) tr.gasPrice = s.gasPrice.get diff --git a/vendor/nim-websock/.github/workflows/ci.yml b/vendor/nim-websock/.github/workflows/ci.yml index 229a72896..7b662ff4b 100644 --- a/vendor/nim-websock/.github/workflows/ci.yml +++ b/vendor/nim-websock/.github/workflows/ci.yml @@ -160,10 +160,6 @@ jobs: - name: Run tests run: | - if [[ "${{ matrix.target.os }}" == "windows" ]]; then - # https://github.com/status-im/nimbus-eth2/issues/3121 - export NIMFLAGS="-d:nimRawSetjmp" - fi nim --version nimble --version nimble install -y --depsOnly diff --git a/vendor/nim-websock/.gitignore b/vendor/nim-websock/.gitignore index b883f1fdc..f470f9c98 100644 --- a/vendor/nim-websock/.gitignore +++ b/vendor/nim-websock/.gitignore @@ -1 +1,4 @@ *.exe +nimcache +nimble.develop +nimble.paths diff --git a/vendor/nim-websock/Readme.md b/vendor/nim-websock/Readme.md index 9878816bd..2a94532fb 100644 --- a/vendor/nim-websock/Readme.md +++ b/vendor/nim-websock/Readme.md @@ -5,7 +5,9 @@ ![Github action](https://github.com/status-im/nim-websock/workflows/CI/badge.svg) This is an implementation of [Websocket](https://tools.ietf.org/html/rfc6455) protocol for -[Nim](https://nim-lang.org/). nim-websock have both client and server in regular ws and wss(secure) mode. +[Nim](https://nim-lang.org/) and [chronos](https://github.com/status-im/nim-chronos/). + +`nim-websock` includes both client and server in regular ws and wss(secure) mode. It also pass all autobahn tests [Autobahn summary report](https://status-im.github.io/nim-websock/). diff --git a/vendor/nim-websock/config.nims b/vendor/nim-websock/config.nims new file mode 100644 index 000000000..7c9db3205 --- /dev/null +++ b/vendor/nim-websock/config.nims @@ -0,0 +1,4 @@ +# begin Nimble config (version 1) +when fileExists("nimble.paths"): + include "nimble.paths" +# end Nimble config diff --git a/vendor/nim-websock/nim.cfg b/vendor/nim-websock/nim.cfg new file mode 100644 index 000000000..371f6d79d --- /dev/null +++ b/vendor/nim-websock/nim.cfg @@ -0,0 +1,5 @@ +# Avoid some rare stack corruption while using exceptions with a SEH-enabled +# toolchain: https://github.com/status-im/nimbus-eth2/issues/3121 +@if windows and not vcc: + --define:nimRawSetjmp +@end diff --git a/vendor/nim-websock/nimble.lock b/vendor/nim-websock/nimble.lock new file mode 100644 index 000000000..9616e9c3b --- /dev/null +++ b/vendor/nim-websock/nimble.lock @@ -0,0 +1,153 @@ +{ + "version": 1, + "packages": { + "unittest2": { + "version": "0.0.4", + "vcsRevision": "f180f596c88dfd266f746ed6f8dbebce39c824db", + "url": "https://github.com/status-im/nim-unittest2.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "fa309c41eaf6ef57895b9e603f2620a2f6e11780" + } + }, + "testutils": { + "version": "0.4.2", + "vcsRevision": "aa6e5216f4b4ab5aa971cdcdd70e1ec1203cedf2", + "url": "https://github.com/status-im/nim-testutils", + "downloadMethod": "git", + "dependencies": [ + "unittest2" + ], + "checksums": { + "sha1": "94427e0cce0e0c5841edcd3a6530b4e6b857a3cb" + } + }, + "stew": { + "version": "0.1.0", + "vcsRevision": "6ad35b876fb6ebe0dfee0f697af173acc47906ee", + "url": "https://github.com/status-im/nim-stew.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "46d58c4feb457f3241e3347778334e325dce5268" + } + }, + "bearssl": { + "version": "0.1.5", + "vcsRevision": "ba80e2a0d7ae8aab666cee013e38ff8d33a3e5e7", + "url": "https://github.com/status-im/nim-bearssl", + "downloadMethod": "git", + "dependencies": [ + "unittest2" + ], + "checksums": { + "sha1": "383abd5becc77bf8e365b780a29d20529e1d9c4c" + } + }, + "httputils": { + "version": "0.3.0", + "vcsRevision": "689da19e9e9cfff4ced85e2b25c6b2b5598ed079", + "url": "https://github.com/status-im/nim-http-utils.git", + "downloadMethod": "git", + "dependencies": [ + "stew" + ], + "checksums": { + "sha1": "4ad3ad68d13c50184180ab4b2eacc0bd7ed2ed44" + } + }, + "chronos": { + "version": "3.0.11", + "vcsRevision": "17fed89c99beac5a92d3668d0d3e9b0e4ac13936", + "url": "https://github.com/status-im/nim-chronos.git", + "downloadMethod": "git", + "dependencies": [ + "stew", + "bearssl", + "httputils", + "unittest2" + ], + "checksums": { + "sha1": "f6fffc87571e5f76af2a77c4ebcc0e00909ced4e" + } + }, + "faststreams": { + "version": "0.3.0", + "vcsRevision": "1b561a9e71b6bdad1c1cdff753418906037e9d09", + "url": "https://github.com/status-im/nim-faststreams.git", + "downloadMethod": "git", + "dependencies": [ + "stew", + "testutils", + "chronos", + "unittest2" + ], + "checksums": { + "sha1": "97edf9797924af48566a0af8267203dc21d80c77" + } + }, + "serialization": { + "version": "0.1.0", + "vcsRevision": "fcd0eadadde0ee000a63df8ab21dc4e9f015a790", + "url": "https://github.com/status-im/nim-serialization.git", + "downloadMethod": "git", + "dependencies": [ + "faststreams", + "unittest2", + "stew" + ], + "checksums": { + "sha1": "fef59519892cac70cccd81b612085caaa5e3e6cf" + } + }, + "json_serialization": { + "version": "0.1.0", + "vcsRevision": "c5f0e2465e8375dfc7aa0f56ccef67cb680bc6b0", + "url": "https://github.com/status-im/nim-json-serialization.git", + "downloadMethod": "git", + "dependencies": [ + "serialization", + "stew" + ], + "checksums": { + "sha1": "d89d79d0679a3a41b350e3ad4be56c0308cc5ec6" + } + }, + "chronicles": { + "version": "0.10.2", + "vcsRevision": "1682096306ddba8185dcfac360a8c3f952d721e4", + "url": "https://github.com/status-im/nim-chronicles.git", + "downloadMethod": "git", + "dependencies": [ + "testutils", + "json_serialization" + ], + "checksums": { + "sha1": "9a5bebb76b0f7d587a31e621d260119279e91c76" + } + }, + "zlib": { + "version": "0.1.0", + "vcsRevision": "74cdeb54b21bededb5a515d36f608bc1850555a2", + "url": "https://github.com/status-im/nim-zlib", + "downloadMethod": "git", + "dependencies": [ + "stew" + ], + "checksums": { + "sha1": "01d330dc4c1924e56b1559ee73bc760e526f635c" + } + }, + "nimcrypto": { + "version": "0.5.4", + "vcsRevision": "a5742a9a214ac33f91615f3862c7b099aec43b00", + "url": "https://github.com/cheatfate/nimcrypto", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "f76c87707cd4e96355b8bb6ef27e7f8b0aac1e08" + } + } + } +} \ No newline at end of file diff --git a/vendor/nim-websock/tests/testcommon.nim b/vendor/nim-websock/tests/all_tests.nim similarity index 100% rename from vendor/nim-websock/tests/testcommon.nim rename to vendor/nim-websock/tests/all_tests.nim diff --git a/vendor/nim-websock/tests/extensions/testcompression.nim b/vendor/nim-websock/tests/extensions/testcompression.nim index 72dc0d5c3..e6b2208f5 100644 --- a/vendor/nim-websock/tests/extensions/testcompression.nim +++ b/vendor/nim-websock/tests/extensions/testcompression.nim @@ -1,5 +1,5 @@ ## nim-websock -## Copyright (c) 2021 Status Research & Development GmbH +## Copyright (c) 2021-2022 Status Research & Development GmbH ## Licensed under either of ## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) ## * MIT license ([LICENSE-MIT](LICENSE-MIT)) @@ -8,8 +8,7 @@ ## those terms. import std/os -import pkg/[chronos, stew/io2] -import pkg/asynctest/unittest2 +import pkg/[chronos/unittest2/asynctests, stew/io2] import ../../websock/websock import ../../websock/extensions/compression/deflate @@ -17,15 +16,17 @@ const dataFolder = "tests" / "extensions" / "data" suite "permessage deflate compression": - var server: HttpServer - let address = initTAddress("127.0.0.1:8888") - let deflateFactory = deflateFactory() + setup: + var server: HttpServer + let address = initTAddress("127.0.0.1:8888") + let deflateFactory = deflateFactory() teardown: - server.stop() - await server.closeWait() + if server != nil: + server.stop() + waitFor server.closeWait() - test "text compression": + asyncTest "text compression": let textData = io2.readAllBytes(dataFolder / "alice29.txt").get() proc handle(request: HttpRequest) {.async.} = let server = WSServer.new( @@ -66,7 +67,7 @@ suite "permessage deflate compression": check textData == recvData await client.close() - test "binary data compression": + asyncTest "binary data compression": let binaryData = io2.readAllBytes(dataFolder / "fireworks.jpg").get() proc handle(request: HttpRequest) {.async.} = let server = WSServer.new( diff --git a/vendor/nim-websock/tests/extensions/testexts.nim b/vendor/nim-websock/tests/extensions/testexts.nim index fa7b1c3f6..6fd9661a0 100644 --- a/vendor/nim-websock/tests/extensions/testexts.nim +++ b/vendor/nim-websock/tests/extensions/testexts.nim @@ -1,5 +1,5 @@ ## nim-websock -## Copyright (c) 2021 Status Research & Development GmbH +## Copyright (c) 2021-2022 Status Research & Development GmbH ## Licensed under either of ## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) ## * MIT license ([LICENSE-MIT](LICENSE-MIT)) @@ -7,22 +7,23 @@ ## This file may not be copied, modified, or distributed except according to ## those terms. -import pkg/[chronos, stew/byteutils] -import pkg/asynctest/unittest2 +import pkg/[chronos/unittest2/asynctests, stew/byteutils] import ./base64ext, ./hexext import ../../websock/websock, ../helpers suite "multiple extensions flow": - var server: HttpServer - let address = initTAddress("127.0.0.1:8888") - let hexFactory = hexFactory() - let base64Factory = base64Factory(padding = true) + setup: + var server: HttpServer + let address = initTAddress("127.0.0.1:8888") + let hexFactory = hexFactory() + let base64Factory = base64Factory(padding = true) teardown: - server.stop() - await server.closeWait() + if server != nil: + server.stop() + waitFor server.closeWait() - test "hex to base64 ext flow": + asyncTest "hex to base64 ext flow": let testData = "hello world" proc handle(request: HttpRequest) {.async.} = let server = WSServer.new( @@ -54,7 +55,7 @@ suite "multiple extensions flow": check testData.toBytes() == res await client.close() - test "base64 to hex ext flow": + asyncTest "base64 to hex ext flow": let testData = "hello world" proc handle(request: HttpRequest) {.async.} = let server = WSServer.new( diff --git a/vendor/nim-websock/tests/testextutils.nim b/vendor/nim-websock/tests/testextutils.nim index 957378cac..8639d94b8 100644 --- a/vendor/nim-websock/tests/testextutils.nim +++ b/vendor/nim-websock/tests/testextutils.nim @@ -8,8 +8,7 @@ ## those terms. import - pkg/chronos, - pkg/asynctest/unittest2, + unittest2, ../websock/extensions suite "extension parser": diff --git a/vendor/nim-websock/tests/testframes.nim b/vendor/nim-websock/tests/testframes.nim index cb0f506b6..d7766b747 100644 --- a/vendor/nim-websock/tests/testframes.nim +++ b/vendor/nim-websock/tests/testframes.nim @@ -7,8 +7,9 @@ ## This file may not be copied, modified, or distributed except according to ## those terms. -import pkg/stew/byteutils -import pkg/asynctest/unittest2 +import + pkg/stew/byteutils, + pkg/chronos/unittest2/asynctests include ../websock/frame include ../websock/utils @@ -16,10 +17,10 @@ include ../websock/utils # TODO: Fix Test. suite "Test data frames": + setup: + var maskKey: array[4, char] - var maskKey: array[4, char] - - test "# 7bit length text": + asyncTest "# 7bit length text": check (await Frame( fin: false, rsv1: false, @@ -30,7 +31,7 @@ suite "Test data frames": data: toBytes("hi there") ).encode()) == toBytes("\1\8hi there") - test "# 7bit length text fin bit": + asyncTest "# 7bit length text fin bit": check (await Frame( fin: true, rsv1: false, @@ -42,7 +43,7 @@ suite "Test data frames": maskKey: maskKey ).encode()) == toBytes("\129\8hi there") - test "# 7bit length binary": + asyncTest "# 7bit length binary": check (await Frame( fin: false, rsv1: false, @@ -54,7 +55,7 @@ suite "Test data frames": maskKey: maskKey ).encode()) == toBytes("\2\8hi there") - test "# 7bit length binary fin bit": + asyncTest "# 7bit length binary fin bit": check (await Frame( fin: true, rsv1: false, @@ -66,7 +67,7 @@ suite "Test data frames": maskKey: maskKey ).encode()) == toBytes("\130\8hi there") - test "# 7bit length continuation": + asyncTest "# 7bit length continuation": check (await Frame( fin: false, rsv1: false, @@ -78,7 +79,7 @@ suite "Test data frames": maskKey: maskKey ).encode()) == toBytes("\0\8hi there") - test "# 7+16 length text": + asyncTest "# 7+16 length text": var data = "" for i in 0..32: data.add "How are you this is the payload!!!" @@ -94,7 +95,7 @@ suite "Test data frames": maskKey: maskKey ).encode()) == toBytes("\1\126\4\98" & data) - test "# 7+16 length text fin bit": + asyncTest "# 7+16 length text fin bit": var data = "" for i in 0..32: data.add "How are you this is the payload!!!" @@ -110,7 +111,7 @@ suite "Test data frames": maskKey: maskKey ).encode()) == toBytes("\1\126\4\98" & data) - test "# 7+16 length binary": + asyncTest "# 7+16 length binary": var data = "" for i in 0..32: data.add "How are you this is the payload!!!" @@ -126,7 +127,7 @@ suite "Test data frames": maskKey: maskKey ).encode()) == toBytes("\2\126\4\98" & data) - test "# 7+16 length binary fin bit": + asyncTest "# 7+16 length binary fin bit": var data = "" for i in 0..32: data.add "How are you this is the payload!!!" @@ -142,7 +143,7 @@ suite "Test data frames": maskKey: maskKey ).encode()) == toBytes("\130\126\4\98" & data) - test "# 7+16 length continuation": + asyncTest "# 7+16 length continuation": var data = "" for i in 0..32: data.add "How are you this is the payload!!!" @@ -158,7 +159,7 @@ suite "Test data frames": maskKey: maskKey ).encode()) == toBytes("\0\126\4\98" & data) - test "# 7+64 length text": + asyncTest "# 7+64 length text": var data = "" for i in 0..3200: data.add "How are you this is the payload!!!" @@ -174,7 +175,7 @@ suite "Test data frames": maskKey: maskKey ).encode()) == toBytes("\1\127\0\0\0\0\0\1\169\34" & data) - test "# 7+64 length fin bit": + asyncTest "# 7+64 length fin bit": var data = "" for i in 0..3200: data.add "How are you this is the payload!!!" @@ -190,7 +191,7 @@ suite "Test data frames": maskKey: maskKey ).encode()) == toBytes("\129\127\0\0\0\0\0\1\169\34" & data) - test "# 7+64 length binary": + asyncTest "# 7+64 length binary": var data = "" for i in 0..3200: data.add "How are you this is the payload!!!" @@ -206,7 +207,7 @@ suite "Test data frames": maskKey: maskKey ).encode()) == toBytes("\2\127\0\0\0\0\0\1\169\34" & data) - test "# 7+64 length binary fin bit": + asyncTest "# 7+64 length binary fin bit": var data = "" for i in 0..3200: data.add "How are you this is the payload!!!" @@ -222,7 +223,7 @@ suite "Test data frames": maskKey: maskKey ).encode()) == toBytes("\130\127\0\0\0\0\0\1\169\34" & data) - test "# 7+64 length binary": + asyncTest "# 7+64 length binary": var data = "" for i in 0..3200: data.add "How are you this is the payload!!!" @@ -238,7 +239,7 @@ suite "Test data frames": maskKey: maskKey ).encode()) == toBytes("\0\127\0\0\0\0\0\1\169\34" & data) - test "# masking": + asyncTest "# masking": let data = (await Frame( fin: true, rsv1: false, @@ -253,10 +254,10 @@ suite "Test data frames": check data == toBytes("\129\136\207\216\5e\167\177%\17\167\189w\0") suite "Test control frames": + setup: + var maskKey: array[4, char] - var maskKey: array[4, char] - - test "Close": + asyncTest "Close": check (await Frame( fin: true, rsv1: false, @@ -268,7 +269,7 @@ suite "Test control frames": maskKey: maskKey ).encode()) == toBytes("\136\10\3\232hi there") - test "Ping": + asyncTest "Ping": check (await Frame( fin: false, rsv1: false, @@ -279,7 +280,7 @@ suite "Test control frames": maskKey: maskKey ).encode()) == toBytes("\9\0") - test "Pong": + asyncTest "Pong": check (await Frame( fin: false, rsv1: false, diff --git a/vendor/nim-websock/tests/testhooks.nim b/vendor/nim-websock/tests/testhooks.nim index 1119bdb5d..a8a8ce4fa 100644 --- a/vendor/nim-websock/tests/testhooks.nim +++ b/vendor/nim-websock/tests/testhooks.nim @@ -1,5 +1,5 @@ ## nim-websock -## Copyright (c) 2021 Status Research & Development GmbH +## Copyright (c) 2021-2022 Status Research & Development GmbH ## Licensed under either of ## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) ## * MIT license ([LICENSE-MIT](LICENSE-MIT)) @@ -7,13 +7,10 @@ ## This file may not be copied, modified, or distributed except according to ## those terms. -import std/strutils import pkg/[ httputils, - chronos, - chronicles, - stew/byteutils, - asynctest/unittest2] + chronos/unittest2/asynctests, + ] import ../websock/websock @@ -96,16 +93,18 @@ proc serverHookWithCode(request: HttpRequest): Hook = ) suite "Test Hooks": - var - server: HttpServer - goodCP = goodClientHook() - badCP = badClientHook() + setup: + var + server: HttpServer + goodCP = goodClientHook() + badCP = badClientHook() teardown: - server.stop() - await server.closeWait() + if server != nil: + server.stop() + waitFor server.closeWait() - test "client with valid token": + asyncTest "client with valid token": proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath let @@ -129,7 +128,7 @@ suite "Test Hooks": check TokenHook(goodCP).token == "accept" await session.stream.closeWait() - test "client with bad token": + asyncTest "client with bad token": proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath let @@ -153,7 +152,7 @@ suite "Test Hooks": check TokenHook(badCP).token == "reject" await session.stream.closeWait() - test "server hook with code get good client": + asyncTest "server hook with code get good client": proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath let @@ -177,7 +176,7 @@ suite "Test Hooks": check TokenHook(goodCP).token == "accept" await session.stream.closeWait() - test "server hook with code get bad client": + asyncTest "server hook with code get bad client": proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath let diff --git a/vendor/nim-websock/tests/testutf8.nim b/vendor/nim-websock/tests/testutf8.nim index dcea2c9bf..01aab1842 100644 --- a/vendor/nim-websock/tests/testutf8.nim +++ b/vendor/nim-websock/tests/testutf8.nim @@ -11,8 +11,7 @@ import std/[strutils], pkg/[ stew/byteutils, - asynctest/unittest2, - chronos, + chronos/unittest2/asynctests, chronicles ], ../websock/[websock, utf8dfa] @@ -79,15 +78,16 @@ proc waitForClose(ws: WSSession) {.async.} = trace "Closing websocket" suite "UTF-8 validator in action": - - var server: HttpServer - let address = initTAddress("127.0.0.1:8888") + setup: + var server: HttpServer + let address = initTAddress("127.0.0.1:8888") teardown: - server.stop() - await server.closeWait() + if server != nil: + server.stop() + waitFor server.closeWait() - test "valid UTF-8 sequence": + asyncTest "valid UTF-8 sequence": let testData = "hello world" proc handle(request: HttpRequest) {.async.} = check request.uri.path == "/ws" @@ -117,7 +117,7 @@ suite "UTF-8 validator in action": await session.send(testData) await session.close() - test "valid UTF-8 sequence in close reason": + asyncTest "valid UTF-8 sequence in close reason": let testData = "hello world" let closeReason = "i want to close" proc handle(request: HttpRequest) {.async.} = @@ -158,7 +158,7 @@ suite "UTF-8 validator in action": await session.send(testData) await session.close(reason = closeReason) - test "invalid UTF-8 sequence": + asyncTest "invalid UTF-8 sequence": let testData = "hello world\xc0\xaf" proc handle(request: HttpRequest) {.async.} = check request.uri.path == "/ws" @@ -183,7 +183,7 @@ suite "UTF-8 validator in action": expect WSInvalidUTF8: let data = await session.recvMsg() - test "invalid UTF-8 sequence close code": + asyncTest "invalid UTF-8 sequence close code": let closeReason = "i want to close\xc0\xaf" proc handle(request: HttpRequest) {.async.} = check request.uri.path == "/ws" diff --git a/vendor/nim-websock/tests/testwebsockets.nim b/vendor/nim-websock/tests/testwebsockets.nim index bbc28f9c4..db10082ff 100644 --- a/vendor/nim-websock/tests/testwebsockets.nim +++ b/vendor/nim-websock/tests/testwebsockets.nim @@ -1,5 +1,5 @@ ## nim-websock -## Copyright (c) 2021 Status Research & Development GmbH +## Copyright (c) 2021-2022 Status Research & Development GmbH ## Licensed under either of ## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) ## * MIT license ([LICENSE-MIT](LICENSE-MIT)) @@ -10,10 +10,9 @@ import std/strutils import pkg/[ httputils, - chronos, + chronos/unittest2/asynctests, chronicles, - stew/byteutils, - asynctest/unittest2] + stew/byteutils] import ../websock/websock @@ -22,15 +21,16 @@ import ./helpers let address = initTAddress("127.0.0.1:8888") suite "Test handshake": - - var - server: HttpServer + setup: + var + server: HttpServer teardown: - server.stop() - await server.closeWait() + if server != nil: + server.stop() + waitFor server.closeWait() - test "Should not select incorrect protocol": + asyncTest "Should not select incorrect protocol": proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath let @@ -50,7 +50,7 @@ suite "Test handshake": check session.proto == "" await session.stream.closeWait() - test "Test for incorrect version": + asyncTest "Test for incorrect version": proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath let server = WSServer.new(protos = ["ws"]) @@ -68,7 +68,7 @@ suite "Test handshake": address = initTAddress("127.0.0.1:8888"), version = 14) - test "Test for client headers": + asyncTest "Test for client headers": proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath check request.headers.getString("Connection").toUpperAscii() == @@ -90,7 +90,7 @@ suite "Test handshake": expect WSFailedUpgradeError: discard await connectClient() - test "Test for incorrect scheme": + asyncTest "Test for incorrect scheme": let uri = "wx://127.0.0.1:8888/ws" expect WSWrongUriSchemeError: discard await WebSocket.connect( @@ -98,14 +98,16 @@ suite "Test handshake": protocols = @["proto"]) suite "Test transmission": - var - server: HttpServer + setup: + var + server: HttpServer teardown: - server.stop() - await server.closeWait() + if server != nil: + server.stop() + waitFor server.closeWait() - test "Server - test reading simple frame": + asyncTest "Server - asyncTest reading simple frame": let testString = "Hello!" proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath @@ -126,7 +128,7 @@ suite "Test transmission": await session.send(testString) await session.close() - test "Send text message message with payload of length 65535": + asyncTest "Send text message message with payload of length 65535": let testString = rndStr(65535) proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath @@ -145,7 +147,7 @@ suite "Test transmission": await session.send(testString) await session.close() - test "Client - test reading simple frame": + asyncTest "Client - asyncTest reading simple frame": let testString = "Hello!" proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath @@ -166,15 +168,16 @@ suite "Test transmission": await waitForClose(session) suite "Test ping-pong": - - var - server: HttpServer + setup: + var + server: HttpServer teardown: - server.stop() - await server.closeWait() + if server != nil: + server.stop() + waitFor server.closeWait() - test "Server - test ping-pong control messages": + asyncTest "Server - asyncTest ping-pong control messages": var ping, pong = false proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath @@ -204,7 +207,7 @@ suite "Test ping-pong": ping pong - test "Client - test ping-pong control messages": + asyncTest "Client - asyncTest ping-pong control messages": var ping, pong = false proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath @@ -234,7 +237,7 @@ suite "Test ping-pong": await session.ping() await session.close() - test "Send ping with small text payload": + asyncTest "Send ping with small text payload": let testData = toBytes("Hello, world!") var ping, pong = false proc handle(request: HttpRequest) {.async.} = @@ -265,7 +268,7 @@ suite "Test ping-pong": ping pong - test "Test ping payload message length": + asyncTest "Test ping payload message length": proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath let server = WSServer.new(protos = ["proto"]) @@ -287,15 +290,16 @@ suite "Test ping-pong": await session.close() suite "Test framing": - - var - server: HttpServer + setup: + var + server: HttpServer teardown: - server.stop() - await server.closeWait() + if server != nil: + server.stop() + waitFor server.closeWait() - test "should split message into frames": + asyncTest "should split message into frames": let testString = "1234567890" proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath @@ -328,7 +332,7 @@ suite "Test framing": await session.send(testString) await session.close() - test "should fail to read past max message size": + asyncTest "should fail to read past max message size": let testString = "1234567890" proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath @@ -349,15 +353,16 @@ suite "Test framing": await waitForClose(session) suite "Test Closing": - - var - server: HttpServer + setup: + var + server: HttpServer teardown: - server.stop() - await server.closeWait() + if server != nil: + server.stop() + waitFor server.closeWait() - test "Server closing": + asyncTest "Server closing": proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath let server = WSServer.new(protos = ["proto"]) @@ -373,7 +378,7 @@ suite "Test Closing": await waitForClose(session) check session.readyState == ReadyState.Closed - test "Server closing with status": + asyncTest "Server closing with status": proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath @@ -415,7 +420,7 @@ suite "Test Closing": await waitForClose(session) check session.readyState == ReadyState.Closed - test "Client closing": + asyncTest "Client closing": proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath let server = WSServer.new(protos = ["proto"]) @@ -430,7 +435,7 @@ suite "Test Closing": let session = await connectClient() await session.close() - test "Client closing with status": + asyncTest "Client closing with status": proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath proc closeServer(status: StatusCodes, reason: string): CloseResult{.gcsafe, @@ -470,7 +475,7 @@ suite "Test Closing": await session.close() check session.readyState == ReadyState.Closed - test "Mutual closing": + asyncTest "Mutual closing": proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath let server = WSServer.new(protos = ["proto"]) @@ -487,7 +492,7 @@ suite "Test Closing": await waitForClose(session) check session.readyState == ReadyState.Closed - test "Server closing with valid close code 3999": + asyncTest "Server closing with valid close code 3999": proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath let server = WSServer.new(protos = ["proto"]) @@ -514,7 +519,7 @@ suite "Test Closing": await waitForClose(session) - test "Client closing with valid close code 3999": + asyncTest "Client closing with valid close code 3999": proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath proc closeServer(status: StatusCodes, reason: string): CloseResult{.gcsafe, @@ -541,7 +546,7 @@ suite "Test Closing": let session = await connectClient() await session.close(code = StatusCodes(3999)) - test "Server closing with Payload of length 2": + asyncTest "Server closing with Payload of length 2": proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath @@ -559,7 +564,7 @@ suite "Test Closing": let session = await connectClient() await waitForClose(session) - test "Client closing with Payload of length 2": + asyncTest "Client closing with Payload of length 2": proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath @@ -579,14 +584,16 @@ suite "Test Closing": await session.close(reason = "HH") suite "Test Payload": - var - server: HttpServer + setup: + var + server: HttpServer teardown: - server.stop() - await server.closeWait() + if server != nil: + server.stop() + waitFor server.closeWait() - test "Test payload of length 0": + asyncTest "Test payload of length 0": let emptyStr = "" proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath @@ -617,7 +624,7 @@ suite "Test Payload": await session.close() - test "Test multiple payloads of length 0": + asyncTest "Test multiple payloads of length 0": let emptyStr = "" proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath @@ -655,7 +662,7 @@ suite "Test Payload": await session.close() - test "Send two fragments": + asyncTest "Send two fragments": var ping, pong = false let testString = "1234567890" let msg = toBytes(testString) @@ -709,7 +716,7 @@ suite "Test Payload": await session.close() - test "Send two fragments with a ping with payload in-between": + asyncTest "Send two fragments with a ping with payload in-between": var ping, pong = false let testString = "1234567890" let msg = toBytes(testString) @@ -774,13 +781,13 @@ suite "Test Payload": ping pong - test "Send text message with multiple frames": + asyncTest "Send text message with multiple frames": const FrameSize = 3000 - let testData = rndStr(FrameSize * 3) + let testData = rndStr(FrameSize * 3 + 100) proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath - let server = WSServer.new(protos = ["proto"]) + let server = WSServer.new(protos = ["proto"], frameSize = FrameSize) let ws = await server.handleRequest(request) let res = await ws.recvMsg() @@ -807,14 +814,16 @@ suite "Test Payload": ws.binary == false suite "Test Binary message with Payload": - var - server: HttpServer + setup: + var + server: HttpServer teardown: - server.stop() - await server.closeWait() + if server != nil: + server.stop() + waitFor server.closeWait() - test "Test binary message with single empty payload message": + asyncTest "Test binary message with single empty payload message": let emptyData = newSeq[byte](0) proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath @@ -838,7 +847,7 @@ suite "Test Binary message with Payload": await session.send(emptyData, Opcode.Binary) await session.close() - test "Test binary message with multiple empty payload": + asyncTest "Test binary message with multiple empty payload": let emptyData = newSeq[byte](0) proc handle(request: HttpRequest) {.async.} = check request.uri.path == WSPath @@ -865,7 +874,7 @@ suite "Test Binary message with Payload": await session.send(emptyData, Opcode.Binary) await session.close() - test "Send binary data with small text payload": + asyncTest "Send binary data with small text payload": let testData = rndBin(10) trace "testData", testData = testData var ping, pong = false @@ -900,7 +909,7 @@ suite "Test Binary message with Payload": await session.send(testData, Opcode.Binary) await session.close() - test "Send binary message message with payload of length 125": + asyncTest "Send binary message message with payload of length 125": let testData = rndBin(125) var ping, pong = false proc handle(request: HttpRequest) {.async.} = @@ -934,7 +943,7 @@ suite "Test Binary message with Payload": await session.send(testData, Opcode.Binary) await session.close() - test "Send binary message with multiple frames": + asyncTest "Send binary message with multiple frames": const FrameSize = 3000 let testData = rndBin(FrameSize * 3) proc handle(request: HttpRequest) {.async.} = @@ -974,62 +983,64 @@ suite "Test Binary message with Payload": ws.binary == true suite "Partial frames": - var - server: HttpServer + setup: + var + server: HttpServer + + proc lowLevelRecv( + senderFrameSize, receiverFrameSize, readChunkSize: int) {.async.} = + + const + howMuchWood = "How much wood could a wood chuck chuck ..." + + proc handle(request: HttpRequest) {.async.} = + check request.uri.path == WSPath + + let + server = WSServer.new(frameSize = receiverFrameSize) + ws = await server.handleRequest(request) + + var + res = newSeq[byte](howMuchWood.len) + pos = 0 + + while ws.readyState != ReadyState.Closed: + let read = await ws.recv(addr res[pos], min(res.len - pos, readChunkSize)) + pos += read + + if pos >= res.len: + break + + res.setLen(pos) + check res.len == howMuchWood.toBytes().len + check res == howMuchWood.toBytes() + await ws.waitForClose() + + server = createServer( + address = address, + handler = handle, + flags = {ReuseAddr}) + + let session = await connectClient( + address = address, + frameSize = senderFrameSize) + + await session.send(howMuchWood) + await session.close() teardown: - server.stop() - await server.closeWait() + if server != nil: + server.stop() + waitFor server.closeWait() - proc lowLevelRecv( - senderFrameSize, receiverFrameSize, readChunkSize: int) {.async.} = - - const - howMuchWood = "How much wood could a wood chuck chuck ..." - - proc handle(request: HttpRequest) {.async.} = - check request.uri.path == WSPath - - let - server = WSServer.new(frameSize = receiverFrameSize) - ws = await server.handleRequest(request) - - var - res = newSeq[byte](howMuchWood.len) - pos = 0 - - while ws.readyState != ReadyState.Closed: - let read = await ws.recv(addr res[pos], min(res.len - pos, readChunkSize)) - pos += read - - if pos >= res.len: - break - - res.setlen(pos) - check res.len == howMuchWood.toBytes().len - check res == howMuchWood.toBytes() - await ws.waitForClose() - - server = createServer( - address = address, - handler = handle, - flags = {ReuseAddr}) - - let session = await connectClient( - address = address, - frameSize = senderFrameSize) - - await session.send(howMuchWood) - await session.close() - - test "read in chunks less than sender frameSize": + asyncTest "read in chunks less than sender frameSize": await lowLevelRecv(7, 7, 5) - test "read in chunks greater than sender frameSize": + asyncTest "read in chunks greater than sender frameSize": await lowLevelRecv(3, 7, 5) - test "sender frameSize greater than receiver": + asyncTest "sender frameSize greater than receiver": await lowLevelRecv(7, 5, 5) - test "receiver frameSize greater than sender": + asyncTest "receiver frameSize greater than sender": await lowLevelRecv(7, 10, 5) diff --git a/vendor/nim-websock/websock.nimble b/vendor/nim-websock/websock.nimble index 4c553e76f..6fdff830d 100644 --- a/vendor/nim-websock/websock.nimble +++ b/vendor/nim-websock/websock.nimble @@ -19,28 +19,37 @@ requires "chronos >= 3.0.0" requires "httputils >= 0.2.0" requires "chronicles >= 0.10.2" requires "stew >= 0.1.0" -requires "asynctest >= 0.3.0 & < 0.4.0" requires "nimcrypto" requires "bearssl" requires "zlib" task test, "run tests": - let envNimflags = getEnv("NIMFLAGS") + let + envNimflags = getEnv("NIMFLAGS") + styleCheckStyle = + if (NimMajor, NimMinor) < (1, 6): + "hint" + else: + "error" + nimFlags = envNimFlags & + " --verbosity:0 --hints:off --hint:Name:on " & + "--styleCheck:usages --styleCheck:" & styleCheckStyle & + " -d:chronosStrictException" # dont't need to run it, only want to test if it is compileable - exec "nim c -c " & envNimflags & " --verbosity:0 --hints:off --hint:Name:on -d:chronicles_log_level=TRACE -d:chronicles_sinks:json --styleCheck:usages --styleCheck:hint ./tests/testcommon" + exec "nim c -c " & nimFlags & " -d:chronicles_log_level=TRACE -d:chronicles_sinks:json --styleCheck:usages --styleCheck:hint ./tests/all_tests" - exec "nim --hints:off c -r " & envNimflags & " --opt:speed -d:debug --verbosity:0 --hints:off -d:chronicles_log_level=INFO ./tests/testcommon.nim" - rmFile "./tests/testcommon" + exec "nim c -r " & nimFlags & " --opt:speed -d:debug -d:chronicles_log_level=INFO ./tests/all_tests.nim" + rmFile "./tests/all_tests" - exec "nim --hints:off c -r " & envNimflags & " --opt:speed -d:debug --verbosity:0 --hints:off -d:chronicles_log_level=INFO ./tests/testwebsockets.nim" + exec "nim c -r " & nimFlags & " --opt:speed -d:debug -d:chronicles_log_level=INFO ./tests/testwebsockets.nim" rmFile "./tests/testwebsockets" - exec "nim --hints:off -d:secure c -r " & envNimflags & " --opt:speed -d:debug --verbosity:0 --hints:off -d:chronicles_log_level=INFO ./tests/testwebsockets.nim" + exec "nim -d:secure c -r " & nimFlags & " --opt:speed -d:debug -d:chronicles_log_level=INFO ./tests/testwebsockets.nim" rmFile "./tests/testwebsockets" - exec "nim --hints:off -d:accepts c -r " & envNimflags & " --opt:speed -d:debug --verbosity:0 --hints:off -d:chronicles_log_level=INFO ./tests/testwebsockets.nim" + exec "nim -d:accepts c -r " & nimFlags & " --opt:speed -d:debug -d:chronicles_log_level=INFO ./tests/testwebsockets.nim" rmFile "./tests/testwebsockets" - exec "nim --hints:off -d:secure -d:accepts c -r " & envNimflags & " --opt:speed -d:debug --verbosity:0 --hints:off -d:chronicles_log_level=INFO ./tests/testwebsockets.nim" + exec "nim -d:secure -d:accepts c -r " & nimFlags & " --opt:speed -d:debug -d:chronicles_log_level=INFO ./tests/testwebsockets.nim" rmFile "./tests/testwebsockets" diff --git a/vendor/nim-websock/websock/extensions/compression/deflate.nim b/vendor/nim-websock/websock/extensions/compression/deflate.nim index c0d92d429..c4b4abf89 100644 --- a/vendor/nim-websock/websock/extensions/compression/deflate.nim +++ b/vendor/nim-websock/websock/extensions/compression/deflate.nim @@ -53,6 +53,22 @@ const ExtDeflateThreshold* = 1024 ExtDeflateDecompressLimit* = 10 shl 20 # 10mb +proc destroyExt(ext: DeflateExt) = + if ext.compCtxState != ContextState.Invalid: + # zlib.deflateEnd somehow return DATA_ERROR + # when compression succeed some cases. + # we forget to do something? + discard ext.compCtx.deflateEnd() + ext.compCtxState = ContextState.Invalid + + if ext.decompCtxState != ContextState.Invalid: + doAssert(ext.decompCtx.inflateEnd() == Z_OK) + ext.decompCtxState = ContextState.Invalid + +# Need to be declared early and not be generic to work with ARC/ORC +proc newDeflateExt: DeflateExt = + result.new(destroyExt) + proc concatParam(resp: var string, param: string) = resp.add "; " resp.add param @@ -327,18 +343,6 @@ method toHttpOptions(ext: DeflateExt): string = # using paramStr here is a bit clunky extID & ext.paramStr -proc destroyExt(ext: DeflateExt) = - if ext.compCtxState != ContextState.Invalid: - # zlib.deflateEnd somehow return DATA_ERROR - # when compression succeed some cases. - # we forget to do something? - discard ext.compCtx.deflateEnd() - ext.compCtxState = ContextState.Invalid - - if ext.decompCtxState != ContextState.Invalid: - doAssert(ext.decompCtx.inflateEnd() == Z_OK) - ext.decompCtxState = ContextState.Invalid - proc makeOffer( clientNoContextTakeOver: bool, clientMaxWindowBits: int): string = @@ -380,8 +384,7 @@ proc deflateFactory*( if resp.isErr: return err(resp.error) - var ext: DeflateExt - ext.new(destroyExt) + var ext = newDeflateExt() ext.name = extID ext.paramStr = resp.get() ext.opts = opts diff --git a/vendor/nim-websock/websock/extensions/extutils.nim b/vendor/nim-websock/websock/extensions/extutils.nim index 5a1a19e7d..f9eba0859 100644 --- a/vendor/nim-websock/websock/extensions/extutils.nim +++ b/vendor/nim-websock/websock/extensions/extutils.nim @@ -1,5 +1,5 @@ ## nim-websock -## Copyright (c) 2021 Status Research & Development GmbH +## Copyright (c) 2021-2022 Status Research & Development GmbH ## Licensed under either of ## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) ## * MIT license ([LICENSE-MIT](LICENSE-MIT)) @@ -137,7 +137,7 @@ proc parseExt*[T: BChar](data: openArray[T], output: var seq[AppExt]): bool = ext.params[^1].name = system.move(param.name) ext.params[^1].value = system.move(param.value) - if lex.tok notin {tkSemcol, tkComma, tkEof}: + if lex.tok notin {tkSemCol, tkComma, tkEof}: return false output.setLen(output.len + 1) diff --git a/vendor/nim-websock/websock/session.nim b/vendor/nim-websock/websock/session.nim index 70800df3b..f243318b6 100644 --- a/vendor/nim-websock/websock/session.nim +++ b/vendor/nim-websock/websock/session.nim @@ -1,5 +1,5 @@ ## nim-websock -## Copyright (c) 2021 Status Research & Development GmbH +## Copyright (c) 2021-2022 Status Research & Development GmbH ## Licensed under either of ## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) ## * MIT license ([LICENSE-MIT](LICENSE-MIT)) @@ -37,21 +37,21 @@ proc writeMessage*(ws: WSSession, let maxSize = ws.frameSize var i = 0 while ws.readyState notin {ReadyState.Closing}: - let len = min(data.len, maxSize) + let canSend = min(data.len - i, maxSize) let frame = Frame( - fin: if (len + i >= data.len): true else: false, + fin: if (canSend + i >= data.len): true else: false, rsv1: false, rsv2: false, rsv3: false, opcode: if i > 0: Opcode.Cont else: opcode, # fragments have to be `Continuation` frames mask: ws.masked, - data: data[i ..< len + i], + data: data[i ..< canSend + i], maskKey: maskKey) let encoded = await frame.encode(extensions) await ws.stream.writer.write(encoded) - i += len + i += canSend if i >= data.len: break @@ -153,7 +153,7 @@ proc handleClose*( code = StatusFulfilled reason = "" - case payLoad.len: + case payload.len: of 0: code = StatusNoStatus of 1: diff --git a/vendor/nim-websock/websock/utils.nim b/vendor/nim-websock/websock/utils.nim index 25772a362..c3504191f 100644 --- a/vendor/nim-websock/websock/utils.nim +++ b/vendor/nim-websock/websock/utils.nim @@ -7,35 +7,25 @@ ## This file may not be copied, modified, or distributed except according to ## those terms. -import bearssl -export bearssl +import bearssl/[rand] +export rand -## Random helpers: similar as in stdlib, but with BrHmacDrbgContext rng +## Random helpers: similar as in stdlib, but with HmacDrbgContext rng const randMax = 18_446_744_073_709_551_615'u64 type - Rng* = ref BrHmacDrbgContext + Rng* = ref HmacDrbgContext proc newRng*(): Rng = # You should only create one instance of the RNG per application / library # Ref is used so that it can be shared between components - # TODO consider moving to bearssl - var seeder = brPrngSeederSystem(nil) - if seeder == nil: - return nil - - var rng = Rng() - brHmacDrbgInit(addr rng[], addr sha256Vtable, nil, 0) - if seeder(addr rng.vtable) == 0: - return nil - - rng + HmacDrbgContext.new() proc rand*(rng: Rng, max: Natural): int = if max == 0: return 0 var x: uint64 while true: - brHmacDrbgGenerate(addr rng[], addr x, csize_t(sizeof(x))) + let x = rng[].generate(uint64) if x < randMax - (randMax mod (uint64(max) + 1'u64)): # against modulo bias return int(x mod (uint64(max) + 1'u64)) diff --git a/vendor/nim-zlib/.gitignore b/vendor/nim-zlib/.gitignore index 796b96d1c..cbf38223a 100644 --- a/vendor/nim-zlib/.gitignore +++ b/vendor/nim-zlib/.gitignore @@ -1 +1,3 @@ /build +nimble.develop +nimble.paths diff --git a/vendor/nim-zlib/config.nims b/vendor/nim-zlib/config.nims new file mode 100644 index 000000000..7c9db3205 --- /dev/null +++ b/vendor/nim-zlib/config.nims @@ -0,0 +1,4 @@ +# begin Nimble config (version 1) +when fileExists("nimble.paths"): + include "nimble.paths" +# end Nimble config diff --git a/vendor/nim-zlib/nimble.lock b/vendor/nim-zlib/nimble.lock new file mode 100644 index 000000000..e2e37bb60 --- /dev/null +++ b/vendor/nim-zlib/nimble.lock @@ -0,0 +1,15 @@ +{ + "version": 1, + "packages": { + "stew": { + "version": "0.1.0", + "vcsRevision": "6ad35b876fb6ebe0dfee0f697af173acc47906ee", + "url": "https://github.com/status-im/nim-stew.git", + "downloadMethod": "git", + "dependencies": [], + "checksums": { + "sha1": "46d58c4feb457f3241e3347778334e325dce5268" + } + } + } +} \ No newline at end of file diff --git a/vendor/nimbus-build-system/makefiles/targets.mk b/vendor/nimbus-build-system/makefiles/targets.mk index 296cfc89d..cf9d4b9c4 100644 --- a/vendor/nimbus-build-system/makefiles/targets.mk +++ b/vendor/nimbus-build-system/makefiles/targets.mk @@ -149,7 +149,7 @@ $(NIMBLE_DIR): git submodule foreach --recursive --quiet '$(CURDIR)/$(BUILD_SYSTEM_DIR)/scripts/create_nimble_link.sh "$$sm_path"' clean-cross: - + [[ -e vendor/nim-nat-traversal/vendor/miniupnp/miniupnpc ]] && "$(MAKE)" -C vendor/nim-nat-traversal/vendor/miniupnp/miniupnpc clean $(HANDLE_OUTPUT) || true + + [[ -e vendor/nim-nat-traversal/vendor/miniupnp/miniupnpc ]] && "$(MAKE)" -C vendor/nim-nat-traversal/vendor/miniupnp/miniupnpc CC=$(CC) clean $(HANDLE_OUTPUT) || true + [[ -e vendor/nim-nat-traversal/vendor/libnatpmp-upstream ]] && "$(MAKE)" -C vendor/nim-nat-traversal/vendor/libnatpmp-upstream CC=$(CC) clean $(HANDLE_OUTPUT) || true clean-common: clean-cross diff --git a/vendor/nimbus-build-system/scripts/env.sh b/vendor/nimbus-build-system/scripts/env.sh index 0a9df32e7..3a734cdac 100755 --- a/vendor/nimbus-build-system/scripts/env.sh +++ b/vendor/nimbus-build-system/scripts/env.sh @@ -66,6 +66,17 @@ add_submodule() { } $EXPORT_FUNC add_submodule +export NIMBUS_BUILD_SYSTEM=yes +echo "--noNimblePath" > nimbus-build-system.paths +for file in $(ls -d $PWD/vendor/*) +do + if [ -d "$file/src" ]; then + echo --path:"\"$file/src\"" + else + echo --path:"\"$file\"" + fi +done >> nimbus-build-system.paths + if [[ $# == 1 && $1 == "bash" ]]; then # the only way to change PS1 in a child shell, apparently # (we're not getting the original PS1 value in here, so set a complete and nice prompt) @@ -75,4 +86,3 @@ else # can't use "exec" here if we're getting function names as params "$@" fi - diff --git a/vendor/nimcrypto/.github/workflows/ci.yml b/vendor/nimcrypto/.github/workflows/ci.yml index 0929563ca..eca4f9f5f 100644 --- a/vendor/nimcrypto/.github/workflows/ci.yml +++ b/vendor/nimcrypto/.github/workflows/ci.yml @@ -11,49 +11,15 @@ jobs: target: - os: linux cpu: amd64 - nim_branch: devel - - os: linux - cpu: amd64 - nim_branch: v1.2.12 - - os: linux - cpu: amd64 - nim_branch: v1.0.10 - os: linux cpu: i386 - nim_branch: devel - - os: linux - cpu: i386 - nim_branch: v1.2.12 - - os: linux - cpu: i386 - nim_branch: v1.0.10 - os: macos cpu: amd64 - nim_branch: devel - - os: macos - cpu: amd64 - nim_branch: v1.2.12 - - os: macos - cpu: amd64 - nim_branch: v1.0.10 - os: windows cpu: amd64 - nim_branch: devel - - os: windows - cpu: amd64 - nim_branch: v1.2.12 - - os: windows - cpu: amd64 - nim_branch: v1.0.10 - os: windows cpu: i386 - nim_branch: devel - - os: windows - cpu: i386 - nim_branch: v1.2.12 - - os: windows - cpu: i386 - nim_branch: v1.0.10 + nim_branch: [version-1-0, version-1-2, version-1-4, version-1-6, devel] include: - target: os: linux @@ -65,11 +31,11 @@ jobs: os: windows builder: windows-2019 - name: '${{ matrix.target.os }}-${{ matrix.target.cpu }}-nim-${{ matrix.target.nim_branch }} (${{ matrix.branch }})' + name: '${{ matrix.target.os }}-${{ matrix.target.cpu }}-nim-${{ matrix.nim_branch }} (${{ matrix.branch }})' runs-on: ${{ matrix.builder }} env: - NIM_DIR: nim-${{ matrix.target.nim_branch }}-${{ matrix.target.cpu }} - NIM_BRANCH: ${{ matrix.target.nim_branch }} + NIM_DIR: nim-${{ matrix.nim_branch }}-${{ matrix.target.cpu }} + NIM_BRANCH: ${{ matrix.nim_branch }} NIM_ARCH: ${{ matrix.target.cpu }} steps: - name: Checkout nimcrypto @@ -133,12 +99,12 @@ jobs: - name: Restore Nim from cache if: > steps.nim-compiler-cache.outputs.cache-hit != 'true' && - matrix.target.nim_branch != 'devel' + matrix.nim_branch != 'devel' id: nim-compiler-cache uses: actions/cache@v2 with: - path: '${{ github.workspace }}/nim-${{ matrix.target.nim_branch }}-${{ matrix.target.cpu }}' - key: 'nim-${{ matrix.target.cpu }}-${{ matrix.target.nim_branch }}' + path: '${{ github.workspace }}/nim-${{ matrix.nim_branch }}-${{ matrix.target.cpu }}' + key: 'nim-${{ matrix.target.cpu }}-${{ matrix.nim_branch }}' - name: Build Nim and associated tools shell: bash @@ -160,5 +126,8 @@ jobs: shell: bash working-directory: nimcrypto run: | + gcc --version + nim --version + nimble --version nimble install -y nimble test diff --git a/vendor/nimcrypto/examples/cbc.nim b/vendor/nimcrypto/examples/cbc.nim index f93a70800..a881f5f9f 100644 --- a/vendor/nimcrypto/examples/cbc.nim +++ b/vendor/nimcrypto/examples/cbc.nim @@ -18,7 +18,7 @@ var aliceData = "Alice hidden secret" var aliceIv = "0123456789ABCDEF" block: - ## Nim's way API using openarray[byte]. + ## Nim's way API using openArray[byte]. var ectx, dctx: CBC[aes256] var key: array[aes256.sizeKey, byte] diff --git a/vendor/nimcrypto/examples/cfb.nim b/vendor/nimcrypto/examples/cfb.nim index acd9e3a21..5de843bef 100644 --- a/vendor/nimcrypto/examples/cfb.nim +++ b/vendor/nimcrypto/examples/cfb.nim @@ -18,7 +18,7 @@ var aliceData = "Alice hidden secret" var aliceIv = "0123456789ABCDEF" block: - ## Nim's way API using openarray[byte]. + ## Nim's way API using openArray[byte]. var ectx, dctx: CFB[aes256] var key: array[aes256.sizeKey, byte] diff --git a/vendor/nimcrypto/examples/ctr.nim b/vendor/nimcrypto/examples/ctr.nim index 7f8946f51..b12724306 100644 --- a/vendor/nimcrypto/examples/ctr.nim +++ b/vendor/nimcrypto/examples/ctr.nim @@ -18,7 +18,7 @@ var aliceData = "Alice hidden secret" var aliceIv = "0123456789ABCDEF" block: - ## Nim's way API using openarray[byte]. + ## Nim's way API using openArray[byte]. var ectx, dctx: CTR[aes256] var key: array[aes256.sizeKey, byte] diff --git a/vendor/nimcrypto/examples/ecb.nim b/vendor/nimcrypto/examples/ecb.nim index 7f4249b59..d0da681ba 100644 --- a/vendor/nimcrypto/examples/ecb.nim +++ b/vendor/nimcrypto/examples/ecb.nim @@ -14,7 +14,7 @@ var aliceKey = "Alice Key" var aliceData = "Alice hidden secret" block: - ## Nim's way API using openarray[byte]. + ## Nim's way API using openArray[byte]. var ectx, dctx: ECB[aes256] var key: array[aes256.sizeKey, byte] diff --git a/vendor/nimcrypto/examples/gcm.nim b/vendor/nimcrypto/examples/gcm.nim index 6af02e55a..9c2969192 100644 --- a/vendor/nimcrypto/examples/gcm.nim +++ b/vendor/nimcrypto/examples/gcm.nim @@ -19,7 +19,7 @@ var aliceData = "Alice hidden secret" var aliceIv = "0123456789ABCDEF" block: - ## Nim's way API using openarray[byte]. + ## Nim's way API using openArray[byte]. var ectx, dctx: GCM[aes256] var key: array[aes256.sizeKey, byte] diff --git a/vendor/nimcrypto/examples/ofb.nim b/vendor/nimcrypto/examples/ofb.nim index c314ec3f2..58c21fa85 100644 --- a/vendor/nimcrypto/examples/ofb.nim +++ b/vendor/nimcrypto/examples/ofb.nim @@ -18,7 +18,7 @@ var aliceData = "Alice hidden secret" var aliceIv = "0123456789ABCDEF" block: - ## Nim's way API using openarray[byte]. + ## Nim's way API using openArray[byte]. var ectx, dctx: OFB[aes256] var key: array[aes256.sizeKey, byte] diff --git a/vendor/nimcrypto/nimcrypto/bcmode.nim b/vendor/nimcrypto/nimcrypto/bcmode.nim index d00d286c0..c0b8aaf50 100644 --- a/vendor/nimcrypto/nimcrypto/bcmode.nim +++ b/vendor/nimcrypto/nimcrypto/bcmode.nim @@ -89,7 +89,7 @@ template sizeKey*[T](ctx: ECB[T]): int = mixin sizeKey sizeKey(ctx.cipher) -proc init*[T](ctx: var ECB[T], key: openarray[byte]) {.inline.} = +proc init*[T](ctx: var ECB[T], key: openArray[byte]) {.inline.} = ## Initialize ``ECB[T]`` with encryption key ``key``. ## ## This procedure will not perform any additional padding for encryption @@ -103,7 +103,7 @@ proc init*[T](ctx: var ECB[T], key: openarray[byte]) {.inline.} = assert(len(key) >= ctx.sizeKey()) init(ctx.cipher, key) -proc init*[T](ctx: var ECB[T], key: openarray[char]) {.inline.} = +proc init*[T](ctx: var ECB[T], key: openArray[char]) {.inline.} = ## Initialize ``ECB[T]`` with encryption key ``key``. ## ## This procedure will not perform any additional padding for encryption @@ -127,8 +127,8 @@ proc clear*[T](ctx: var ECB[T]) {.inline.} = ## Clear ``ECB[T]`` context ``ctx``. burnMem(ctx) -proc encrypt*[T](ctx: var ECB[T], input: openarray[byte], - output: var openarray[byte]) {.inline.} = +proc encrypt*[T](ctx: var ECB[T], input: openArray[byte], + output: var openArray[byte]) {.inline.} = ## Encrypt array of data ``input`` and store encrypted data to array ## ``output`` using ``ECB[T]`` context ``ctx``. ## @@ -147,8 +147,8 @@ proc encrypt*[T](ctx: var ECB[T], input: openarray[byte], output.toOpenArray(offset, offset + ctx.sizeBlock() - 1)) offset = offset + ctx.sizeBlock() -proc encrypt*[T](ctx: var ECB[T], input: openarray[char], - output: var openarray[char]) {.inline.} = +proc encrypt*[T](ctx: var ECB[T], input: openArray[char], + output: var openArray[char]) {.inline.} = ## Encrypt array of data ``input`` and store encrypted data to array ## ``output`` using ``ECB[T]`` context ``ctx``. ## @@ -161,8 +161,8 @@ proc encrypt*[T](ctx: var ECB[T], input: openarray[char], encrypt(ctx, input.toOpenArrayByte(0, len(input) - 1), output.toOpenArrayByte(0, len(output) - 1)) -proc decrypt*[T](ctx: var ECB[T], input: openarray[byte], - output: var openarray[byte]) {.inline.} = +proc decrypt*[T](ctx: var ECB[T], input: openArray[byte], + output: var openArray[byte]) {.inline.} = ## Decrypt array of data ``input`` and store decrypted data to array ## ``output`` using ``ECB[T]`` context ``ctx``. ## @@ -181,8 +181,8 @@ proc decrypt*[T](ctx: var ECB[T], input: openarray[byte], output.toOpenArray(offset, offset + ctx.sizeBlock() - 1)) offset = offset + ctx.sizeBlock() -proc decrypt*[T](ctx: var ECB[T], input: openarray[char], - output: var openarray[char]) {.inline.} = +proc decrypt*[T](ctx: var ECB[T], input: openArray[char], + output: var openArray[char]) {.inline.} = ## Decrypt array of data ``input`` and store decrypted data to array ## ``output`` using ``ECB[T]`` context ``ctx``. ## @@ -243,7 +243,7 @@ template sizeKey*[T](ctx: CBC[T]): int = mixin sizeKey sizeKey(ctx.cipher) -proc init*[T](ctx: var CBC[T], key: openarray[byte], iv: openarray[byte]) = +proc init*[T](ctx: var CBC[T], key: openArray[byte], iv: openArray[byte]) = ## Initialize ``CBC[T]`` with encryption key ``key`` and initial vector (IV) ## ``iv``. ## @@ -261,7 +261,7 @@ proc init*[T](ctx: var CBC[T], key: openarray[byte], iv: openarray[byte]) = init(ctx.cipher, key) ctx.iv[0 ..< ctx.sizeBlock()] = iv.toOpenArray(0, ctx.sizeBlock() - 1) -proc init*[T](ctx: var CBC[T], key: openarray[char], iv: openarray[char]) = +proc init*[T](ctx: var CBC[T], key: openArray[char], iv: openArray[char]) = ## Initialize ``CBC[T]`` with encryption key ``key`` and initial vector (IV) ## ``iv``. ## @@ -294,8 +294,8 @@ proc clear*[T](ctx: var CBC[T]) {.inline.} = ## Clear ``CBC[T]`` context ``ctx``. burnMem(ctx) -proc encrypt*[T](ctx: var CBC[T], input: openarray[byte], - output: var openarray[byte]) {.inline.} = +proc encrypt*[T](ctx: var CBC[T], input: openArray[byte], + output: var openArray[byte]) {.inline.} = ## Encrypt array of data ``input`` and store encrypted data to array ## ``output`` using ``CBC[T]`` context ``ctx``. ## @@ -335,8 +335,8 @@ proc encrypt*[T](ctx: var CBC[T], inp: ptr byte, oup: ptr byte, toOpenArray(op[], 0, int(length - 1))) result = length -proc encrypt*[T](ctx: var CBC[T], input: openarray[char], - output: var openarray[char]) {.inline.} = +proc encrypt*[T](ctx: var CBC[T], input: openArray[char], + output: var openArray[char]) {.inline.} = ## Encrypt array of data ``input`` and store encrypted data to array ## ``output`` using ``CBC[T]`` context ``ctx``. ## @@ -349,8 +349,8 @@ proc encrypt*[T](ctx: var CBC[T], input: openarray[char], encrypt(ctx, input.toOpenArrayByte(0, len(input) - 1), output.toOpenArrayByte(0, len(output) - 1)) -proc decrypt*[T](ctx: var CBC[T], input: openarray[byte], - output: var openarray[byte]) {.inline.} = +proc decrypt*[T](ctx: var CBC[T], input: openArray[byte], + output: var openArray[byte]) {.inline.} = ## Decrypt array of data ``input`` and store decrypted data to array ## ``output`` using ``CBC[T]`` context ``ctx``. ## @@ -390,8 +390,8 @@ proc decrypt*[T](ctx: var CBC[T], inp: ptr byte, oup: ptr byte, toOpenArray(op[], 0, int(length - 1))) result = length -proc decrypt*[T](ctx: var CBC[T], input: openarray[char], - output: var openarray[char]) {.inline.} = +proc decrypt*[T](ctx: var CBC[T], input: openArray[char], + output: var openArray[char]) {.inline.} = ## Decrypt array of data ``input`` and store decrypted data to array ## ``output`` using ``CBC[T]`` context ``ctx``. ## @@ -418,7 +418,7 @@ template sizeKey*[T](ctx: CTR[T]): int = mixin sizeKey sizeKey(ctx.cipher) -proc inc128(counter: var openarray[byte]) = +proc inc128(counter: var openArray[byte]) = var n = 16'u32 var c = 1'u32 while true: @@ -429,7 +429,7 @@ proc inc128(counter: var openarray[byte]) = if n == 0: break -proc inc256(counter: var openarray[byte]) = +proc inc256(counter: var openArray[byte]) = var n = 32'u32 var c = 1'u32 while true: @@ -440,7 +440,7 @@ proc inc256(counter: var openarray[byte]) = if n == 0: break -proc init*[T](ctx: var CTR[T], key: openarray[byte], iv: openarray[byte]) = +proc init*[T](ctx: var CTR[T], key: openArray[byte], iv: openArray[byte]) = ## Initialize ``CTR[T]`` with encryption key ``key`` and initial vector (IV) ## ``iv``. ## @@ -473,8 +473,8 @@ proc init*[T](ctx: var CTR[T], key: ptr byte, iv: ptr byte) = init(ctx, toOpenArray(pkey[], 0, ctx.sizeKey() - 1), toOpenArray(piv[], 0, ctx.sizeBlock() - 1)) -proc init*[T](ctx: var CTR[T], key: openarray[char], - iv: openarray[char]) {.inline.} = +proc init*[T](ctx: var CTR[T], key: openArray[char], + iv: openArray[char]) {.inline.} = ## Initialize ``CTR[T]`` with encryption key ``key`` and initial vector (IV) ## ``iv``. ## @@ -492,8 +492,8 @@ proc clear*[T](ctx: var CTR[T]) {.inline.} = ## Clear ``CTR[T]`` context ``ctx``. burnMem(ctx) -proc encrypt*[T](ctx: var CTR[T], input: openarray[byte], - output: var openarray[byte]) {.inline.} = +proc encrypt*[T](ctx: var CTR[T], input: openArray[byte], + output: var openArray[byte]) {.inline.} = ## Perform ``CTR[T]`` encryption of plain data array ``input`` and store ## encrypted data to array ``output`` using ``CTR[T]`` context ``ctx``. ## @@ -517,8 +517,8 @@ proc encrypt*[T](ctx: var CTR[T], input: openarray[byte], n = (n + 1) mod ctx.sizeBlock() ctx.num = n -proc encrypt*[T](ctx: var CTR[T], input: openarray[char], - output: var openarray[char]) {.inline.} = +proc encrypt*[T](ctx: var CTR[T], input: openArray[char], + output: var openArray[char]) {.inline.} = ## Perform ``CTR[T]`` encryption of plain data array ``input`` and store ## encrypted data to array ``output`` using ``CTR[T]`` context ``ctx``. ## @@ -540,8 +540,8 @@ proc encrypt*[T](ctx: var CTR[T], inp: ptr byte, oup: ptr byte, toOpenArray(op[], 0, int(length - 1))) result = length -proc decrypt*[T](ctx: var CTR[T], input: openarray[byte], - output: var openarray[byte]) {.inline.} = +proc decrypt*[T](ctx: var CTR[T], input: openArray[byte], + output: var openArray[byte]) {.inline.} = ## Perform ``CTR[T]`` decryption of encrypted data array ``input`` and ## store decrypted data to array ``output`` using ``CTR[T]`` context ``ctx``. ## @@ -562,8 +562,8 @@ proc decrypt*[T](ctx: var CTR[T], inp: ptr byte, oup: ptr byte, toOpenArray(op[], 0, int(length - 1))) result = length -proc decrypt*[T](ctx: var CTR[T], input: openarray[char], - output: var openarray[char]) {.inline.} = +proc decrypt*[T](ctx: var CTR[T], input: openArray[char], + output: var openArray[char]) {.inline.} = ## Perform ``CTR[T]`` decryption of encrypted data array ``input`` and ## store decrypted data to array ``output`` using ``CTR[T]`` context ``ctx``. ## @@ -586,7 +586,7 @@ template sizeKey*[T](ctx: OFB[T]): int = mixin sizeKey sizeKey(ctx.cipher) -proc init*[T](ctx: var OFB[T], key: openarray[byte], iv: openarray[byte]) = +proc init*[T](ctx: var OFB[T], key: openArray[byte], iv: openArray[byte]) = ## Initialize ``OFB[T]`` with encryption key ``key`` and initial vector (IV) ## ``iv``. ## @@ -619,7 +619,7 @@ proc init*[T](ctx: var OFB[T], key: ptr byte, iv: ptr byte) = init(ctx, toOpenArray(pkey[], 0, ctx.sizeKey() - 1), toOpenArray(piv[], 0, ctx.sizeBlock() - 1)) -proc init*[T](ctx: var OFB[T], key: openarray[char], iv: openarray[char]) = +proc init*[T](ctx: var OFB[T], key: openArray[char], iv: openArray[char]) = ## Initialize ``OFB[T]`` with encryption key ``key`` and initial vector (IV) ## ``iv``. ## @@ -637,8 +637,8 @@ proc clear*[T](ctx: var OFB[T]) {.inline.} = ## Clear ``OFB[T]`` context ``ctx``. burnMem(ctx) -proc encrypt*[T](ctx: var OFB[T], input: openarray[byte], - output: var openarray[byte]) {.inline.} = +proc encrypt*[T](ctx: var OFB[T], input: openArray[byte], + output: var openArray[byte]) {.inline.} = ## Encrypt array of data ``input`` and store encrypted data to array ## ``output`` using ``OFB[T]`` context ``ctx``. ## @@ -668,8 +668,8 @@ proc encrypt*[T](ctx: var OFB[T], inp: ptr byte, oup: ptr byte, toOpenArray(op[], 0, int(length - 1))) result = length -proc encrypt*[T](ctx: var OFB[T], input: openarray[char], - output: var openarray[char]) {.inline.} = +proc encrypt*[T](ctx: var OFB[T], input: openArray[char], + output: var openArray[char]) {.inline.} = ## Encrypt array of data ``input`` and store encrypted data to array ## ``output`` using ``OFB[T]`` context ``ctx``. ## @@ -678,8 +678,8 @@ proc encrypt*[T](ctx: var OFB[T], input: openarray[char], encrypt(ctx, input.toOpenArrayByte(0, len(input) - 1), output.toOpenArrayByte(0, len(output) - 1)) -proc decrypt*[T](ctx: var OFB[T], input: openarray[byte], - output: var openarray[byte]) {.inline.} = +proc decrypt*[T](ctx: var OFB[T], input: openArray[byte], + output: var openArray[byte]) {.inline.} = ## Decrypt array of data ``input`` and store decrypted data to array ## ``output`` using ``OFB[T]`` context ``ctx``. ## @@ -700,8 +700,8 @@ proc decrypt*[T](ctx: var OFB[T], inp: ptr byte, oup: ptr byte, toOpenArray(op[], 0, int(length - 1))) result = length -proc decrypt*[T](ctx: var OFB[T], input: openarray[char], - output: var openarray[char]) {.inline.} = +proc decrypt*[T](ctx: var OFB[T], input: openArray[char], + output: var openArray[char]) {.inline.} = ## Decrypt array of data ``input`` and store decrypted data to array ## ``output`` using ``OFB[T]`` context ``ctx``. ## @@ -724,7 +724,7 @@ template sizeKey*[T](ctx: CFB[T]): int = mixin sizeKey sizeKey(ctx.cipher) -proc init*[T](ctx: var CFB[T], key: openarray[byte], iv: openarray[byte]) = +proc init*[T](ctx: var CFB[T], key: openArray[byte], iv: openArray[byte]) = ## Initialize ``CFB[T]`` with encryption key ``key`` and initial vector (IV) ## ``iv``. ## @@ -757,7 +757,7 @@ proc init*[T](ctx: var CFB[T], key: ptr byte, iv: ptr byte) = init(ctx, toOpenArray(pkey[], 0, ctx.sizeKey() - 1), toOpenArray(piv[], 0, ctx.sizeBlock() - 1)) -proc init*[T](ctx: var CFB[T], key: openarray[char], iv: openarray[char]) = +proc init*[T](ctx: var CFB[T], key: openArray[char], iv: openArray[char]) = ## Initialize ``CFB[T]`` with encryption key ``key`` and initial vector (IV) ## ``iv``. ## @@ -775,8 +775,8 @@ proc clear*[T](ctx: var CFB[T]) {.inline.} = ## Clear ``CFB[T]`` context ``ctx``. burnMem(ctx) -proc encrypt*[T](ctx: var CFB[T], input: openarray[byte], - output: var openarray[byte]) {.inline.} = +proc encrypt*[T](ctx: var CFB[T], input: openArray[byte], + output: var openArray[byte]) {.inline.} = ## Encrypt array of data ``input`` and store encrypted data to array ## ``output`` using ``CFB[T]`` context ``ctx``. ## @@ -807,8 +807,8 @@ proc encrypt*[T](ctx: var CFB[T], inp: ptr byte, oup: ptr byte, toOpenArray(op[], 0, int(length - 1))) result = length -proc encrypt*[T](ctx: var CFB[T], input: openarray[char], - output: var openarray[char]) {.inline.} = +proc encrypt*[T](ctx: var CFB[T], input: openArray[char], + output: var openArray[char]) {.inline.} = ## Encrypt array of data ``input`` and store encrypted data to array ## ``output`` using ``CFB[T]`` context ``ctx``. ## @@ -817,8 +817,8 @@ proc encrypt*[T](ctx: var CFB[T], input: openarray[char], encrypt(ctx, input.toOpenArrayByte(0, len(input) - 1), output.toOpenArrayByte(0, len(output) - 1)) -proc decrypt*[T](ctx: var CFB[T], input: openarray[byte], - output: var openarray[byte]) = +proc decrypt*[T](ctx: var CFB[T], input: openArray[byte], + output: var openArray[byte]) = ## Decrypt array of data ``input`` and store decrypted data to array ## ``output`` using ``CFB[T]`` context ``ctx``. ## @@ -850,8 +850,8 @@ proc decrypt*[T](ctx: var CFB[T], inp: ptr byte, oup: ptr byte, toOpenArray(op[], 0, int(length - 1))) result = length -proc decrypt*[T](ctx: var CFB[T], input: openarray[char], - output: var openarray[char]) = +proc decrypt*[T](ctx: var CFB[T], input: openArray[char], + output: var openArray[char]) = ## Decrypt array of data ``input`` and store decrypted data to array ## ``output`` using ``CFB[T]`` context ``ctx``. ## @@ -898,8 +898,8 @@ proc rev64(x: uint64): uint64 = RMS(xx, 0x0000FFFF0000FFFF'u64, 16) result = (xx shl 32) or (xx shr 32) -proc ghash(y: var openarray[byte], h: openarray[byte], - data: openarray[byte]) = +proc ghash(y: var openArray[byte], h: openArray[byte], + data: openArray[byte]) = var y0, y1, h0, h1, h2, h0r, h1r, h2r: uint64 y1 = beLoad64(y, 0) @@ -979,8 +979,8 @@ template sizeKey*[T](ctx: GCM[T]): int = mixin sizeKey sizeKey(ctx.cipher) -proc init*[T](ctx: var GCM[T], key: openarray[byte], iv: openarray[byte], - aad: openarray[byte]) = +proc init*[T](ctx: var GCM[T], key: openArray[byte], iv: openArray[byte], + aad: openArray[byte]) = ## Initialize ``GCM[T]`` with encryption key ``key``, initial vector (IV) ## ``iv`` and additional authentication data (AAD) ``aad``. ## @@ -1009,8 +1009,8 @@ proc init*[T](ctx: var GCM[T], key: openarray[byte], iv: openarray[byte], if len(aad) > 0: ghash(ctx.buf, ctx.h, aad) -proc encrypt*[T](ctx: var GCM[T], input: openarray[byte], - output: var openarray[byte]) = +proc encrypt*[T](ctx: var GCM[T], input: openArray[byte], + output: var openArray[byte]) = ## Encrypt array of data ``input`` and store encrypted data to array ## ``output`` using ``GCM[T]`` context ``ctx``. ## @@ -1033,8 +1033,8 @@ proc encrypt*[T](ctx: var GCM[T], input: openarray[byte], length -= uselen offset += uselen -proc decrypt*[T](ctx: var GCM[T], input: openarray[byte], - output: var openarray[byte]) = +proc decrypt*[T](ctx: var GCM[T], input: openArray[byte], + output: var openArray[byte]) = ## Decrypt array of data ``input`` and store decrypted data to array ## ``output`` using ``GCM[T]`` context ``ctx``. ## @@ -1057,7 +1057,7 @@ proc decrypt*[T](ctx: var GCM[T], input: openarray[byte], length -= uselen offset += uselen -proc getTag*[T](ctx: var GCM[T], tag: var openarray[byte]) = +proc getTag*[T](ctx: var GCM[T], tag: var openArray[byte]) = ## Obtain authentication tag from ``GCM[T]`` context ``ctx`` and store it to ## ``tag``. ## diff --git a/vendor/nimcrypto/nimcrypto/blake2.nim b/vendor/nimcrypto/nimcrypto/blake2.nim index 55b7bc79f..73fd7b362 100644 --- a/vendor/nimcrypto/nimcrypto/blake2.nim +++ b/vendor/nimcrypto/nimcrypto/blake2.nim @@ -285,7 +285,7 @@ template sizeBlock*(r: typedesc[blake2]): int = else: (128) -proc init*[T: bchar](ctx: var Blake2Context, key: openarray[T]) {.inline.} = +proc init*[T: bchar](ctx: var Blake2Context, key: openArray[T]) {.inline.} = when ctx is Blake2sContext: when nimvm: for i in 0 ..< 64: @@ -382,7 +382,7 @@ proc reset*(ctx: var Blake2Context) {.inline.} = ctx.t[1] = ctx.tb[1] ctx.c = ctx.cb -proc update*[T: bchar](ctx: var Blake2Context, data: openarray[T]) {.inline.} = +proc update*[T: bchar](ctx: var Blake2Context, data: openArray[T]) {.inline.} = var i = 0 while i < len(data): if ctx.c == int(ctx.sizeBlock): @@ -409,7 +409,7 @@ proc update*(ctx: var Blake2Context, pbytes: ptr byte, ctx.update(toOpenArray(p[], 0, int(nbytes) - 1)) proc finish*(ctx: var Blake2sContext, - data: var openarray[byte]): uint {.inline, discardable.} = + data: var openArray[byte]): uint {.inline, discardable.} = ctx.t[0] = ctx.t[0] + uint32(ctx.c) if ctx.t[0] < uint32(ctx.c): ctx.t[1] = ctx.t[1] + 1 @@ -423,7 +423,7 @@ proc finish*(ctx: var Blake2sContext, data[i] = byte((ctx.h[i shr 2] shr (8 * (i and 3))) and 0xFF'u32) proc finish*(ctx: var Blake2bContext, - data: var openarray[byte]): uint {.inline, discardable.} = + data: var openArray[byte]): uint {.inline, discardable.} = ctx.t[0] = ctx.t[0] + uint64(ctx.c) if ctx.t[0] < uint64(ctx.c): ctx.t[1] = ctx.t[1] + 1'u64 diff --git a/vendor/nimcrypto/nimcrypto/blowfish.nim b/vendor/nimcrypto/nimcrypto/blowfish.nim index 3ba0ec1a8..23dea9735 100644 --- a/vendor/nimcrypto/nimcrypto/blowfish.nim +++ b/vendor/nimcrypto/nimcrypto/blowfish.nim @@ -336,8 +336,8 @@ template f(ctx: var BlowfishContext, x: uint32): uint32 = vy = vy + ctx.S[3][d] vy -proc blowfishEncrypt*(ctx: var BlowfishContext, inp: openarray[byte], - oup: var openarray[byte]) = +proc blowfishEncrypt*(ctx: var BlowfishContext, inp: openArray[byte], + oup: var openArray[byte]) = var nxl = leLoad32(inp, 0) var nxr = leLoad32(inp, 4) @@ -362,8 +362,8 @@ proc blowfishEncrypt*(ctx: var BlowfishContext, inp: openarray[byte], leStore32(oup, 0, nxl) leStore32(oup, 4, nxr) -proc blowfishDecrypt*(ctx: var BlowfishContext, inp: openarray[byte], - oup: var openarray[byte]) = +proc blowfishDecrypt*(ctx: var BlowfishContext, inp: openArray[byte], + oup: var openArray[byte]) = var nxl = leLoad32(inp, 0) var nxr = leLoad32(inp, 4) @@ -388,7 +388,7 @@ proc blowfishDecrypt*(ctx: var BlowfishContext, inp: openarray[byte], leStore32(oup, 0, nxl) leStore32(oup, 4, nxr) -proc initBlowfishContext*(ctx: var BlowfishContext, key: openarray[byte], +proc initBlowfishContext*(ctx: var BlowfishContext, key: openArray[byte], nkey: int) = var i = 0 var j = 0 @@ -448,7 +448,7 @@ template sizeKey*(r: typedesc[blowfish]): int = template sizeBlock*(r: typedesc[blowfish]): int = (8) -proc init*(ctx: var BlowfishContext, key: openarray[byte]) {.inline.} = +proc init*(ctx: var BlowfishContext, key: openArray[byte]) {.inline.} = ctx.sizeKey = len(key) shl 3 initBlowfishContext(ctx, key, ctx.sizeKey) @@ -461,12 +461,12 @@ proc init*(ctx: var BlowfishContext, key: ptr byte, nkey: int) {.inline.} = proc clear*(ctx: var BlowfishContext) {.inline.} = burnMem(ctx) -proc encrypt*(ctx: var BlowfishContext, input: openarray[byte], - output: var openarray[byte]) {.inline.} = +proc encrypt*(ctx: var BlowfishContext, input: openArray[byte], + output: var openArray[byte]) {.inline.} = blowfishEncrypt(ctx, input, output) -proc decrypt*(ctx: var BlowfishContext, input: openarray[byte], - output: var openarray[byte]) {.inline.} = +proc decrypt*(ctx: var BlowfishContext, input: openArray[byte], + output: var openArray[byte]) {.inline.} = blowfishDecrypt(ctx, input, output) proc encrypt*(ctx: var BlowfishContext, inbytes: ptr byte, diff --git a/vendor/nimcrypto/nimcrypto/hash.nim b/vendor/nimcrypto/nimcrypto/hash.nim index 76b930733..379148c99 100644 --- a/vendor/nimcrypto/nimcrypto/hash.nim +++ b/vendor/nimcrypto/nimcrypto/hash.nim @@ -68,7 +68,7 @@ proc digest*(HashType: typedesc, data: ptr byte, ctx.clear() proc digest*[T: bchar](HashType: typedesc, - data: openarray[T]): MDigest[HashType.bits] = + data: openArray[T]): MDigest[HashType.bits] = ## Calculate and return digest using algorithm ``HashType`` of data ``data`` ## ## .. code-block::nim @@ -92,7 +92,7 @@ proc digest*[T: bchar](HashType: typedesc, result = ctx.finish() ctx.clear() -proc digest*[T](HashType: typedesc, data: openarray[T], +proc digest*[T](HashType: typedesc, data: openArray[T], ostart: int, ofinish = -1): MDigest[HashType.bits] {. deprecated: "Use digest(data.toOpenArray()) instead", inline.} = if ofinish < 0: diff --git a/vendor/nimcrypto/nimcrypto/hmac.nim b/vendor/nimcrypto/nimcrypto/hmac.nim index cfc66b11a..294dcbc09 100644 --- a/vendor/nimcrypto/nimcrypto/hmac.nim +++ b/vendor/nimcrypto/nimcrypto/hmac.nim @@ -55,7 +55,7 @@ ## # 18AF7C8586141A47EAAD416C2B356431D001FAFF3B8C98C80AA108DC971B230D ## # 18AF7C8586141A47EAAD416C2B356431D001FAFF3B8C98C80AA108DC971B230D ## # 18AF7C8586141A47EAAD416C2B356431D001FAFF3B8C98C80AA108DC971B230D -import hash, utils +import utils import sha, sha2, ripemd, keccak, blake2, hash export sha, sha2, ripemd, keccak, blake2, hash @@ -98,10 +98,10 @@ template sizeDigest*[T](h: HMAC[T]): uint = ## Size of HMAC digest in octets (bytes). uint(h.mdctx.sizeDigest) -proc init*[T, M](hmctx: var HMAC[T], key: openarray[M]) = +proc init*[T, M](hmctx: var HMAC[T], key: openArray[M]) = ## Initialize HMAC context ``hmctx`` with key using ``key`` array. ## - ## ``key`` supports ``openarray[byte]`` and ``openarray[char]`` only. + ## ``key`` supports ``openArray[byte]`` and ``openArray[char]`` only. mixin init, update, finish when not((M is byte) or (M is char)): @@ -155,7 +155,7 @@ proc reset*(hmctx: var HMAC) = update(hmctx.mdctx, hmctx.ipad) update(hmctx.opadctx, hmctx.opad) -proc update*[T: bchar](hmctx: var HMAC, data: openarray[T]) {.inline.} = +proc update*[T: bchar](hmctx: var HMAC, data: openArray[T]) {.inline.} = ## Update HMAC context ``hmctx`` with data array ``data``. Repeated calls are ## equivalent to a single call with the concatenation of all ``data`` ## arguments. @@ -195,7 +195,7 @@ proc update*(hmctx: var HMAC, pbytes: ptr byte, nbytes: uint) {.inline.} = hmctx.update(ptrarr[].toOpenArray(0, int(nbytes) - 1)) proc finish*[T: bchar](hmctx: var HMAC, - data: var openarray[T]): uint {.inline.} = + data: var openArray[T]): uint {.inline.} = ## Finalize HMAC context ``hmctx`` and store calculated digest to array ## ``data``. ``data`` length must be at least ``hmctx.sizeDigest`` octets ## (bytes). @@ -218,8 +218,8 @@ proc finish*(hmctx: var HMAC): MDigest[hmctx.HashType.bits] = ## ``MDigest`` object. discard finish(hmctx, result.data) -proc hmac*[A: bchar, B: bchar](HashType: typedesc, key: openarray[A], - data: openarray[B]): MDigest[HashType.bits] = +proc hmac*[A: bchar, B: bchar](HashType: typedesc, key: openArray[A], + data: openArray[B]): MDigest[HashType.bits] = ## Perform HMAC computation with hash algorithm ``HashType`` using key ``key`` ## of data ``data``. ## diff --git a/vendor/nimcrypto/nimcrypto/keccak.nim b/vendor/nimcrypto/nimcrypto/keccak.nim index f5ad9f2c7..6e09fbce2 100644 --- a/vendor/nimcrypto/nimcrypto/keccak.nim +++ b/vendor/nimcrypto/nimcrypto/keccak.nim @@ -60,27 +60,27 @@ type # then 256 registers and so it is not enough for it to perform round in # template. when nimvm: - proc THETA1(a: var openarray[uint64], b: openarray[uint64], + proc THETA1(a: var openArray[uint64], b: openArray[uint64], c: int) {.inline.} = a[c] = b[c] xor b[c + 5] xor b[c + 10] xor b[c + 15] xor b[c + 20] - proc THETA2(a: var uint64, b: openarray[uint64], c: int) {.inline.} = + proc THETA2(a: var uint64, b: openArray[uint64], c: int) {.inline.} = a = b[(c + 4) mod 5] xor ROL(uint64(b[(c + 1) mod 5]), 1) - proc THETA3(a: var openarray[uint64], b: int, c: uint64) {.inline.} = + proc THETA3(a: var openArray[uint64], b: int, c: uint64) {.inline.} = a[b] = a[b] xor c a[b + 5] = a[b + 5] xor c a[b + 10] = a[b + 10] xor c a[b + 15] = a[b + 15] xor c a[b + 20] = a[b + 20] xor c - proc RHOPI(a: var openarray[uint64], b: var openarray[uint64], c: var uint64, + proc RHOPI(a: var openArray[uint64], b: var openArray[uint64], c: var uint64, d, e: int) {.inline.} = a[0] = b[d] b[d] = ROL(c, e) c = uint64(a[0]) - proc CHI(a: var openarray[uint64], b: var openarray[uint64], + proc CHI(a: var openArray[uint64], b: var openArray[uint64], c: int) {.inline.} = a[0] = b[c] a[1] = b[c + 1] @@ -94,7 +94,7 @@ when nimvm: b[c + 4] = b[c + 4] xor (not(a[0]) and a[1]) - proc KECCAKROUNDP(a: var openarray[uint64], b: var openarray[uint64], + proc KECCAKROUNDP(a: var openArray[uint64], b: var openArray[uint64], c: var uint64, r: int) {.inline.} = THETA1(b, a, 0) THETA1(b, a, 1) @@ -364,7 +364,7 @@ proc reset*(ctx: var KeccakContext) {.inline.} = init(ctx) proc update*[T: bchar](ctx: var KeccakContext, - data: openarray[T]) {.inline.} = + data: openArray[T]) {.inline.} = var j = ctx.pt if len(data) > 0: for i in 0 ..< len(data): @@ -392,7 +392,7 @@ proc xof*(ctx: var KeccakContext) {.inline.} = ctx.pt = 0 proc output*(ctx: var KeccakContext, - data: var openarray[byte]): uint {.inline.} = + data: var openArray[byte]): uint {.inline.} = when ctx.kind != Shake: {.error: "Only `Shake128` and `Shake256` types are supported".} var j = ctx.pt @@ -412,7 +412,7 @@ proc output*(ctx: var KeccakContext, pbytes: ptr byte, result = ctx.output(ptrarr[].toOpenArray(0, int(nbytes) - 1)) proc finish*(ctx: var KeccakContext, - data: var openarray[byte]): uint {.inline, discardable.} = + data: var openArray[byte]): uint {.inline, discardable.} = when ctx.kind == Sha3: ctx.q[ctx.pt] = ctx.q[ctx.pt] xor 0x06'u8 else: diff --git a/vendor/nimcrypto/nimcrypto/pbkdf2.nim b/vendor/nimcrypto/nimcrypto/pbkdf2.nim index 466883e6e..33570a59d 100644 --- a/vendor/nimcrypto/nimcrypto/pbkdf2.nim +++ b/vendor/nimcrypto/nimcrypto/pbkdf2.nim @@ -15,9 +15,9 @@ import hmac, utils export hmac -proc pbkdf2*[T, M, N](ctx: var HMAC[T], password: openarray[M], - salt: openarray[N], c: int, - output: var openarray[byte]): int = +proc pbkdf2*[T, M, N](ctx: var HMAC[T], password: openArray[M], + salt: openArray[N], c: int, + output: var openArray[byte]): int = ## Calculate PBKDF2 result using HMAC algorithm `ctx`. ## ## ``ctx`` - HMAC[T] context @@ -74,9 +74,9 @@ proc pbkdf2*[T, M, N](ctx: var HMAC[T], password: openarray[M], ctx.clear() int(glength) -proc pbkdf2*[T, M, N](ctx: var HMAC[T], password: openarray[M], - salt: openarray[N], c: int, - output: var openarray[byte], outlen: int): int {. +proc pbkdf2*[T, M, N](ctx: var HMAC[T], password: openArray[M], + salt: openArray[N], c: int, + output: var openArray[byte], outlen: int): int {. deprecated: "Use pbkdf2() with output.toOpenArray()", inline.} = ## Calculate PBKDF2 result using HMAC algorithm `ctx`. ## @@ -93,8 +93,8 @@ proc pbkdf2*[T, M, N](ctx: var HMAC[T], password: openarray[M], else: pbkdf2(ctx, password, salt, c, output.toOpenArray(0, outlen)) -proc pbkdf2*[T, M](hashtype: typedesc, password: openarray[T], - salt: openarray[M], c: int, +proc pbkdf2*[T, M](hashtype: typedesc, password: openArray[T], + salt: openArray[M], c: int, outlen: int): seq[byte] {.inline.} = ## Calculate PBKDF2 result using HMAC[``hashtype``] algorithm. ## diff --git a/vendor/nimcrypto/nimcrypto/rijndael.nim b/vendor/nimcrypto/nimcrypto/rijndael.nim index d09e2600b..f5d8be463 100644 --- a/vendor/nimcrypto/nimcrypto/rijndael.nim +++ b/vendor/nimcrypto/nimcrypto/rijndael.nim @@ -239,7 +239,7 @@ when sizeof(int) == 4: q[1] = q3 xor q6 xor q0 q[0] = q2 xor q5 xor q7 - proc ortho(q: var openarray[uint32]) {.inline.} = + proc ortho(q: var openArray[uint32]) {.inline.} = template swapN(cl, ch, s, x, y) = var a, b: uint32 a = x @@ -284,7 +284,7 @@ when sizeof(int) == 4: ortho(q) q[0] - proc keySchedule(ctx: var RijndaelContext, key: openarray[byte]) = + proc keySchedule(ctx: var RijndaelContext, key: openArray[byte]) = var tmp = 0'u32 var j, k: int @@ -459,8 +459,8 @@ when sizeof(int) == 4: q[6] = q3 xor q4 xor q5 xor q7 xor r3 xor r5 xor r6 xor r7 xor rotr16(v6) q[7] = q4 xor q5 xor q6 xor r4 xor r6 xor r7 xor rotr16(v7) - proc encrypt*(ctx: RijndaelContext, input: openarray[byte], - output: var openarray[byte]) = + proc encrypt*(ctx: RijndaelContext, input: openArray[byte], + output: var openArray[byte]) = var q {.noinit.}: array[8, uint32] q[0] = leLoad32(input, 0) q[2] = leLoad32(input, 4) @@ -487,8 +487,8 @@ when sizeof(int) == 4: leStore32(output, 8, q[4]) leStore32(output, 12, q[6]) - proc decrypt*(ctx: RijndaelContext, input: openarray[byte], - output: var openarray[byte]) = + proc decrypt*(ctx: RijndaelContext, input: openArray[byte], + output: var openArray[byte]) = var q {.noinit.}: array[8, uint32] q[0] = leLoad32(input, 0) q[2] = leLoad32(input, 4) @@ -743,7 +743,7 @@ elif sizeof(int) == 8: swap8(q[3], q[7]) proc interleaveIn(q0: var uint64, q1: var uint64, - w: openarray[uint32]) {.inline.} = + w: openArray[uint32]) {.inline.} = var x0, x1, x2, x3: uint64 x0 = w[0] @@ -769,7 +769,7 @@ elif sizeof(int) == 8: q0 = x0 or (x2 shl 8) q1 = x1 or (x3 shl 8) - proc interleaveOut(w: var openarray[uint32], q0: uint64, + proc interleaveOut(w: var openArray[uint32], q0: uint64, q1: uint64) {.inline.} = var x0, x1, x2, x3: uint64 @@ -802,7 +802,7 @@ elif sizeof(int) == 8: ortho(q) uint32(q[0] and 0xFFFF_FFFF'u64) - proc keySchedule(ctx: var RijndaelContext, key: openarray[byte]) = + proc keySchedule(ctx: var RijndaelContext, key: openArray[byte]) = var skey: array[60, uint32] var tkey: array[30, uint64] var tmp = 0'u32 @@ -997,8 +997,8 @@ elif sizeof(int) == 8: q[6] = q3 xor q4 xor q5 xor q7 xor r3 xor r5 xor r6 xor r7 xor rotr32(v6) q[7] = q4 xor q5 xor q6 xor r4 xor r6 xor r7 xor rotr32(v7) - proc encrypt*(ctx: RijndaelContext, input: openarray[byte], - output: var openarray[byte]) = + proc encrypt*(ctx: RijndaelContext, input: openArray[byte], + output: var openArray[byte]) = var q: array[8, uint64] var w: array[4, uint32] @@ -1031,8 +1031,8 @@ elif sizeof(int) == 8: leStore32(output, 8, w[2]) leStore32(output, 12, w[3]) - proc decrypt*(ctx: RijndaelContext, input: openarray[byte], - output: var openarray[byte]) = + proc decrypt*(ctx: RijndaelContext, input: openArray[byte], + output: var openArray[byte]) = var q: array[8, uint64] var w: array[16, uint32] @@ -1088,7 +1088,7 @@ template sizeKey*(r: typedesc[rijndael]): int = template sizeBlock*(r: typedesc[rijndael]): int = (16) -proc init*(ctx: var RijndaelContext, key: openarray[byte]) {.inline.} = +proc init*(ctx: var RijndaelContext, key: openArray[byte]) {.inline.} = keySchedule(ctx, key) proc init*(ctx: var RijndaelContext, key: ptr byte, nkey: int = 0) {.inline.} = diff --git a/vendor/nimcrypto/nimcrypto/ripemd.nim b/vendor/nimcrypto/nimcrypto/ripemd.nim index 3498c253b..8a2815d0d 100644 --- a/vendor/nimcrypto/nimcrypto/ripemd.nim +++ b/vendor/nimcrypto/nimcrypto/ripemd.nim @@ -465,7 +465,7 @@ template RROUND160N5(a, b, c, d, e, x): void = FFF160(c, d, e, a, b, x[ 9] , 11) FFF160(b, c, d, e, a, x[11] , 11) -proc ripemd128Transform(state: var array[4, uint32], data: openarray[byte]) = +proc ripemd128Transform(state: var array[4, uint32], data: openArray[byte]) = var aa = state[0] bb = state[1] @@ -502,7 +502,7 @@ proc ripemd128Transform(state: var array[4, uint32], data: openarray[byte]) = state[3] = state[0] + bb + ccc state[0] = ddd -proc ripemd256Transform(state: var array[8, uint32], data: openarray[byte]) = +proc ripemd256Transform(state: var array[8, uint32], data: openArray[byte]) = var aa = state[0] bb = state[1] @@ -547,7 +547,7 @@ proc ripemd256Transform(state: var array[8, uint32], data: openarray[byte]) = state[7] = state[7] + ddd proc ripemd160Transform(state: var array[5, uint32], - data: openarray[byte]) {.inline.} = + data: openArray[byte]) {.inline.} = var aa = state[0] bb = state[1] @@ -590,7 +590,7 @@ proc ripemd160Transform(state: var array[5, uint32], state[0] = ddd proc ripemd320Transform(state: var array[10, uint32], - data: openarray[byte]) {.inline.} = + data: openArray[byte]) {.inline.} = var aa = state[0] bb = state[1] @@ -745,7 +745,7 @@ proc clear*(ctx: var RipemdContext) {.inline.} = proc reset*(ctx: var RipemdContext) {.inline.} = init(ctx) -proc update*[T: bchar](ctx: var RipemdContext, data: openarray[T]) {.inline.} = +proc update*[T: bchar](ctx: var RipemdContext, data: openArray[T]) {.inline.} = var pos = 0 var length = len(data) @@ -810,7 +810,7 @@ proc finalize(ctx: var RipemdContext) {.inline.} = ripemd320Transform(ctx.state, ctx.buffer) proc finish*(ctx: var RipemdContext, - data: var openarray[byte]): uint {.inline, discardable.} = + data: var openArray[byte]): uint {.inline, discardable.} = result = 0 finalize(ctx) when ctx.bits == 128: diff --git a/vendor/nimcrypto/nimcrypto/sha.nim b/vendor/nimcrypto/nimcrypto/sha.nim index 3a3570e55..ae5e91852 100644 --- a/vendor/nimcrypto/nimcrypto/sha.nim +++ b/vendor/nimcrypto/nimcrypto/sha.nim @@ -78,7 +78,7 @@ proc init*(ctx: var Sha1Context) {.inline.} = ctx.h[4] = 0xC3D2E1F0'u32 proc sha1Transform[T: bchar](ctx: var Sha1Context, - blk: openarray[T], + blk: openArray[T], offset: int) {.noinit, inline.} = var A, B, C, D, E: uint32 @@ -195,7 +195,7 @@ proc clear*(ctx: var Sha1Context) {.inline.} = proc reset*(ctx: var Sha1Context) {.inline.} = init(ctx) -proc update*[T: bchar](ctx: var Sha1Context, data: openarray[T]) {.inline.} = +proc update*[T: bchar](ctx: var Sha1Context, data: openArray[T]) {.inline.} = var length = len(data) if length > 0: var lenw = int(ctx.size and 63'u64) # ctx.size mod 64 @@ -226,7 +226,7 @@ proc update*(ctx: var Sha1Context, pbytes: ptr byte, ctx.update(toOpenArray(p[], 0, int(nbytes) - 1)) proc finish*(ctx: var Sha1Context, - data: var openarray[byte]): uint {.inline, discardable.} = + data: var openArray[byte]): uint {.inline, discardable.} = let one80 = [0x80'u8] one00 = [0x00'u8] diff --git a/vendor/nimcrypto/nimcrypto/sha2.nim b/vendor/nimcrypto/nimcrypto/sha2.nim index 9fa97bfc7..543074cd5 100644 --- a/vendor/nimcrypto/nimcrypto/sha2.nim +++ b/vendor/nimcrypto/nimcrypto/sha2.nim @@ -233,7 +233,7 @@ template ROUND512(a, b, c, d, e, f, g, h, z) = d = d + t0 h = t0 + t1 -proc sha256Transform(state: var array[8, uint32], data: openarray[byte]) = +proc sha256Transform(state: var array[8, uint32], data: openArray[byte]) = var t0, t1: uint32 W {.noinit.}: array[64, uint32] @@ -336,7 +336,7 @@ proc sha256Transform(state: var array[8, uint32], data: openarray[byte]) = state[6] = state[6] + s6 state[7] = state[7] + s7 -proc sha512Transform(state: var array[8, uint64], data: openarray[byte]) = +proc sha512Transform(state: var array[8, uint64], data: openArray[byte]) = var t0, t1: uint64 W {.noinit.}: array[80, uint64] @@ -456,7 +456,7 @@ proc sha512Transform(state: var array[8, uint64], data: openarray[byte]) = state[6] = state[6] + s6 state[7] = state[7] + s7 -proc update*[T: bchar](ctx: var Sha2Context, data: openarray[T]) {.inline.} = +proc update*[T: bchar](ctx: var Sha2Context, data: openArray[T]) {.inline.} = var pos = 0 var length = len(data) @@ -522,7 +522,7 @@ proc finalize512(ctx: var Sha2Context) {.inline.} = sha512Transform(ctx.state, ctx.buffer) proc finish*(ctx: var Sha2Context, - data: var openarray[byte]): uint {.inline, discardable.} = + data: var openArray[byte]): uint {.inline, discardable.} = result = 0'u when ctx.bits == 224 and ctx.bsize == 64: if len(data) >= 28: diff --git a/vendor/nimcrypto/nimcrypto/sysrand.nim b/vendor/nimcrypto/nimcrypto/sysrand.nim index f5e1bbcba..04ef055d2 100644 --- a/vendor/nimcrypto/nimcrypto/sysrand.nim +++ b/vendor/nimcrypto/nimcrypto/sysrand.nim @@ -13,8 +13,8 @@ ## ``Windows`` using BCryptGenRandom (if available), ## CryptGenRandom(PROV_INTEL_SEC) (if available), RtlGenRandom. ## -## RtlGenRandom (available from Windows XP) -## BCryptGenRandom (available from Windows Vista SP1) +## RtlGenRandom (available since Windows XP) +## BCryptGenRandom (available since Windows Vista SP1) ## CryptGenRandom(PROV_INTEL_SEC) (only when Intel SandyBridge ## CPU is available). ## @@ -25,60 +25,63 @@ ## ``NetBSD``, ``FreeBSD``, ``MacOS``, ``Solaris`` using `/dev/urandom`. {.deadCodeElim:on.} +{.push raises: [].} when defined(posix): import os, posix proc urandomRead(pbytes: pointer, nbytes: int): int = - result = -1 var st: Stat let fd = posix.open("/dev/urandom", posix.O_RDONLY) - if fd != -1: - if posix.fstat(fd, st) != -1 and S_ISCHR(st.st_mode): - result = 0 - while result < nbytes: - var p = cast[pointer](cast[uint]((pbytes)) + uint(result)) - var res = posix.read(fd, p, nbytes - result) - if res > 0: - result += res - elif res == 0: - break - else: - if osLastError().int32 != EINTR: - result = -1 - break + if fd == -1: + return -1 + if posix.fstat(fd, st) == -1 or not(S_ISCHR(st.st_mode)): discard posix.close(fd) + return -1 + + var res = 0 + while res < nbytes: + var p = cast[pointer](cast[uint]((pbytes)) + uint(res)) + var bytesRead = posix.read(fd, p, nbytes - res) + if bytesRead > 0: + res += bytesRead + elif bytesRead == 0: + break + else: + if osLastError() != OSErrorCode(EINTR): + break + discard posix.close(fd) + res when defined(openbsd): - import posix, os - proc getentropy(pBytes: pointer, nBytes: int): cint + proc getentropy(pbytes: pointer, nbytes: int): cint {.importc: "getentropy", header: "".} proc randomBytes*(pbytes: pointer, nbytes: int): int = var p: pointer - while result < nbytes: - p = cast[pointer](cast[uint](pbytes) + uint(result)) - let res = getentropy(p, nbytes - result) - if res > 0: - result += res - elif res == 0: + var res = 0 + while res < nbytes: + p = cast[pointer](cast[uint](pbytes) + uint(res)) + let bytesRead = getentropy(p, nbytes - res) + if bytesRead > 0: + res += bytesRead + elif bytesRead == 0: break else: - if osLastError().int32 != EINTR: - result = -1 + if osLastError() != OSErrorCode(EINTR): break - if result == -1: - result = urandomRead(pbytes, nbytes) - elif result < nbytes: - p = cast[pointer](cast[uint](pbytes) + uint(result)) - let res = urandomRead(p, nbytes - result) - if res != -1: - result += res + if res <= 0: + res = urandomRead(pbytes, nbytes) + elif res < nbytes: + p = cast[pointer](cast[uint](pbytes) + uint(res)) + let bytesRead = urandomRead(p, nbytes - res) + if bytesRead != -1: + res += bytesRead + res elif defined(linux): - import posix, os when defined(i386): const SYS_getrandom = 355 elif defined(powerpc64) or defined(powerpc64el) or defined(powerpc): @@ -109,47 +112,50 @@ elif defined(linux): var gSystemRng {.threadvar.}: SystemRng ## System thread global RNG - proc newSystemRNG(): SystemRng = - result = SystemRng() - + proc newSystemRng(): SystemRng = + var rng = SystemRng() if SYS_getrandom != 0: var data: int - result.getRandomPresent = true + rng.getRandomPresent = true let res = syscall(SYS_getrandom, addr data, 1, GRND_NONBLOCK) if res == -1: - let err = osLastError().int32 - if err == ENOSYS or err == EPERM: - result.getRandomPresent = false + let err = osLastError() + if err == OSErrorCode(ENOSYS) or err == OSErrorCode(EPERM): + rng.getRandomPresent = false + rng - proc getSystemRNG(): SystemRng = - if gSystemRng.isNil: gSystemRng = newSystemRng() - result = gSystemRng + proc getSystemRng(): SystemRng = + if isNil(gSystemRng): + gSystemRng = newSystemRng() + gSystemRng proc randomBytes*(pbytes: pointer, nbytes: int): int = var p: pointer - let srng = getSystemRNG() + let srng = getSystemRng() + if srng.getRandomPresent: - while result < nbytes: - p = cast[pointer](cast[uint](pbytes) + uint(result)) - let res = syscall(SYS_getrandom, pBytes, nBytes - result, 0) - if res > 0: - result += res - elif res == 0: + var res = 0 + while res < nbytes: + p = cast[pointer](cast[uint](pbytes) + uint(res)) + let bytesRead = syscall(SYS_getrandom, pbytes, nbytes - res, 0) + if bytesRead > 0: + res += bytesRead + elif bytesRead == 0: break else: if osLastError().int32 != EINTR: - result = -1 break - if result == -1: - result = urandomRead(pbytes, nbytes) - elif result < nbytes: - p = cast[pointer](cast[uint](pbytes) + uint(result)) - let res = urandomRead(p, nbytes - result) - if res != -1: - result += res + if res <= 0: + res = urandomRead(pbytes, nbytes) + elif res < nbytes: + p = cast[pointer](cast[uint](pbytes) + uint(res)) + let bytesRead = urandomRead(p, nbytes - res) + if bytesRead != -1: + res += bytesRead + res else: - result = urandomRead(pbytes, nbytes) + urandomRead(pbytes, nbytes) elif defined(windows): import os, winlean, dynlib @@ -219,71 +225,73 @@ elif defined(windows): proc isEqualOrHigher(major: int, minor: int, servicePack: int): bool = var mask = 0'u64 - var ov = OSVERSIONINFOEXW() - ov.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW).DWORD - ov.dwMajorVersion = major.DWORD - ov.dwMinorVersion = minor.DWORD - ov.wServicePackMajor = servicePack.uint16 - ov.wServicePackMinor = 0 - var typeMask = (VER_MAJORVERSION or VER_MINORVERSION or - VER_SERVICEPACKMAJOR or VER_SERVICEPACKMINOR).DWORD + var ov = OSVERSIONINFOEXW( + dwOSVersionInfoSize: DWORD(sizeof(OSVERSIONINFOEXW)), + dwMajorVersion: DWORD(major), + dwMinorVersion: DWORD(minor), + wServicePackMajor: uint16(servicePack), + wServicePackMinor: 0 + ) + let typeMask = + DWORD(VER_MAJORVERSION or VER_MINORVERSION or + VER_SERVICEPACKMAJOR or VER_SERVICEPACKMINOR) mask = verSetConditionMask(mask, VER_MAJORVERSION, VER_GREATER_EQUAL) mask = verSetConditionMask(mask, VER_MINORVERSION, VER_GREATER_EQUAL) mask = verSetConditionMask(mask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL) mask = verSetConditionMask(mask, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL) - return (verifyVersionInfo(addr ov, typeMask, mask) == 1) + verifyVersionInfo(addr ov, typeMask, mask) == 1 - proc newSystemRNG(): SystemRng = - result = SystemRng() + proc newSystemRng(): SystemRng = + var rng = SystemRng() if isEqualOrHigher(6, 0, 0): if isEqualOrHigher(6, 0, 1): let lib = loadLib("bcrypt.dll") if lib != nil: var lProc = cast[BCGRMPROC](symAddr(lib, "BCryptGenRandom")) if not isNil(lProc): - result.bCryptGenRandom = lProc - + rng.bCryptGenRandom = lProc var hp: HCRYPTPROV = 0 let intelDef = newWideCString(INTEL_DEF_PROV) - let res1 = cryptAcquireContext(addr hp, nil, intelDef, PROV_INTEL_SEC, - CRYPT_VERIFYCONTEXT or CRYPT_SILENT).bool - if res1: - result.hIntel = hp + let res = cryptAcquireContext(addr hp, nil, intelDef, PROV_INTEL_SEC, + CRYPT_VERIFYCONTEXT or CRYPT_SILENT).bool + if res: + rng.hIntel = hp + rng - proc getSystemRNG(): SystemRng = - if gSystemRng.isNil: gSystemRng = newSystemRng() - result = gSystemRng + proc getSystemRng(): SystemRng = + if isNil(gSystemRng): + gSystemRng = newSystemRng() + gSystemRng proc randomBytes*(pbytes: pointer, nbytes: int): int = - let srng = getSystemRNG() - result = -1 + let srng = getSystemRng() + if not isNil(srng.bCryptGenRandom): - if srng.bCryptGenRandom(nil, pbytes, nbytes.ULONG, + if srng.bCryptGenRandom(nil, pbytes, ULONG(nbytes), BCRYPT_USE_SYSTEM_PREFERRED_RNG) == 0: - result = nbytes - - if srng.hIntel != 0 and result == -1: - if cryptGenRandom(srng.hIntel, nbytes.DWORD, pbytes) != 0: - result = nbytes - - if result == -1: - if rtlGenRandom(pBytes, nbytes.ULONG) != 0: - result = nbytes + return nbytes + if srng.hIntel != 0: + if cryptGenRandom(srng.hIntel, DWORD(nbytes), pbytes) != 0: + return nbytes + if rtlGenRandom(pbytes, ULONG(nbytes)) != 0: + return nbytes + -1 proc randomClose*() = - let srng = getSystemRNG() + let srng = getSystemRng() if srng.hIntel != 0: - if cryptReleaseContext(srng.hIntel, 0) == 0: - raiseOsError(osLastError()) + discard cryptReleaseContext(srng.hIntel, 0) + else: - import posix - proc randomBytes*(pbytes: pointer, nbytes: int): int = - result = urandomRead(pbytes, nbytes) + urandomRead(pbytes, nbytes) -proc randomBytes*[T](bytes: var openarray[T]): int = +proc randomBytes*[T](bytes: var openArray[T]): int = let length = len(bytes) * sizeof(T) - if length > 0: - result = randomBytes(addr bytes[0], length) - if result != -1: - result = result div sizeof(T) + if length == 0: + return 0 + let res = randomBytes(addr bytes[0], length) + if res != -1: + res div sizeof(T) + else: + res diff --git a/vendor/nimcrypto/nimcrypto/twofish.nim b/vendor/nimcrypto/nimcrypto/twofish.nim index 516f847ab..b5de16314 100644 --- a/vendor/nimcrypto/nimcrypto/twofish.nim +++ b/vendor/nimcrypto/nimcrypto/twofish.nim @@ -313,8 +313,8 @@ template DEC_ROUND(CTX, R0, R1, R2, R3, round) = R2 = ROL(R2, 1) xor (T0 + T1 + CTX.K[2 * round + 8]) R3 = ROR(R3 xor (T0 + 2'u32 * T1 + CTX.K[2 * round + 9]), 1) -proc twofishEncrypt(ctx: var TwofishContext, inp: openarray[byte], - oup: var openarray[byte]) {.inline.} = +proc twofishEncrypt(ctx: var TwofishContext, inp: openArray[byte], + oup: var openArray[byte]) {.inline.} = var T0, T1: uint32 var r3 = ctx.K[3] xor leLoad32(inp, 12) @@ -344,8 +344,8 @@ proc twofishEncrypt(ctx: var TwofishContext, inp: openarray[byte], leStore32(oup, 4, r3 xor ctx.K[5]) leStore32(oup, 0, r2 xor ctx.K[4]) -proc twofishDecrypt(ctx: var TwofishContext, inp: openarray[byte], - oup: var openarray[byte]) {.inline.} = +proc twofishDecrypt(ctx: var TwofishContext, inp: openArray[byte], + oup: var openArray[byte]) {.inline.} = var T0, T1: uint32 var r3 = ctx.K[7] xor leLoad32(inp, 12) @@ -376,7 +376,7 @@ proc twofishDecrypt(ctx: var TwofishContext, inp: openarray[byte], leStore32(oup, 0, r2 xor ctx.K[0]) proc initTwofishContext(ctx: var TwofishContext, N: int, - key: openarray[byte]) = + key: openArray[byte]) = var A, B: uint32 @@ -421,7 +421,7 @@ template sizeKey*(r: typedesc[twofish]): int = template sizeBlock*(r: typedesc[twofish]): int = (16) -proc init*(ctx: var TwofishContext, key: openarray[byte]) {.inline.} = +proc init*(ctx: var TwofishContext, key: openArray[byte]) {.inline.} = initTwofishContext(ctx, ctx.bits, key) proc init*(ctx: var TwofishContext, key: ptr byte, nkey: int = 0) {.inline.} = @@ -432,12 +432,12 @@ proc init*(ctx: var TwofishContext, key: ptr byte, nkey: int = 0) {.inline.} = proc clear*(ctx: var TwofishContext) {.inline.} = burnMem(ctx) -proc encrypt*(ctx: var TwofishContext, input: openarray[byte], - output: var openarray[byte]) {.inline.} = +proc encrypt*(ctx: var TwofishContext, input: openArray[byte], + output: var openArray[byte]) {.inline.} = twofishEncrypt(ctx, input, output) -proc decrypt*(ctx: var TwofishContext, input: openarray[byte], - output: var openarray[byte]) {.inline.} = +proc decrypt*(ctx: var TwofishContext, input: openArray[byte], + output: var openArray[byte]) {.inline.} = twofishDecrypt(ctx, input, output) proc encrypt*(ctx: var TwofishContext, inbytes: ptr byte, diff --git a/vendor/nimcrypto/nimcrypto/utils.nim b/vendor/nimcrypto/nimcrypto/utils.nim index b110a82f4..12cdcb8ef 100644 --- a/vendor/nimcrypto/nimcrypto/utils.nim +++ b/vendor/nimcrypto/nimcrypto/utils.nim @@ -57,7 +57,7 @@ proc hexDigit(x: int, lowercase: bool = false): char = off += 0x20 char(0x30'u32 + uint32(x) + (off and not((uint32(x) - 10) shr 8))) -proc bytesToHex*(src: openarray[byte], dst: var openarray[char], +proc bytesToHex*(src: openArray[byte], dst: var openArray[char], flags: set[HexFlags]): int = if len(dst) == 0: (len(src) shl 1) @@ -89,7 +89,7 @@ proc bytesToHex*(src: openarray[byte], dst: var openarray[char], k -proc hexToBytes*(src: openarray[char], dst: var openarray[byte], +proc hexToBytes*(src: openArray[char], dst: var openArray[byte], flags: set[HexFlags]): int = var halfbyte = false var acc: byte @@ -142,12 +142,12 @@ proc hexToBytes*(src: openarray[char], dst: var openarray[byte], return v return v -proc toHex*(a: openarray[byte], flags: set[HexFlags]): string = +proc toHex*(a: openArray[byte], flags: set[HexFlags]): string = var res = newString(len(a) shl 1) discard bytesToHex(a, res, flags) res -proc toHex*(a: openarray[byte], lowercase: bool = false): string {.inline.} = +proc toHex*(a: openArray[byte], lowercase: bool = false): string {.inline.} = var res = newString(len(a) shl 1) if lowercase: discard bytesToHex(a, res, {HexFlags.LowerCase}) @@ -155,7 +155,7 @@ proc toHex*(a: openarray[byte], lowercase: bool = false): string {.inline.} = discard bytesToHex(a, res, {}) res -proc hexToBytes*(a: string, output: var openarray[byte]) {.inline.} = +proc hexToBytes*(a: string, output: var openArray[byte]) {.inline.} = discard hexToBytes(a, output, {HexFlags.SkipPrefix, HexFlags.PadOdd}) proc fromHex*(a: string): seq[byte] = @@ -181,7 +181,7 @@ proc burnMem*(p: pointer, size: Natural) = sp = cast[ptr byte](cast[uint](sp) + 1) dec(c) -proc burnArray*[T](a: var openarray[T]) {.inline.} = +proc burnArray*[T](a: var openArray[T]) {.inline.} = if len(a) > 0: burnMem(addr a[0], len(a) * sizeof(T)) @@ -207,7 +207,7 @@ proc isFullZero*(p: pointer, size: Natural): bool = dec(c) result = (counter == 0) -proc isFullZero*[T](a: openarray[T]): bool {.inline.} = +proc isFullZero*[T](a: openArray[T]): bool {.inline.} = result = true if len(a) > 0: result = isFullZero(unsafeAddr a[0], len(a) * sizeof(T)) @@ -327,7 +327,7 @@ template beSwap64*(a: uint64): uint64 = else: (a) -template beLoad32*[T: byte|char](src: openarray[T], srco: int): uint32 = +template beLoad32*[T: byte|char](src: openArray[T], srco: int): uint32 = when nimvm: (uint32(src[srco + 0]) shl 24) or (uint32(src[srco + 1]) shl 16) or (uint32(src[srco + 2]) shl 8) or uint32(src[srco + 3]) @@ -335,7 +335,7 @@ template beLoad32*[T: byte|char](src: openarray[T], srco: int): uint32 = let p = cast[ptr uint32](unsafeAddr src[srco])[] leSwap32(p) -template leLoad32*[T: byte|char](src: openarray[T], srco: int): uint32 = +template leLoad32*[T: byte|char](src: openArray[T], srco: int): uint32 = when nimvm: (uint32(src[srco + 3]) shl 24) or (uint32(src[srco + 2]) shl 16) or (uint32(src[srco + 1]) shl 8) or uint32(src[srco + 0]) @@ -343,7 +343,7 @@ template leLoad32*[T: byte|char](src: openarray[T], srco: int): uint32 = let p = cast[ptr uint32](unsafeAddr src[srco])[] beSwap32(p) -template beLoad64*[T: byte|char](src: openarray[T], srco: int): uint64 = +template beLoad64*[T: byte|char](src: openArray[T], srco: int): uint64 = when nimvm: (uint64(src[srco + 0]) shl 56) or (uint64(src[srco + 1]) shl 48) or (uint64(src[srco + 2]) shl 40) or (uint64(src[srco + 3]) shl 32) or @@ -353,7 +353,7 @@ template beLoad64*[T: byte|char](src: openarray[T], srco: int): uint64 = let p = cast[ptr uint64](unsafeAddr src[srco])[] leSwap64(p) -template leLoad64*[T: byte|char](src: openarray[T], srco: int): uint64 = +template leLoad64*[T: byte|char](src: openArray[T], srco: int): uint64 = when nimvm: (uint64(src[srco + 7]) shl 56) or (uint64(src[srco + 6]) shl 48) or (uint64(src[srco + 5]) shl 40) or (uint64(src[srco + 4]) shl 32) or @@ -363,7 +363,7 @@ template leLoad64*[T: byte|char](src: openarray[T], srco: int): uint64 = let p = cast[ptr uint64](unsafeAddr src[srco])[] beSwap64(p) -template beStore32*(dst: var openarray[byte], so: int, v: uint32) = +template beStore32*(dst: var openArray[byte], so: int, v: uint32) = when nimvm: dst[so + 0] = byte((v shr 24) and 0xFF'u32) dst[so + 1] = byte((v shr 16) and 0xFF'u32) @@ -372,7 +372,7 @@ template beStore32*(dst: var openarray[byte], so: int, v: uint32) = else: cast[ptr uint32](addr dst[so])[] = leSwap32(v) -template beStore64*(dst: var openarray[byte], so: int, v: uint64) = +template beStore64*(dst: var openArray[byte], so: int, v: uint64) = when nimvm: dst[so + 0] = byte((v shr 56) and 0xFF'u64) dst[so + 1] = byte((v shr 48) and 0xFF'u64) @@ -385,7 +385,7 @@ template beStore64*(dst: var openarray[byte], so: int, v: uint64) = else: cast[ptr uint64](addr dst[so])[] = leSwap64(v) -template leStore32*(dst: var openarray[byte], so: int, v: uint32) = +template leStore32*(dst: var openArray[byte], so: int, v: uint32) = when nimvm: dst[so + 0] = byte(v and 0xFF'u32) dst[so + 1] = byte((v shr 8) and 0xFF'u32) @@ -394,7 +394,7 @@ template leStore32*(dst: var openarray[byte], so: int, v: uint32) = else: cast[ptr uint32](addr dst[so])[] = beSwap32(v) -template leStore64*(dst: var openarray[byte], so: int, v: uint64) = +template leStore64*(dst: var openArray[byte], so: int, v: uint64) = when nimvm: dst[so + 0] = byte(v and 0xFF'u64) dst[so + 1] = byte((v shr 8) and 0xFF'u64) @@ -407,8 +407,8 @@ template leStore64*(dst: var openarray[byte], so: int, v: uint64) = else: cast[ptr uint64](addr dst[so])[] = beSwap64(v) -template copyMem*[A, B](dst: var openarray[A], dsto: int, - src: openarray[B], srco: int, +template copyMem*[A, B](dst: var openArray[A], dsto: int, + src: openArray[B], srco: int, length: int) = when nimvm: for i in 0 ..< length: diff --git a/vendor/nimcrypto/tests/bootstrap.bat b/vendor/nimcrypto/tests/bootstrap.bat index 9e242fb9e..620d2eb4b 100644 --- a/vendor/nimcrypto/tests/bootstrap.bat +++ b/vendor/nimcrypto/tests/bootstrap.bat @@ -29,7 +29,7 @@ ECHO Building Nim [%NIM_BRANCH%] (%NIM_ARCH%) in %NIM_DIR% git clone https://github.com/nim-lang/Nim.git "%CD%\%NIM_DIR%" CD "%CD%\%NIM_DIR%" IF NOT "%NIM_BRANCH%" == "devel" ( - git checkout "tags/%NIM_BRANCH%" -b "%NIM_BRANCH%" + git checkout "%NIM_BRANCH%" ) ELSE ( git checkout devel ) diff --git a/vendor/nimcrypto/tests/bootstrap.sh b/vendor/nimcrypto/tests/bootstrap.sh index ce9b9fb17..f4301064f 100755 --- a/vendor/nimcrypto/tests/bootstrap.sh +++ b/vendor/nimcrypto/tests/bootstrap.sh @@ -17,7 +17,7 @@ function build_nim { if [ "${NIM_BRANCH}" = "devel" ]; then git checkout devel else - git checkout "tags/${NIM_BRANCH}" -b "${NIM_BRANCH}" + git checkout "${NIM_BRANCH}" fi git clone --depth 1 https://github.com/nim-lang/csources_v1 cd csources_v1 && sh build.sh diff --git a/vendor/nimcrypto/tests/testblake2.nim b/vendor/nimcrypto/tests/testblake2.nim index b2c0b2a47..6e6bcf30a 100644 --- a/vendor/nimcrypto/tests/testblake2.nim +++ b/vendor/nimcrypto/tests/testblake2.nim @@ -209,7 +209,7 @@ suite "BLAKE2B/BLAKE2S Tests": "E6C8125637438D0905B749F46560AC89FD471CF8692E28FAB982F73F019B83A9" ] - proc keyDigest(a: openarray[byte]): string = + proc keyDigest(a: openArray[byte]): string = var ctx: blake2_256 ctx.init(fromHex(stripSpaces(keys[0]))) ctx.update(a) @@ -306,7 +306,7 @@ suite "BLAKE2B/BLAKE2S Tests": E2228152A3C4BBBE72FC3B12629528CFBB09FE630F0474339F54ABF453E2ED52""" ] - proc keyDigest(a: openarray[byte]): string = + proc keyDigest(a: openArray[byte]): string = var ctx: blake2_512 ctx.init(fromHex(stripSpaces(keys[0]))) ctx.update(a) diff --git a/vendor/nimcrypto/tests/testkdf.nim b/vendor/nimcrypto/tests/testkdf.nim index af11b9644..899353f2f 100644 --- a/vendor/nimcrypto/tests/testkdf.nim +++ b/vendor/nimcrypto/tests/testkdf.nim @@ -470,7 +470,7 @@ suite "PBKDF2-HMAC-SHA1/SHA224/256/384/512 tests suite": D7""" ] - proc compare(x: openarray[byte], y: openarray[byte]): bool = + proc compare(x: openArray[byte], y: openArray[byte]): bool = result = false if len(x) == len(y): result = equalMem(unsafeAddr x[0], unsafeAddr y[0], len(x)) diff --git a/vendor/nimcrypto/tests/testkeccak.nim b/vendor/nimcrypto/tests/testkeccak.nim index d7776fba2..9b5f904e3 100644 --- a/vendor/nimcrypto/tests/testkeccak.nim +++ b/vendor/nimcrypto/tests/testkeccak.nim @@ -572,7 +572,7 @@ suite "KECCAK/SHA3 Tests": dcheck256 == stripSpaces(sdigest256[i]) dcheck384 == stripSpaces(sdigest384[i]) dcheck512 == stripSpaces(sdigest512[i]) - # openarray[T] test + # openArray[T] test check: $sha3_224.digest(msg) == stripSpaces(sdigest224[i]) $sha3_256.digest(msg) == stripSpaces(sdigest256[i]) diff --git a/waku/common/config_bridge.nim b/waku/common/config_bridge.nim index 8fbde9df8..463d9d48a 100644 --- a/waku/common/config_bridge.nim +++ b/waku/common/config_bridge.nim @@ -106,7 +106,7 @@ type nodekeyV2* {. desc: "P2P node private key as hex" - defaultValue: crypto.PrivateKey.random(Secp256k1, keys.newRng()[]).tryGet() + defaultValue: crypto.PrivateKey.random(Secp256k1, crypto.newRng()[]).tryGet() name: "nodekey-v2" }: crypto.PrivateKey store* {. diff --git a/waku/common/wakubridge.nim b/waku/common/wakubridge.nim index 80cb24c6d..3925f6664 100644 --- a/waku/common/wakubridge.nim +++ b/waku/common/wakubridge.nim @@ -49,7 +49,7 @@ type nodev2*: WakuNode nodev2PubsubTopic: wakunode2.Topic # Pubsub topic to bridge to/from seen: seq[hashes.Hash] # FIFO queue of seen WakuMessages. Used for deduplication. - rng: ref BrHmacDrbgContext + rng: ref HmacDrbgContext v1Pool: seq[Node] # Pool of v1 nodes for possible connections targetV1Peers: int # Target number of v1 peers to maintain started: bool # Indicates that bridge is running @@ -215,7 +215,7 @@ proc new*(T: type WakuBridge, nodev1Key: keys.KeyPair, nodev1Address: Address, powRequirement = 0.002, - rng: ref BrHmacDrbgContext, + rng: ref HmacDrbgContext, topicInterest = none(seq[waku_protocol.Topic]), bloom = some(fullBloom()), # NodeV2 initialisation @@ -233,7 +233,7 @@ proc new*(T: type WakuBridge, var nodev1 = newEthereumNode(keys = nodev1Key, address = nodev1Address, networkId = NetworkId(1), chain = nil, clientId = ClientIdV1, - addAllCapabilities = false, rng = rng) + addAllCapabilities = false, bindUdpPort = nodev1Address.udpPort, bindTcpPort = nodev1Address.tcpPort, rng = rng) nodev1.addCapability Waku # Always enable Waku protocol @@ -268,7 +268,7 @@ proc start*(bridge: WakuBridge) {.async.} = debug "Start listening on Waku v1" # Start listening on Waku v1 node - let connectedFut = bridge.nodev1.connectToNetwork(@[], + let connectedFut = bridge.nodev1.connectToNetwork( true, # Always enable listening false # Disable discovery (only discovery v4 is currently supported) ) @@ -284,7 +284,7 @@ proc start*(bridge: WakuBridge) {.async.} = # Always mount relay for bridge. # `triggerSelf` is false on a `bridge` to avoid duplicates - bridge.nodev2.mountRelay(triggerSelf = false) + await bridge.nodev2.mountRelay(triggerSelf = false) # Bridging # Handle messages on Waku v1 and bridge to Waku v2 @@ -317,9 +317,9 @@ proc stop*(bridge: WakuBridge) {.async.} = {.pop.} # @TODO confutils.nim(775, 17) Error: can raise an unlisted exception: ref IOError when isMainModule: import - eth/p2p/whispernodes, libp2p/nameresolving/dnsresolver, ./utils/nat, + ../whisper/whispernodes, ../v1/node/rpc/wakusim, ../v1/node/rpc/waku, ../v1/node/rpc/key_storage, @@ -424,13 +424,13 @@ when isMainModule: # Now load rest of config # Mount configured Waku v2 protocols - mountLibp2pPing(bridge.nodev2) + waitFor mountLibp2pPing(bridge.nodev2) if conf.store: - mountStore(bridge.nodev2, persistMessages = false) # Bridge does not persist messages + waitFor mountStore(bridge.nodev2, persistMessages = false) # Bridge does not persist messages if conf.filter: - mountFilter(bridge.nodev2) + waitFor mountFilter(bridge.nodev2) if conf.staticnodesV2.len > 0: waitFor connectToNodes(bridge.nodev2, conf.staticnodesV2) diff --git a/waku/v1/node/rpc/waku.nim b/waku/v1/node/rpc/waku.nim index ebf94d754..be8db8876 100644 --- a/waku/v1/node/rpc/waku.nim +++ b/waku/v1/node/rpc/waku.nim @@ -10,7 +10,7 @@ from stew/byteutils import hexToSeqByte, hexToByteArray # Blatant copy of Whisper RPC but for the Waku protocol proc setupWakuRPC*(node: EthereumNode, keys: KeyStorage, rpcsrv: RpcServer, - rng: ref BrHmacDrbgContext) = + rng: ref HmacDrbgContext) = rpcsrv.rpc("waku_version") do() -> string: ## Returns string of the current Waku protocol version. diff --git a/waku/v1/node/wakunode1.nim b/waku/v1/node/wakunode1.nim index 1f36128cb..c831f559a 100644 --- a/waku/v1/node/wakunode1.nim +++ b/waku/v1/node/wakunode1.nim @@ -5,15 +5,15 @@ import metrics, metrics/chronicles_support, metrics/chronos_httpserver, stew/shims/net as stewNet, eth/[keys, p2p], eth/common/utils, - eth/p2p/[discovery, enode, peer_pool, bootnodes, whispernodes], - ../../whisper/whisper_protocol, + eth/p2p/[discovery, enode, peer_pool, bootnodes], + ../../whisper/[whispernodes, whisper_protocol], ../protocol/[waku_protocol, waku_bridge], ../../common/utils/nat, ./rpc/[waku, wakusim, key_storage], ./waku_helpers, ./config const clientId = "Nimbus waku node" -proc run(config: WakuNodeConf, rng: ref BrHmacDrbgContext) +proc run(config: WakuNodeConf, rng: ref HmacDrbgContext) {.raises: [Defect, ValueError, RpcBindError, CatchableError, Exception]} = ## `udpPort` is only supplied to satisfy underlying APIs but is not ## actually a supported transport. @@ -32,10 +32,15 @@ proc run(config: WakuNodeConf, rng: ref BrHmacDrbgContext) Address(ip: ipExt.get(), tcpPort: Port(config.tcpPort + config.portsShift), udpPort: Port(udpPort + config.portsShift)) + bootnodes = if config.bootnodes.len > 0: setBootNodes(config.bootnodes) + elif config.fleet == prod: setBootNodes(StatusBootNodes) + elif config.fleet == staging: setBootNodes(StatusBootNodesStaging) + elif config.fleet == test : setBootNodes(StatusBootNodesTest) + else: @[] # Set-up node var node = newEthereumNode(config.nodekey, address, NetworkId(1), nil, clientId, - addAllCapabilities = false, rng = rng) + addAllCapabilities = false, bootstrapNodes = bootnodes, bindUdpPort = address.udpPort, bindTcpPort = address.tcpPort, rng = rng) if not config.bootnodeOnly: node.addCapability Waku # Always enable Waku protocol var topicInterest: Option[seq[waku_protocol.Topic]] @@ -57,14 +62,7 @@ proc run(config: WakuNodeConf, rng: ref BrHmacDrbgContext) if config.whisperBridge: node.shareMessageQueue() - # TODO: Status fleet bootnodes are discv5? That will not work. - let bootnodes = if config.bootnodes.len > 0: setBootNodes(config.bootnodes) - elif config.fleet == prod: setBootNodes(StatusBootNodes) - elif config.fleet == staging: setBootNodes(StatusBootNodesStaging) - elif config.fleet == test : setBootNodes(StatusBootNodesTest) - else: @[] - - let connectedFut = node.connectToNetwork(bootnodes, not config.noListen, + let connectedFut = node.connectToNetwork(not config.noListen, config.discovery) connectedFut.callback = proc(data: pointer) {.gcsafe.} = {.gcsafe.}: diff --git a/waku/v1/protocol/waku_protocol.nim b/waku/v1/protocol/waku_protocol.nim index be58a09a4..b0cd79d3d 100644 --- a/waku/v1/protocol/waku_protocol.nim +++ b/waku/v1/protocol/waku_protocol.nim @@ -72,7 +72,7 @@ type maxMsgSize*: uint32 confirmationsEnabled*: bool rateLimits*: Option[RateLimits] - topics*: Option[seq[Topic]] + topics*: Option[seq[whisper_types.Topic]] Accounting* = ref object sent*: uint @@ -84,7 +84,7 @@ type bloom*: Bloom isLightNode*: bool trusted*: bool - topics*: Option[seq[Topic]] + topics*: Option[seq[whisper_types.Topic]] received: HashSet[Hash] accounting*: Accounting @@ -112,7 +112,7 @@ type lightNode*: Option[bool] confirmationsEnabled*: Option[bool] rateLimits*: Option[RateLimits] - topicInterest*: Option[seq[Topic]] + topicInterest*: Option[seq[whisper_types.Topic]] KeyKind* = enum powRequirementKey, @@ -191,7 +191,7 @@ proc read*(rlp: var Rlp, T: typedesc[StatusOptions]): of rateLimitsKey: result.rateLimits = some(rlp.read(RateLimits)) of topicInterestKey: - result.topicInterest = some(rlp.read(seq[Topic])) + result.topicInterest = some(rlp.read(seq[whisper_types.Topic])) proc allowed*(msg: Message, config: WakuConfig): bool = # Check max msg size, already happens in RLPx but there is a specific waku @@ -235,7 +235,7 @@ proc initProtocolState*(network: WakuNetwork, node: EthereumNode) {.gcsafe.} = network.config.confirmationsEnabled = false network.config.rateLimits = none(RateLimits) network.config.maxMsgSize = defaultMaxMsgSize - network.config.topics = none(seq[Topic]) + network.config.topics = none(seq[whisper_types.Topic]) asyncSpawn node.run(network) p2pProtocol Waku(version = wakuVersion, @@ -349,7 +349,7 @@ p2pProtocol Waku(version = wakuVersion, peer.state.topics = options.topicInterest elif options.bloomFilter.isSome(): peer.state.bloom = options.bloomFilter.get() - peer.state.topics = none(seq[Topic]) + peer.state.topics = none(seq[whisper_types.Topic]) if options.powRequirement.isSome(): peer.state.powRequirement = options.powRequirement.get() @@ -498,7 +498,7 @@ proc queueMessage(node: EthereumNode, msg: Message): bool = # Public EthereumNode calls ---------------------------------------------------- proc postEncoded*(node: EthereumNode, ttl: uint32, - topic: Topic, encodedPayload: seq[byte], + topic: whisper_types.Topic, encodedPayload: seq[byte], powTime = 1'f, powTarget = defaultMinPow, targetPeer = none[NodeId]()): bool = @@ -548,7 +548,7 @@ proc postEncoded*(node: EthereumNode, ttl: uint32, proc postMessage*(node: EthereumNode, pubKey = none[PublicKey](), symKey = none[SymKey](), src = none[PrivateKey](), - ttl: uint32, topic: Topic, payload: seq[byte], + ttl: uint32, topic: whisper_types.Topic, payload: seq[byte], padding = none[seq[byte]](), powTime = 1'f, powTarget = defaultMinPow, targetPeer = none[NodeId]()): bool = @@ -614,7 +614,7 @@ proc setBloomFilter*(node: EthereumNode, bloom: Bloom) {.async.} = # NOTE: do we need a tolerance of old bloom filter for some time? node.protocolState(Waku).config.bloom = some(bloom) # reset topics - node.protocolState(Waku).config.topics = none(seq[Topic]) + node.protocolState(Waku).config.topics = none(seq[whisper_types.Topic]) var futures: seq[Future[void]] = @[] let list = StatusOptions(bloomFilter: some(bloom)) @@ -624,7 +624,7 @@ proc setBloomFilter*(node: EthereumNode, bloom: Bloom) {.async.} = # Exceptions from sendMsg will not be raised await allFutures(futures) -proc setTopicInterest*(node: EthereumNode, topics: seq[Topic]): +proc setTopicInterest*(node: EthereumNode, topics: seq[whisper_types.Topic]): Future[bool] {.async.} = if topics.len > topicInterestMax: return false diff --git a/waku/v2/node/config.nim b/waku/v2/node/config.nim index 6f73c62fd..9015c2351 100644 --- a/waku/v2/node/config.nim +++ b/waku/v2/node/config.nim @@ -35,7 +35,7 @@ type nodekey* {. desc: "P2P node private key as 64 char hex string.", - defaultValue: crypto.PrivateKey.random(Secp256k1, keys.newRng()[]).tryGet() + defaultValue: crypto.PrivateKey.random(Secp256k1, crypto.newRng()[]).tryGet() name: "nodekey" }: crypto.PrivateKey listenAddress* {. diff --git a/waku/v2/node/discv5/waku_discv5.nim b/waku/v2/node/discv5/waku_discv5.nim index 065d63d96..eb979962c 100644 --- a/waku/v2/node/discv5/waku_discv5.nim +++ b/waku/v2/node/discv5/waku_discv5.nim @@ -108,7 +108,7 @@ proc new*(T: type WakuDiscoveryV5, privateKey: keys.PrivateKey, flags: WakuEnrBitfield, enrFields: openArray[(string, seq[byte])], - rng: ref BrHmacDrbgContext, + rng: ref HmacDrbgContext, discv5Config: protocol.DiscoveryConfig = protocol.defaultDiscoveryConfig): T = ## TODO: consider loading from a configurable bootstrap file @@ -140,7 +140,7 @@ proc new*(T: type WakuDiscoveryV5, privateKey: keys.PrivateKey, flags: WakuEnrBitfield, enrFields: openArray[(string, seq[byte])], - rng: ref BrHmacDrbgContext, + rng: ref HmacDrbgContext, discv5Config: protocol.DiscoveryConfig = protocol.defaultDiscoveryConfig): T = var bootstrapEnrs: seq[enr.Record] diff --git a/waku/v2/node/jsonrpc/jsonrpc_utils.nim b/waku/v2/node/jsonrpc/jsonrpc_utils.nim index 461f1474b..1f09b402a 100644 --- a/waku/v2/node/jsonrpc/jsonrpc_utils.nim +++ b/waku/v2/node/jsonrpc/jsonrpc_utils.nim @@ -54,7 +54,7 @@ proc toWakuMessage*(relayMessage: WakuRelayMessage, version: uint32): WakuMessag version: version, timestamp: t) -proc toWakuMessage*(relayMessage: WakuRelayMessage, version: uint32, rng: ref BrHmacDrbgContext, symkey: Option[SymKey], pubKey: Option[keys.PublicKey]): WakuMessage = +proc toWakuMessage*(relayMessage: WakuRelayMessage, version: uint32, rng: ref HmacDrbgContext, symkey: Option[SymKey], pubKey: Option[keys.PublicKey]): WakuMessage = # @TODO global definition for default content topic const defaultCT = ContentTopic("/waku/2/default-content/proto") diff --git a/waku/v2/node/jsonrpc/private_api.nim b/waku/v2/node/jsonrpc/private_api.nim index eec46c38e..987f31fdb 100644 --- a/waku/v2/node/jsonrpc/private_api.nim +++ b/waku/v2/node/jsonrpc/private_api.nim @@ -3,6 +3,7 @@ import std/[tables,sequtils], chronicles, + eth/keys, json_rpc/rpcserver, nimcrypto/sysrand, ../wakunode2, @@ -17,8 +18,7 @@ logScope: const futTimeout* = 5.seconds # Max time to wait for futures -proc installPrivateApiHandlers*(node: WakuNode, rpcsrv: RpcServer, rng: ref BrHmacDrbgContext, topicCache: TopicCache) = - +proc installPrivateApiHandlers*(node: WakuNode, rpcsrv: RpcServer, topicCache: TopicCache) = ## Private API version 1 definitions ## Definitions for symmetric cryptography @@ -38,7 +38,7 @@ proc installPrivateApiHandlers*(node: WakuNode, rpcsrv: RpcServer, rng: ref BrHm debug "post_waku_v2_private_v1_symmetric_message" let msg = message.toWakuMessage(version = 1, - rng = rng, + rng = node.rng, pubKey = none(waku_payload.PublicKey), symkey = some(symkey.toSymKey())) @@ -73,7 +73,7 @@ proc installPrivateApiHandlers*(node: WakuNode, rpcsrv: RpcServer, rng: ref BrHm ## Generates and returns a public/private key pair for asymmetric message encryption and decryption. debug "get_waku_v2_private_v1_asymmetric_keypair" - let privKey = waku_payload.PrivateKey.random(rng[]) + let privKey = waku_payload.PrivateKey.random(node.rng[]) return WakuKeyPair(seckey: privKey, pubkey: privKey.toPublicKey()) @@ -82,7 +82,7 @@ proc installPrivateApiHandlers*(node: WakuNode, rpcsrv: RpcServer, rng: ref BrHm debug "post_waku_v2_private_v1_asymmetric_message" let msg = message.toWakuMessage(version = 1, - rng = rng, + rng = node.rng, symkey = none(SymKey), pubKey = some(publicKey.toPublicKey())) diff --git a/waku/v2/node/rest/relay/relay_api.nim b/waku/v2/node/rest/relay/relay_api.nim index 1030e7ae7..967b71434 100644 --- a/waku/v2/node/rest/relay/relay_api.nim +++ b/waku/v2/node/rest/relay/relay_api.nim @@ -36,7 +36,7 @@ proc installRelayPostSubscriptionsV1Handler*(router: var RestRouter, node: WakuN if contentBody.isNone(): return RestApiResponse.badRequest() - let reqBodyContentType = MediaType.init(contentBody.get().contentType) + let reqBodyContentType = MediaType.init($contentBody.get().contentType) if reqBodyContentType != MIMETYPE_JSON: return RestApiResponse.badRequest() @@ -67,7 +67,7 @@ proc installRelayDeleteSubscriptionsV1Handler*(router: var RestRouter, node: Wak if contentBody.isNone(): return RestApiResponse.badRequest() - let reqBodyContentType = MediaType.init(contentBody.get().contentType) + let reqBodyContentType = MediaType.init($contentBody.get().contentType) if reqBodyContentType != MIMETYPE_JSON: return RestApiResponse.badRequest() @@ -124,7 +124,7 @@ proc installRelayPostMessagesV1Handler*(router: var RestRouter, node: WakuNode) if contentBody.isNone(): return RestApiResponse.badRequest() - let reqBodyContentType = MediaType.init(contentBody.get().contentType) + let reqBodyContentType = MediaType.init($contentBody.get().contentType) if reqBodyContentType != MIMETYPE_JSON: return RestApiResponse.badRequest() diff --git a/waku/v2/node/waku_payload.nim b/waku/v2/node/waku_payload.nim index 941d39a19..8a849de94 100644 --- a/waku/v2/node/waku_payload.nim +++ b/waku/v2/node/waku_payload.nim @@ -65,7 +65,7 @@ proc decodePayload*(message: WakuMessage, keyInfo: KeyInfo): # TODO: same story as for `decodedPayload`, but then regarding the `Payload` # object. -proc encode*(payload: Payload, version: uint32, rng: var BrHmacDrbgContext): +proc encode*(payload: Payload, version: uint32, rng: var HmacDrbgContext): WakuResult[seq[byte]] = case version of 0: diff --git a/waku/v2/node/wakunode2.nim b/waku/v2/node/wakunode2.nim index 28366a067..9eb6fa309 100644 --- a/waku/v2/node/wakunode2.nim +++ b/waku/v2/node/wakunode2.nim @@ -419,7 +419,7 @@ proc info*(node: WakuNode): WakuInfo = let wakuInfo = WakuInfo(listenAddresses: listenStr, enrUri: enrUri) return wakuInfo -proc mountFilter*(node: WakuNode, filterTimeout: Duration = WakuFilterTimeout) {.raises: [Defect, LPError]} = +proc mountFilter*(node: WakuNode, filterTimeout: Duration = WakuFilterTimeout) {.async, raises: [Defect, LPError]} = info "mounting filter" proc filterHandler(requestId: string, msg: MessagePush) {.async, gcsafe.} = @@ -434,18 +434,26 @@ proc mountFilter*(node: WakuNode, filterTimeout: Duration = WakuFilterTimeout) { waku_node_messages.inc(labelValues = ["filter"]) node.wakuFilter = WakuFilter.init(node.peerManager, node.rng, filterHandler, filterTimeout) + if node.started: + # Node has started already. Let's start filter too. + await node.wakuFilter.start() + node.switch.mount(node.wakuFilter, protocolMatcher(WakuFilterCodec)) + # NOTE: If using the swap protocol, it must be mounted before store. This is # because store is using a reference to the swap protocol. -proc mountSwap*(node: WakuNode, swapConfig: SwapConfig = SwapConfig.init()) {.raises: [Defect, LPError].} = +proc mountSwap*(node: WakuNode, swapConfig: SwapConfig = SwapConfig.init()) {.async, raises: [Defect, LPError].} = info "mounting swap", mode = $swapConfig.mode - node.wakuSwap = WakuSwap.init(node.peerManager, node.rng, swapConfig) - node.switch.mount(node.wakuSwap, protocolMatcher(WakuSwapCodec)) - # NYI - Do we need this? - #node.subscriptions.subscribe(WakuSwapCodec, node.wakuSwap.subscription()) -proc mountStore*(node: WakuNode, store: MessageStore = nil, persistMessages: bool = false, capacity = StoreDefaultCapacity, isSqliteOnly = false) {.raises: [Defect, LPError].} = + node.wakuSwap = WakuSwap.init(node.peerManager, node.rng, swapConfig) + if node.started: + # Node has started already. Let's start swap too. + await node.wakuSwap.start() + + node.switch.mount(node.wakuSwap, protocolMatcher(WakuSwapCodec)) + +proc mountStore*(node: WakuNode, store: MessageStore = nil, persistMessages: bool = false, capacity = StoreDefaultCapacity, isSqliteOnly = false) {.async, raises: [Defect, LPError].} = info "mounting store" if node.wakuSwap.isNil: @@ -454,6 +462,10 @@ proc mountStore*(node: WakuNode, store: MessageStore = nil, persistMessages: boo else: debug "mounting store with swap" node.wakuStore = WakuStore.init(node.peerManager, node.rng, store, node.wakuSwap, persistMessages=persistMessages, capacity=capacity, isSqliteOnly=isSqliteOnly) + + if node.started: + # Node has started already. Let's start store too. + await node.wakuStore.start() node.switch.mount(node.wakuStore, protocolMatcher(WakuStoreCodec)) @@ -488,11 +500,10 @@ proc startRelay*(node: WakuNode) {.async.} = proc mountRelay*(node: WakuNode, topics: seq[string] = newSeq[string](), - relayMessages = true, triggerSelf = true, peerExchangeHandler = none(RoutingRecordsHandler)) # @TODO: Better error handling: CatchableError is raised by `waitFor` - {.gcsafe, raises: [Defect, InitializationError, LPError, CatchableError].} = + {.async, gcsafe, raises: [Defect, InitializationError, LPError, CatchableError].} = proc msgIdProvider(m: messages.Message): Result[MessageID, ValidationResult] = let mh = MultiHash.digest("sha2-256", m.data) @@ -510,7 +521,7 @@ proc mountRelay*(node: WakuNode, maxMessageSize = MaxWakuMessageSize ) - info "mounting relay", relayMessages=relayMessages + info "mounting relay" ## The default relay topics is the union of ## all configured topics plus the hard-coded defaultTopic(s) @@ -521,24 +532,16 @@ proc mountRelay*(node: WakuNode, wakuRelay.parameters.enablePX = true # Feature flag for peer exchange in nim-libp2p wakuRelay.routingRecordsHandler.add(peerExchangeHandler.get()) - node.switch.mount(wakuRelay, protocolMatcher(WakuRelayCodec)) + node.wakuRelay = wakuRelay + if node.started: + # Node has started already. Let's start relay too. + await node.startRelay() - if relayMessages: - ## Some nodes may choose not to have the capability to relay messages (e.g. "light" nodes). - ## All nodes, however, currently require WakuRelay, regardless of desired capabilities. - ## This is to allow protocol stream negotation with relay-capable nodes to succeed. - ## Here we mount relay on the switch only, but do not proceed to subscribe to any pubsub - ## topics. We also never start the relay protocol. node.wakuRelay remains nil. - ## @TODO: in future, this WakuRelay dependency will be removed completely - node.wakuRelay = wakuRelay + node.switch.mount(wakuRelay, protocolMatcher(WakuRelayCodec)) info "relay mounted successfully" - if node.started: - # Node has started already. Let's start relay too. - waitFor node.startRelay() - -proc mountLightPush*(node: WakuNode) {.raises: [Defect, LPError].} = +proc mountLightPush*(node: WakuNode) {.async, raises: [Defect, LPError].} = info "mounting light push" if node.wakuRelay.isNil: @@ -548,9 +551,13 @@ proc mountLightPush*(node: WakuNode) {.raises: [Defect, LPError].} = debug "mounting lightpush with relay" node.wakuLightPush = WakuLightPush.init(node.peerManager, node.rng, nil, node.wakuRelay) + if node.started: + # Node has started already. Let's start lightpush too. + await node.wakuLightPush.start() + node.switch.mount(node.wakuLightPush, protocolMatcher(WakuLightPushCodec)) -proc mountLibp2pPing*(node: WakuNode) {.raises: [Defect, LPError].} = +proc mountLibp2pPing*(node: WakuNode) {.async, raises: [Defect, LPError].} = info "mounting libp2p ping protocol" try: @@ -559,7 +566,11 @@ proc mountLibp2pPing*(node: WakuNode) {.raises: [Defect, LPError].} = # This is necessary as `Ping.new*` does not have explicit `raises` requirement # @TODO: remove exception handling once explicit `raises` in ping module raise newException(LPError, "Failed to initialize ping protocol") - + + if node.started: + # Node has started already. Let's start ping too. + await node.libp2pPing.start() + node.switch.mount(node.libp2pPing) proc keepaliveLoop(node: WakuNode, keepalive: chronos.Duration) {.async.} = @@ -745,8 +756,6 @@ proc start*(node: WakuNode) {.async.} = ## ## Status: Implemented. - await node.switch.start() - # TODO Get this from WakuNode obj let peerInfo = node.switch.peerInfo info "PeerInfo", peerId = peerInfo.peerId, addrs = peerInfo.addrs @@ -762,11 +771,24 @@ proc start*(node: WakuNode) {.async.} = ## Update switch peer info with announced addrs node.updateSwitchPeerInfo() + # Start mounted protocols. For now we start each one explicitly if not node.wakuRelay.isNil: await node.startRelay() + if not node.wakuStore.isNil: + await node.wakuStore.start() + if not node.wakuFilter.isNil: + await node.wakuFilter.start() + if not node.wakuLightPush.isNil: + await node.wakuLightPush.start() + if not node.wakuSwap.isNil: + await node.wakuSwap.start() + if not node.libp2pPing.isNil: + await node.libp2pPing.start() + + await node.switch.start() + node.started = true info "Node started successfully" - node.started = true proc stop*(node: WakuNode) {.async.} = if not node.wakuRelay.isNil: @@ -1013,13 +1035,13 @@ when isMainModule: peerExchangeHandler = some(handlePeerExchange) - mountRelay(node, - conf.topics.split(" "), - relayMessages = conf.relay, # Indicates if node is capable to relay messages - peerExchangeHandler = peerExchangeHandler) + if conf.relay: + waitFor mountRelay(node, + conf.topics.split(" "), + peerExchangeHandler = peerExchangeHandler) # Keepalive mounted on all nodes - mountLibp2pPing(node) + waitFor mountLibp2pPing(node) when defined(rln): if conf.rlnRelay: @@ -1028,26 +1050,26 @@ when isMainModule: debug "could not mount WakuRlnRelay" if conf.swap: - mountSwap(node) + waitFor mountSwap(node) # TODO Set swap peer, for now should be same as store peer # Store setup if (conf.storenode != "") or (conf.store): - mountStore(node, mStorage, conf.persistMessages, conf.storeCapacity, conf.sqliteStore) + waitFor mountStore(node, mStorage, conf.persistMessages, conf.storeCapacity, conf.sqliteStore) if conf.storenode != "": setStorePeer(node, conf.storenode) # NOTE Must be mounted after relay if (conf.lightpushnode != "") or (conf.lightpush): - mountLightPush(node) + waitFor mountLightPush(node) if conf.lightpushnode != "": setLightPushPeer(node, conf.lightpushnode) # Filter setup. NOTE Must be mounted after relay if (conf.filternode != "") or (conf.filter): - mountFilter(node, filterTimeout = chronos.seconds(conf.filterTimeout)) + waitFor mountFilter(node, filterTimeout = chronos.seconds(conf.filterTimeout)) if conf.filternode != "": setFilterPeer(node, conf.filternode) @@ -1210,7 +1232,7 @@ when isMainModule: waitFor node.stop() quit(QuitSuccess) - c_signal(SIGTERM, handleSigterm) + c_signal(ansi_c.SIGTERM, handleSigterm) debug "Node setup complete" diff --git a/waku/v2/node/wakunode2_setup_rpc.nim b/waku/v2/node/wakunode2_setup_rpc.nim index 4e35467e5..352879667 100644 --- a/waku/v2/node/wakunode2_setup_rpc.nim +++ b/waku/v2/node/wakunode2_setup_rpc.nim @@ -36,7 +36,7 @@ proc startRpcServer*(node: WakuNode, rpcIp: ValidIpAddress, rpcPort: Port, conf: if conf.rpcPrivate: # Private API access allows WakuRelay functionality that # is backwards compatible with Waku v1. - installPrivateApiHandlers(node, rpcServer, node.rng, topicCache) + installPrivateApiHandlers(node, rpcServer, topicCache) if conf.filter: let messageCache = newTable[ContentTopic, seq[WakuMessage]]() diff --git a/waku/v2/node/wakunode2_types.nim b/waku/v2/node/wakunode2_types.nim index 7e3314a01..d1c1026f5 100644 --- a/waku/v2/node/wakunode2_types.nim +++ b/waku/v2/node/wakunode2_types.nim @@ -1,4 +1,5 @@ import + bearssl/rand, eth/p2p/discoveryv5/enr, libp2p/crypto/crypto, libp2p/protocols/ping, @@ -41,7 +42,7 @@ type enr*: enr.Record libp2pPing*: Ping filters*: Filters - rng*: ref BrHmacDrbgContext + rng*: ref rand.HmacDrbgContext wakuDiscv5*: WakuDiscoveryV5 announcedAddresses* : seq[MultiAddress] started*: bool # Indicates that node has started listening diff --git a/waku/v2/protocol/waku_filter/protocol.nim b/waku/v2/protocol/waku_filter/protocol.nim index d1d4d40a6..da09a1472 100644 --- a/waku/v2/protocol/waku_filter/protocol.nim +++ b/waku/v2/protocol/waku_filter/protocol.nim @@ -4,7 +4,7 @@ import chronicles, chronos, metrics, - bearssl, + bearssl/rand, libp2p/protocols/protocol, libp2p/crypto/crypto import @@ -74,7 +74,7 @@ type WakuFilterResult*[T] = Result[T, string] WakuFilter* = ref object of LPProtocol - rng*: ref BrHmacDrbgContext + rng*: ref rand.HmacDrbgContext peerManager*: PeerManager pushHandler*: MessagePushHandler subscriptions*: seq[Subscription] @@ -134,7 +134,7 @@ proc init(wf: WakuFilter) = proc init*(T: type WakuFilter, peerManager: PeerManager, - rng: ref BrHmacDrbgContext, + rng: ref rand.HmacDrbgContext, handler: MessagePushHandler, timeout: Duration = WakuFilterTimeout): T = let wf = WakuFilter(rng: rng, diff --git a/waku/v2/protocol/waku_lightpush/protocol.nim b/waku/v2/protocol/waku_lightpush/protocol.nim index 8644ef7d2..557f7badb 100644 --- a/waku/v2/protocol/waku_lightpush/protocol.nim +++ b/waku/v2/protocol/waku_lightpush/protocol.nim @@ -6,7 +6,7 @@ import chronicles, chronos, metrics, - bearssl, + bearssl/rand, libp2p/crypto/crypto import @@ -46,7 +46,7 @@ type WakuLightPushResult*[T] = Result[T, string] WakuLightPush* = ref object of LPProtocol - rng*: ref BrHmacDrbgContext + rng*: ref rand.HmacDrbgContext peerManager*: PeerManager requestHandler*: PushRequestHandler relayReference*: WakuRelay @@ -98,7 +98,7 @@ proc init*(wl: WakuLightPush) = wl.handler = handle wl.codec = WakuLightPushCodec -proc init*(T: type WakuLightPush, peerManager: PeerManager, rng: ref BrHmacDrbgContext, handler: PushRequestHandler, relay: WakuRelay = nil): T = +proc init*(T: type WakuLightPush, peerManager: PeerManager, rng: ref rand.HmacDrbgContext, handler: PushRequestHandler, relay: WakuRelay = nil): T = debug "init" let rng = crypto.newRng() let wl = WakuLightPush(rng: rng, diff --git a/waku/v2/protocol/waku_noise/noise.nim b/waku/v2/protocol/waku_noise/noise.nim index db47771cd..ca722f3f1 100644 --- a/waku/v2/protocol/waku_noise/noise.nim +++ b/waku/v2/protocol/waku_noise/noise.nim @@ -11,7 +11,7 @@ import std/[oids, options, strutils, tables] import chronos import chronicles -import bearssl +import bearssl/rand import stew/[results, byteutils, endians2] import nimcrypto/[utils, sha2, hmac] @@ -159,9 +159,9 @@ proc setCipherStateKey*(cs: var CipherState, key: ChaChaPolyKey) = cs.k = key # Generates a random Symmetric Cipher State for test purposes -proc randomCipherState*(rng: var BrHmacDrbgContext, nonce: uint64 = 0): CipherState = +proc randomCipherState*(rng: var HmacDrbgContext, nonce: uint64 = 0): CipherState = var randomCipherState: CipherState - brHmacDrbgGenerate(rng, randomCipherState.k) + hmacDrbgGenerate(rng, randomCipherState.k) setNonce(randomCipherState, nonce) return randomCipherState diff --git a/waku/v2/protocol/waku_noise/noise_handshake_processing.nim b/waku/v2/protocol/waku_noise/noise_handshake_processing.nim index 8d72a50d9..da1606d0b 100644 --- a/waku/v2/protocol/waku_noise/noise_handshake_processing.nim +++ b/waku/v2/protocol/waku_noise/noise_handshake_processing.nim @@ -7,7 +7,7 @@ import std/[oids, options, strutils, tables] import chronos import chronicles -import bearssl +import bearssl/rand import stew/[results, endians2] import nimcrypto/[utils, sha2, hmac] @@ -229,7 +229,7 @@ proc processMessagePatternPayload(hs: var HandshakeState, transportMessage: seq[ return payload # We process an input handshake message according to current handshake state and we return the next handshake step's handshake message -proc processMessagePatternTokens(rng: var BrHmacDrbgContext, hs: var HandshakeState, inputHandshakeMessage: seq[NoisePublicKey] = @[]): Result[seq[NoisePublicKey], cstring] +proc processMessagePatternTokens(rng: var rand.HmacDrbgContext, hs: var HandshakeState, inputHandshakeMessage: seq[NoisePublicKey] = @[]): Result[seq[NoisePublicKey], cstring] {.raises: [Defect, NoiseHandshakeError, NoiseMalformedHandshake, NoisePublicKeyError, NoiseDecryptTagError, NoiseNonceMaxError].} = # We retrieve current message pattern (direction + tokens) to process @@ -463,7 +463,7 @@ proc initialize*(hsPattern: HandshakePattern, ephemeralKey: KeyPair = default(Ke # Each user in a handshake alternates writing and reading of handshake messages. # If the user is writing the handshake message, the transport message (if not empty) has to be passed to transportMessage and readPayloadV2 can be left to its default value # It the user is reading the handshake message, the read payload v2 has to be passed to readPayloadV2 and the transportMessage can be left to its default values. -proc stepHandshake*(rng: var BrHmacDrbgContext, hs: var HandshakeState, readPayloadV2: PayloadV2 = default(PayloadV2), transportMessage: seq[byte] = @[]): Result[HandshakeStepResult, cstring] +proc stepHandshake*(rng: var rand.HmacDrbgContext, hs: var HandshakeState, readPayloadV2: PayloadV2 = default(PayloadV2), transportMessage: seq[byte] = @[]): Result[HandshakeStepResult, cstring] {.raises: [Defect, NoiseHandshakeError, NoiseMalformedHandshake, NoisePublicKeyError, NoiseDecryptTagError, NoiseNonceMaxError].} = var hsStepResult: HandshakeStepResult diff --git a/waku/v2/protocol/waku_noise/noise_utils.nim b/waku/v2/protocol/waku_noise/noise_utils.nim index e58bcbdfa..ed7334aaf 100644 --- a/waku/v2/protocol/waku_noise/noise_utils.nim +++ b/waku/v2/protocol/waku_noise/noise_utils.nim @@ -8,7 +8,7 @@ import std/[oids, options, strutils, tables, sequtils] import chronos import chronicles -import bearssl +import bearssl/rand import stew/[results, endians2, byteutils] import nimcrypto/[utils, sha2, hmac] @@ -28,9 +28,9 @@ logScope: ################################# # Generates random byte sequences of given size -proc randomSeqByte*(rng: var BrHmacDrbgContext, size: int): seq[byte] = +proc randomSeqByte*(rng: var HmacDrbgContext, size: int): seq[byte] = var output = newSeq[byte](size.uint32) - brHmacDrbgGenerate(rng, output) + hmacDrbgGenerate(rng, output) return output # Pads a payload according to PKCS#7 as per RFC 5652 https://datatracker.ietf.org/doc/html/rfc5652#section-6.3 @@ -69,7 +69,7 @@ proc isDefault*[T](value: T): bool = ################################# # Generate random (public, private) Elliptic Curve key pairs -proc genKeyPair*(rng: var BrHmacDrbgContext): KeyPair = +proc genKeyPair*(rng: var HmacDrbgContext): KeyPair = var keyPair: KeyPair keyPair.privateKey = EllipticCurveKey.random(rng) keyPair.publicKey = keyPair.privateKey.public() @@ -158,18 +158,18 @@ proc dh*(private: EllipticCurveKey, public: EllipticCurveKey): EllipticCurveKey ################################# # Generates a random ChaChaPolyKey for testing encryption/decryption -proc randomChaChaPolyKey*(rng: var BrHmacDrbgContext): ChaChaPolyKey = +proc randomChaChaPolyKey*(rng: var HmacDrbgContext): ChaChaPolyKey = var key: ChaChaPolyKey - brHmacDrbgGenerate(rng, key) + hmacDrbgGenerate(rng, key) return key # Generates a random ChaChaPoly Cipher State for testing encryption/decryption -proc randomChaChaPolyCipherState*(rng: var BrHmacDrbgContext): ChaChaPolyCipherState = +proc randomChaChaPolyCipherState*(rng: var HmacDrbgContext): ChaChaPolyCipherState = var randomCipherState: ChaChaPolyCipherState randomCipherState.k = randomChaChaPolyKey(rng) - brHmacDrbgGenerate(rng, randomCipherState.nonce) + hmacDrbgGenerate(rng, randomCipherState.nonce) randomCipherState.ad = newSeq[byte](32) - brHmacDrbgGenerate(rng, randomCipherState.ad) + hmacDrbgGenerate(rng, randomCipherState.ad) return randomCipherState ################################################################# @@ -190,7 +190,7 @@ proc toNoisePublicKey*(publicKey: EllipticCurveKey): NoisePublicKey = return noisePublicKey # Generates a random Noise public key -proc genNoisePublicKey*(rng: var BrHmacDrbgContext): NoisePublicKey = +proc genNoisePublicKey*(rng: var HmacDrbgContext): NoisePublicKey = var noisePublicKey: NoisePublicKey # We generate a random key pair let keyPair: KeyPair = genKeyPair(rng) @@ -281,7 +281,7 @@ proc `==`*(p1, p2: PayloadV2): bool = # Generates a random PayloadV2 -proc randomPayloadV2*(rng: var BrHmacDrbgContext): PayloadV2 = +proc randomPayloadV2*(rng: var HmacDrbgContext): PayloadV2 = var payload2: PayloadV2 # To generate a random protocol id, we generate a random 1-byte long sequence, and we convert the first element to uint8 payload2.protocolId = randomSeqByte(rng, 1)[0].uint8 diff --git a/waku/v2/protocol/waku_store/protocol.nim b/waku/v2/protocol/waku_store/protocol.nim index 2b97eb9a8..ef109bbc7 100644 --- a/waku/v2/protocol/waku_store/protocol.nim +++ b/waku/v2/protocol/waku_store/protocol.nim @@ -8,7 +8,7 @@ import stew/results, chronicles, chronos, - bearssl, + bearssl/rand, libp2p/crypto/crypto, libp2p/protocols/protocol, libp2p/protobuf/minprotobuf, @@ -65,7 +65,7 @@ type WakuStore* = ref object of LPProtocol peerManager*: PeerManager - rng*: ref BrHmacDrbgContext + rng*: ref rand.HmacDrbgContext messages*: StoreQueueRef # in-memory message store store*: MessageStore # sqlite DB handle wakuSwap*: WakuSwap @@ -186,7 +186,7 @@ proc init*(ws: WakuStore, capacity = StoreDefaultCapacity) = debug "the number of messages in the memory", messageNum=ws.messages.len waku_store_messages.set(ws.messages.len.int64, labelValues = ["stored"]) -proc init*(T: type WakuStore, peerManager: PeerManager, rng: ref BrHmacDrbgContext, +proc init*(T: type WakuStore, peerManager: PeerManager, rng: ref rand.HmacDrbgContext, store: MessageStore = nil, wakuSwap: WakuSwap = nil, persistMessages = true, capacity = StoreDefaultCapacity, isSqliteOnly = false): T = let ws = WakuStore(rng: rng, peerManager: peerManager, store: store, wakuSwap: wakuSwap, persistMessages: persistMessages, isSqliteOnly: isSqliteOnly) diff --git a/waku/v2/protocol/waku_swap/waku_swap.nim b/waku/v2/protocol/waku_swap/waku_swap.nim index fa462530d..e154f522a 100644 --- a/waku/v2/protocol/waku_swap/waku_swap.nim +++ b/waku/v2/protocol/waku_swap/waku_swap.nim @@ -34,7 +34,7 @@ import std/[tables, options, json], - bearssl, + bearssl/rand, chronos, chronicles, metrics, stew/results, libp2p/crypto/crypto, libp2p/protocols/protocol, @@ -285,7 +285,7 @@ proc init*(wakuSwap: WakuSwap) = wakuswap.applyPolicy = applyPolicy # TODO Expression return? -proc init*(T: type WakuSwap, peerManager: PeerManager, rng: ref BrHmacDrbgContext, swapConfig: SwapConfig): T = +proc init*(T: type WakuSwap, peerManager: PeerManager, rng: ref rand.HmacDrbgContext, swapConfig: SwapConfig): T = info "wakuSwap init 2" let accounting = initTable[PeerId, int]() diff --git a/waku/v2/protocol/waku_swap/waku_swap_types.nim b/waku/v2/protocol/waku_swap/waku_swap_types.nim index 4325f62f8..23f491fd6 100644 --- a/waku/v2/protocol/waku_swap/waku_swap_types.nim +++ b/waku/v2/protocol/waku_swap/waku_swap_types.nim @@ -2,7 +2,7 @@ import std/tables, - bearssl, + bearssl/rand, libp2p/protocols/protocol, ../../node/peer_manager/peer_manager @@ -44,7 +44,7 @@ type WakuSwap* = ref object of LPProtocol peerManager*: PeerManager - rng*: ref BrHmacDrbgContext + rng*: ref rand.HmacDrbgContext text*: string accounting*: Table[PeerId, int] credit*: CreditHandler diff --git a/waku/v2/utils/requests.nim b/waku/v2/utils/requests.nim index 0b8db18f7..c64df71d0 100644 --- a/waku/v2/utils/requests.nim +++ b/waku/v2/utils/requests.nim @@ -2,9 +2,9 @@ {.push raises: [Defect].} -import bearssl, stew/byteutils +import bearssl/rand, stew/byteutils -proc generateRequestId*(rng: ref BrHmacDrbgContext): string = +proc generateRequestId*(rng: ref HmacDrbgContext): string = var bytes: array[10, byte] - brHmacDrbgGenerate(rng[], bytes) + hmacDrbgGenerate(rng[], bytes) return toHex(bytes) diff --git a/waku/whisper/whisper_protocol.nim b/waku/whisper/whisper_protocol.nim index 17a3681dd..ccc907ae6 100644 --- a/waku/whisper/whisper_protocol.nim +++ b/waku/whisper/whisper_protocol.nim @@ -342,7 +342,7 @@ proc queueMessage(node: EthereumNode, msg: Message): bool = proc postMessage*(node: EthereumNode, pubKey = none[PublicKey](), symKey = none[SymKey](), src = none[PrivateKey](), - ttl: uint32, topic: Topic, payload: seq[byte], + ttl: uint32, topic: whisper_types.Topic, payload: seq[byte], padding = none[seq[byte]](), powTime = 1'f, powTarget = defaultMinPow, targetPeer = none[NodeId]()): bool = diff --git a/waku/whisper/whisper_types.nim b/waku/whisper/whisper_types.nim index 566cb1c6b..4805d1962 100644 --- a/waku/whisper/whisper_types.nim +++ b/waku/whisper/whisper_types.nim @@ -9,7 +9,7 @@ import std/[algorithm, bitops, math, options, tables, times, hashes], - chronicles, stew/[byteutils, endians2], metrics, bearssl, + chronicles, stew/[byteutils, endians2], metrics, bearssl/rand, nimcrypto/[bcmode, hash, keccak, rijndael], eth/[keys, rlp, p2p], eth/p2p/ecies @@ -160,9 +160,9 @@ proc topicBloom*(topic: Topic): Bloom = doAssert idx <= 511 result[idx div 8] = result[idx div 8] or byte(1 shl (idx and 7'u16)) -proc generateRandomID*(rng: var BrHmacDrbgContext): string = +proc generateRandomID*(rng: var HmacDrbgContext): string = var bytes: array[256 div 8, byte] - brHmacDrbgGenerate(rng, bytes) + hmacDrbgGenerate(rng, bytes) toHex(bytes) proc `or`(a, b: Bloom): Bloom = @@ -231,7 +231,7 @@ proc decryptAesGcm(cipher: openarray[byte], key: SymKey): Option[seq[byte]] = # simply because that makes it closer to EIP 627 - see also: # https://github.com/paritytech/parity-ethereum/issues/9652 -proc encode*(rng: var BrHmacDrbgContext, self: Payload): Option[seq[byte]] = +proc encode*(rng: var HmacDrbgContext, self: Payload): Option[seq[byte]] = ## Encode a payload according so as to make it suitable to put in an Envelope ## The format follows EIP 627 - https://eips.ethereum.org/EIPS/eip-627 @@ -284,7 +284,7 @@ proc encode*(rng: var BrHmacDrbgContext, self: Payload): Option[seq[byte]] = plain.add self.padding.get() else: var padding = newSeq[byte](padLen) - brHmacDrbgGenerate(rng, padding) + hmacDrbgGenerate(rng, padding) plain.add padding @@ -303,7 +303,7 @@ proc encode*(rng: var BrHmacDrbgContext, self: Payload): Option[seq[byte]] = if self.symKey.isSome(): # Symmetric key present - encryption requested var iv: array[gcmIVLen, byte] - brHmacDrbgGenerate(rng, iv) + hmacDrbgGenerate(rng, iv) return some(encryptAesGcm(plain, self.symKey.get(), iv)) @@ -579,7 +579,7 @@ proc initFilter*(src = none[PublicKey](), privateKey = none[PrivateKey](), powReq: powReq, allowP2P: allowP2P, bloom: toBloom(topics)) proc subscribeFilter*( - rng: var BrHmacDrbgContext, filters: var Filters, filter: Filter, + rng: var HmacDrbgContext, filters: var Filters, filter: Filter, handler: FilterMsgHandler = nil): string = # NOTE: Should we allow a filter without a key? Encryption is mandatory in v6? # Check if asymmetric _and_ symmetric key? Now asymmetric just has precedence. diff --git a/vendor/nim-eth/eth/p2p/whispernodes.nim b/waku/whisper/whispernodes.nim similarity index 69% rename from vendor/nim-eth/eth/p2p/whispernodes.nim rename to waku/whisper/whispernodes.nim index b3c746f00..3b726db01 100644 --- a/vendor/nim-eth/eth/p2p/whispernodes.nim +++ b/waku/whisper/whispernodes.nim @@ -41,3 +41,27 @@ const "enode://1d193635e015918fb85bbaf774863d12f65d70c6977506187ef04420d74ec06c9e8f0dcb57ea042f85df87433dab17a1260ed8dde1bdf9d6d5d2de4b7bf8e993@206.189.243.163:443", "enode://f593a27731bc0f8eb088e2d39222c2d59dfb9bf0b3950d7a828d51e8ab9e08fffbd9916a82fd993c1a080c57c2bd70ed6c36f489a969de697aff93088dbee1a9@35.194.31.108:443", ] + + # curl -s https://fleets.status.im | jq '"\"" + .fleets["eth.prod"].boot[] + "\","' -r + StatusBootNodes* = [ + "enode://6e6554fb3034b211398fcd0f0082cbb6bd13619e1a7e76ba66e1809aaa0c5f1ac53c9ae79cf2fd4a7bacb10d12010899b370c75fed19b991d9c0cdd02891abad@47.75.99.169:443", + "enode://436cc6f674928fdc9a9f7990f2944002b685d1c37f025c1be425185b5b1f0900feaf1ccc2a6130268f9901be4a7d252f37302c8335a2c1a62736e9232691cc3a@178.128.138.128:443", + "enode://32ff6d88760b0947a3dee54ceff4d8d7f0b4c023c6dad34568615fcae89e26cc2753f28f12485a4116c977be937a72665116596265aa0736b53d46b27446296a@34.70.75.208:443", + "enode://23d0740b11919358625d79d4cac7d50a34d79e9c69e16831c5c70573757a1f5d7d884510bc595d7ee4da3c1508adf87bbc9e9260d804ef03f8c1e37f2fb2fc69@47.52.106.107:443", + "enode://5395aab7833f1ecb671b59bf0521cf20224fe8162fc3d2675de4ee4d5636a75ec32d13268fc184df8d1ddfa803943906882da62a4df42d4fccf6d17808156a87@178.128.140.188:443", + "enode://5405c509df683c962e7c9470b251bb679dd6978f82d5b469f1f6c64d11d50fbd5dd9f7801c6ad51f3b20a5f6c7ffe248cc9ab223f8bcbaeaf14bb1c0ef295fd0@35.223.215.156:443", + ] + + # curl -s https://fleets.status.im | jq '"\"" + .fleets["eth.staging"].boot[] + "\","' -r + StatusBootNodesStaging* = [ + "enode://630b0342ca4e9552f50714b6c8e28d6955bc0fd14e7950f93bc3b2b8cc8c1f3b6d103df66f51a13d773b5db0f130661fb5c7b8fa21c48890c64c79b41a56a490@47.91.229.44:443", + "enode://f79fb3919f72ca560ad0434dcc387abfe41e0666201ebdada8ede0462454a13deb05cda15f287d2c4bd85da81f0eb25d0a486bbbc8df427b971ac51533bd00fe@174.138.107.239:443", + "enode://10a78c17929a7019ef4aa2249d7302f76ae8a06f40b2dc88b7b31ebff4a623fbb44b4a627acba296c1ced3775d91fbe18463c15097a6a36fdb2c804ff3fc5b35@35.238.97.234:443", + ] + + # curl -s https://fleets.status.im | jq '"\"" + .fleets["eth.test"].boot[] + "\","' -r + StatusBootNodesTest* = [ + "enode://daae2e72820e86e942fa2a8aa7d6e9954d4043a753483d8bd338e16be82cf962392d5c0e1ae57c3d793c3d3dddd8fd58339262e4234dc966f953cd73b535f5fa@47.52.188.149:443", + "enode://9e0988575eb7717c25dea72fd11c7b37767dc09c1a7686f7c2ec577d308d24b377ceb675de4317474a1a870e47882732967f4fa785b02ba95d669b31d464dec0@206.189.243.164:443", + "enode://c1e5018887c863d64e431b69bf617561087825430e4401733f5ba77c70db14236df381fefb0ebe1ac42294b9e261bbe233dbdb83e32c586c66ae26c8de70cb4c@35.188.168.137:443", + ]