chore: github workflows (#53)

* chore: github workflows
* fix: reduce the minimum required nim version
* fix: compile examples
* chore: use specific commit for libp2p (should be replaced by v1.10.4 once available)
* fix: 1.6
This commit is contained in:
richΛrd
2025-07-17 16:57:33 -04:00
committed by Richard Ramos
parent 058be6cb47
commit fa1a26a295
16 changed files with 150 additions and 33 deletions

15
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
name: CI
on:
push:
branches:
- main
pull_request:
workflow_dispatch:
jobs:
build:
uses: status-im/nimbus-common-workflow/.github/workflows/common.yml@main
with:
test-command: |
env NIMLANG=c nimble test
env NIMLANG=cpp nimble test

16
.github/workflows/examples.yml vendored Normal file
View File

@@ -0,0 +1,16 @@
name: Examples
on:
push:
branches:
- main
pull_request:
workflow_dispatch:
jobs:
examples:
uses: status-im/nimbus-common-workflow/.github/workflows/common.yml@main
with:
test-command: |
nimble c ./mix/examples/poc_gossipsub.nim
nimble c ./mix/examples/poc_gossipsub_repeated_runs.nim
nimble c ./mix/examples/poc_noresp_ping.nim

27
.github/workflows/linters.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: Linters
on:
pull_request:
merge_group:
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
nph:
name: NPH
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 2 # In PR, has extra merge commit: ^1 = PR, ^2 = base
- name: Check `nph` formatting
uses: arnetheduck/nph-action@v1
with:
version: 0.6.1
options: "mix tests *.nim*"
fail: true
suggest: true

35
.github/workflows/pr_lint.yml vendored Normal file
View File

@@ -0,0 +1,35 @@
name: "Conventional Commits"
on:
pull_request:
types:
- opened
- edited
- reopened
- synchronize
jobs:
main:
name: Validate PR title
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: amannn/action-semantic-pull-request@v5
id: lint_pr_title
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: marocchino/sticky-pull-request-comment@v2
# When the previous steps fails, the workflow would stop. By adding this
# condition you can continue the execution with the populated error message.
if: always() && (steps.lint_pr_title.outputs.error_message != null)
with:
header: pr-title-lint-error
message: |
Pull requests titles must follow the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/)
# Delete a previous comment when the issue has been resolved
- if: ${{ steps.lint_pr_title.outputs.error_message == null }}
uses: marocchino/sticky-pull-request-comment@v2
with:
header: pr-title-lint-error
delete: true

View File

@@ -1 +1,2 @@
--mm:refc
--mm:
refc

View File

@@ -6,8 +6,8 @@ license = "MIT"
# Dependencies
requires "stew >= 0.3.0"
requires "chronos >= 4.0.3"
requires "libp2p >= 1.11.0"
requires "nim >= 2.0.8"
requires "https://github.com/vacp2p/nim-libp2p#64c9cf1b9e69a6d1da9f430ffb1f91e949658f28"
requires "nim >= 1.6.0"
requires "nimcrypto >= 0.6.0"
requires "serialization >= 0.2.2"

View File

@@ -76,7 +76,7 @@ method writeLp*(
): Future[void] {.async: (raises: [CancelledError, LPStreamError], raw: true), public.} =
self.writeLp(msg.toOpenArrayByte(0, msg.high))
method shortLog*(self: MixEntryConnection): string {.raises: [].} =
proc shortLog*(self: MixEntryConnection): string {.raises: [].} =
"[MixEntryConnection] Destination: " & $self.destMultiAddr & "/p2p/" & $self.destPeerId
method initStream*(self: MixEntryConnection) =

View File

@@ -93,12 +93,10 @@ proc oneNode(node: Node) {.async.} =
)
if node.id == 0:
node.gossip.subscribe(
"message",
proc(topic: string, data: seq[byte]) {.async.} =
info "Message received", nodeId = node.id, msg = cast[string](data)
,
)
let handler = proc(topic: string, data: seq[byte]) {.async.} =
info "Message received", nodeId = node.id, msg = cast[string](data)
node.gossip.subscribe("message", handler)
else:
node.gossip.subscribe("message", nil)
@@ -114,7 +112,7 @@ proc oneNode(node: Node) {.async.} =
await sleepAsync(1000.milliseconds)
await node.switch.stop()
proc mixnet_gossipsub_test() {.async.} =
proc mixnet_gossipsub_test() {.async: (raises: [Exception]).} =
let
numberOfNodes = 5
switch = setUpNodes(numberOfNodes)

View File

@@ -114,7 +114,7 @@ proc oneNode(node: Node, rcvdCnt: ptr Atomic[int]) {.async.} =
await sleepAsync(1000.milliseconds)
await node.switch.stop()
proc mixnet_gossipsub_test(): Future[int] {.async.} =
proc mixnet_gossipsub_test(): Future[int] {.async: (raises: [Exception]).} =
let
numberOfNodes = 5
switch = setUpNodes(numberOfNodes)
@@ -177,7 +177,7 @@ proc mixnet_gossipsub_test(): Future[int] {.async.} =
import std/[tables, algorithm, math, strformat]
proc main() {.async.} =
proc main() {.async: (raises: [Exception]).} =
var results: seq[int] = @[]
let n = 25

View File

@@ -71,7 +71,7 @@ proc setUpNodes(numNodes: int): seq[Switch] =
return nodes
proc mixnetSimulation() {.async.} =
proc mixnetSimulation() {.async: (raises: [Exception]).} =
let
numberOfNodes = 10
nodes = setUpNodes(numberOfNodes)

View File

@@ -123,8 +123,8 @@ method writeLp*(
): Future[void] {.async: (raises: [CancelledError, LPStreamError]), public.} =
raise newException(LPStreamError, "writeLp not implemented for MixExitConnection")
method shortLog*(self: MixExitConnection): string {.raises: [].} =
discard
func shortLog*(self: MixExitConnection): string {.raises: [].} =
"MixExitConnection"
method initStream*(self: MixExitConnection) =
discard

View File

@@ -111,7 +111,7 @@ proc writeMixNodeInfoToFile*(
let serializedData = serializeMixNodeInfo(node).valueOr:
return err("Failed to serialize mix node info: " & error)
file.writeData(addr serializedData[0], serializedData.len)
file.writeData(unsafeAddr serializedData[0], serializedData.len)
return ok()
proc readMixNodeInfoFromFile*(
@@ -203,7 +203,7 @@ proc writeMixPubInfoToFile*(
let serializedData = serializeMixPubInfo(node).valueOr:
return err("Failed to serialize mix pub info: " & error)
file.writeData(addr serializedData[0], serializedData.len)
file.writeData(unsafeAddr serializedData[0], serializedData.len)
return ok()
proc readMixPubInfoFromFile*(

View File

@@ -6,14 +6,31 @@ import ./protocols/noresp_ping
const protocolTypeSize* = 2
type ProtocolType* = enum
Ping = PingCodec
GossipSub12 = GossipSubCodec_12
GossipSub11 = GossipSubCodec_11
GossipSub10 = GossipSubCodec_10
NoRespPing = NoRespPingCodec
WakuLightPushProtocol = "/vac/waku/lightpush/3.0.0"
#TODO: fix this hardcoding, for now doing it as importing codecs from waku causses various build errors.
OtherProtocol = "other" # Placeholder for other protocols
Ping
GossipSub12
GossipSub11
GossipSub10
NoRespPing
WakuLightPushProtocol
OtherProtocol
proc `$`*(proto: ProtocolType): string =
case proto
of Ping:
PingCodec
of GossipSub12:
GossipSubCodec_12
of GossipSub11:
GossipSubCodec_11
of GossipSub10:
GossipSubCodec_10
of NoRespPing:
NoRespPingCodec
of WakuLightPushProtocol:
"/vac/waku/lightpush/3.0.0"
#TODO: fix this hardcoding, for now doing it as importing codecs from waku causses various build errors.
else:
"other" # Placeholder for other protocols
type ProtocolHandler* = proc(conn: Connection, proto: ProtocolType): Future[void] {.
async: (raises: [CancelledError])

View File

@@ -16,7 +16,7 @@ proc generateSeqNo*(seqNo: var SeqNo, messageBytes: seq[byte]) =
let
currentTime = getTime().toUnix() * 1000
currentTimeBytes = newSeq[byte](8)
bigEndian64(addr currentTimeBytes[0], unsafeAddr currentTime)
bigEndian64(unsafeAddr currentTimeBytes[0], unsafeAddr currentTime)
let messageHash = sha256_hash(messageBytes & currentTimeBytes)
var cnt: uint32
for i in 0 .. 3:

View File

@@ -213,7 +213,10 @@ proc wrapInSphinxPacket*(
return ok(serializeRes)
proc processSphinxPacket*(
serSphinxPacket: seq[byte], privateKey: FieldElement, tm: var TagManager, isDestEmbedded: bool
serSphinxPacket: seq[byte],
privateKey: FieldElement,
tm: var TagManager,
isDestEmbedded: bool,
): Result[(Hop, seq[byte], seq[byte], ProcessingStatus), string] =
# Deserialize the Sphinx packet
let deserializeRes = deserializeSphinxPacket(serSphinxPacket).valueOr:
@@ -268,14 +271,19 @@ proc processSphinxPacket*(
return err("Error in aes: " & error)
# Check if B has the required prefix for the original message
paddingLength = if isDestEmbedded:
paddingLength =
if isDestEmbedded:
(((t + 1) * (r - L)) + 2) * k
else:
(((t + 1) * (r - L)) + t + 2) * k
zeroPadding = newSeq[byte](paddingLength)
let bOffset = if isDestEmbedded: (t * k) else: 0
let bOffset =
if isDestEmbedded:
(t * k)
else:
0
if B[bOffset .. bOffset + paddingLength - 1] == zeroPadding:
let deserializeRes = deserializeMessage(delta_prime).valueOr:
@@ -288,7 +296,6 @@ proc processSphinxPacket*(
return ok((hop, B[addrSize .. ((t * k) - 1)], msg[0 .. messageSize - 1], Exit))
else:
return ok((Hop(), @[], msg[0 .. messageSize - 1], Exit))
else:
# Extract routing information from B
let deserializeRes = deserializeRoutingInfo(B).valueOr:

View File

@@ -196,8 +196,9 @@ suite "Sphinx Tests":
message[i] = byte(rand(256))
let paddedMessage = padMessage(message, messageSize)
let packetRes =
wrapInSphinxPacket(initMessage(paddedMessage), publicKeys, delay, hops, none(Hop))
let packetRes = wrapInSphinxPacket(
initMessage(paddedMessage), publicKeys, delay, hops, none(Hop)
)
if packetRes.isErr:
error "Sphinx wrap error", err = packetRes.error
let packet = packetRes.get()