Three bugs the kernel suite never caught, because CI only compiles it.
A peer's addresses were comma-joined into one argument, but the library
inits that argument as a single multiaddress, so StoreQuery and PingPeer
failed against any peer advertising more than one address.
StoreQueryResponse could decode neither the Opt[T] wrapper objects the
library renders results.Opt as, nor the integer arrays it renders
seq[byte] as, so every store reply failed to unmarshal. Both shapes now
decode, and the bare value still does.
A context without a deadline sent timeoutMs=0, which chronos' withTimeout
expires on immediately rather than treating as unbounded. StoreQuery with
context.Background() could never have succeeded.
Consumers resolve liblogosdelivery at the revision these bindings were
written against, instead of pinning it themselves, and build it through
the task here rather than reimplementing logos-delivery's flags.
srcDir points at an empty directory, so nothing is contributed to a
dependent's Nim path.
* feat(messaging): object-oriented Go mirror of the Nim MessagingClient
Adds pkg/messaging: a high-level, idiomatic Go binding for the Messaging
API, mirroring logos-delivery's Nim MessagingClient. A MessagingClient owns
a node and carries the messaging surface as methods on it — New / Start /
Stop / Close, Subscribe / Unsubscribe, Send(ctx, Envelope) (RequestID,
error) — over internal/ffi rather than exposing the raw FFI.
Events arrive on a single Events() <-chan Event with a sealed Event
interface: MessageReceivedEvent, MessageSentEvent, MessagePropagatedEvent,
MessageErrorEvent and ConnectionStatusEvent. Delivery never blocks the
library's event thread; an event is dropped when a consumer falls behind.
Config marshals to the layered configuration JSON (mode / preset /
messagingOverrides / channelsOverrides), with every field omitempty so it
can never be mistaken for the legacy flat blob.
Migrating internal/ffi to the current C ABI comes with it, because the
generated surface has moved on since the bridge was written and no longer
compiles: nim-ffi now generates the header from the {.ffi.} annotations,
argument-taking calls pass a per-call <Name>Req struct and a typed
<Name>ReplyFn, no-argument calls take a raw scalar callback, destroy is
synchronous, and the single set_event_callback has been replaced by a
per-event listener registry. The bridge now also copies every callback
string while it is still borrowed, and ignores the non-terminal
STALE_WARN progress code instead of settling the call on it.
pkg/kernel follows the same listener change, registering the three kernel
events it already consumed.
Verified against a liblogosdelivery built from logos-delivery master:
build / vet / golangci-lint / go mod tidy clean, unit tests green, and the
tagged integration test does a full create-start-subscribe-send round trip
on logos.dev, observing the message back and its propagation confirmation.
Closes#119.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CnzdnSMtHM5aLHLtDGBGR9
* review: address feedback on the MessagingClient API
- Send takes contentTopic / payload / ephemeral directly instead of an
Envelope struct, which drops the Envelope type; ContentTopic and RequestID
move to types.go.
- messagingEvents becomes a function returning the slice, so the set cannot
be mutated by accident.
- Document what seals the Event interface and what that buys callers.
- Document why the received payload is decoded from a JSON integer array:
base64 is only used on the send path and by the channel events, not by the
messaging events.
* ci: stop golangci-lint's config verify from failing on a network timeout
golangci-lint-action runs `golangci-lint config verify` before linting, which
fetches the v2.4 JSON schema from golangci-lint.run on every run. That request
timed out on the runner and failed the gate with no lint finding behind it. An
invalid config still fails the lint run itself, so the pre-check only costs a
network dependency.
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* refactor: build against the single liblogosdelivery library
logos-delivery#4012 unifies the node lifecycle on logosdelivery_* and ships the
full API — Messaging, Reliable Channels, and the low-level Kernel (waku_*) tier
— in one liblogosdelivery library, retiring the separate libwaku. Migrate the
bindings onto it.
- internal/ffi: collapse the two bridges into one internal/ffi/liblogosdelivery
over the single library. The kernel wrappers keep calling waku_* (kernel
header), the lifecycle now uses logosdelivery_create_node/start_node/
stop_node/destroy (waku_new/start/stop/destroy are gone), events use
logosdelivery_set_event_callback. Include liblogosdelivery_kernel.h (which
re-exports the stable header) and link -llogosdelivery. Remove
internal/ffi/libwaku.
- pkg/kernel: repoint at internal/ffi/liblogosdelivery; the Makefile links
-llogosdelivery.
- CI: build only `make liblogosdelivery`, headers from library/, single
-llogosdelivery. Pinned to logos-delivery#4012 until it merges (see the
TODO/LOGOS_DELIVERY_REF in pr.yml).
The high-level MessagingClient (pkg/messaging) lands in a follow-up PR on top.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(kernel): drop removed config keys + add a runnable example
Running against the single liblogosdelivery library surfaced a config drift:
the consolidated WakuNodeConf strictly rejects unknown keys, and
common.WakuConfig still emitted `legacyStore` (removed upstream, and sent
unconditionally) and `host` (renamed to `listenAddress`). That failed node
creation, so every kernel test that starts a node failed. Reconcile the config:
- drop the LegacyStore field (and its two obsolete test references; the
already-skipped TestCheckLegacyStore keeps compiling);
- map Host to the `listenAddress` JSON key.
Add examples/kernel: a small runnable check that drives the unified lifecycle
(logosdelivery_create_node/start/stop/destroy) and a few kernel ops (version,
listen addresses, is-online, relay subscribe/unsubscribe) over the single
library. `go run ./examples/kernel` prints OK.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(kernel): correct RelayPublish wire format; verify send/receive
RelayPublish marshalled the generated protobuf (content_topic), but the library
requires the WakuMessage wire format (contentTopic) and rejected it with
"Missing required field: contentTopic". Marshal the wire shape explicitly.
Turn examples/kernel into an end-to-end send/receive check: two relay nodes on
cluster 16 / shard 64, connected via the listen multiaddr, one publishes and the
other receives it off MsgChan. Verified against a locally-built liblogosdelivery:
prints "send/receive OK".
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* ci: build against logos-delivery master (unpin #4012)
logos-delivery#4012 merged, so drop the LOGOS_DELIVERY_REF pin and clone the
default branch; the cache key tracks master's HEAD again.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(ffi): flatten internal/ffi/liblogosdelivery into internal/ffi
With a single library there is no bridge to choose between, so the extra
subpackage adds nothing: move the bridge to internal/ffi (package ffi) and drop
the umbrella doc. pkg/kernel now imports internal/ffi and calls ffi.*.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test(kernel): add a two-node relay send/receive integration test
TestRelaySendReceive connects two relay nodes, publishes a random payload from
one and requires the other to receive it — end-to-end over the single library.
Compiled by the PR gate; run under `make test` / locally against a built
liblogosdelivery. (Replaces the former examples/kernel, removed alongside the
ffi flatten.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(ffi): keep two files in package ffi, one per header
The single library still ships two headers — liblogosdelivery.h (stable
Messaging/lifecycle) and liblogosdelivery_kernel.h (low-level waku_*). Mirror
that with two files in one package instead of one merged ffi.go: keep the
messaging bridge and all the shared plumbing (Handle/RetOK/lifecycle/callbacks/
call) in liblogosdelivery.go, and keep the kernel wrappers in libwaku.go, which
reuses the shared call + logosGoCallback. This is the same two files we had,
moved into package ffi — a much smaller diff than the merge.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Apply suggestions from code review
Co-authored-by: Ivan FB <128452529+Ivansete-status@users.noreply.github.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Ivan FB <128452529+Ivansete-status@users.noreply.github.com>
Add internal/ffi/liblogosdelivery, the cgo bridge over liblogosdelivery
(Messaging API), mirroring the libwaku subpackage from #114: synchronous
request/response plumbing, a shared async event callback, and a handle->handler
registry, exposing Go-typed primitives (New/Start/Stop/Destroy,
Subscribe/Unsubscribe/Send, SetEventHandler, Handle, RetOK, EventHandler).
It self-links liblogosdelivery via a #cgo directive. For symmetry — and so the
two bridges never need a shared global -l flag — add the same #cgo LDFLAGS:
-lwaku to the libwaku subpackage. Each subpackage now links exactly its own
library; no binary links both (until logos-delivery#3851).
Extend the PR gate to build liblogosdelivery, set CGO_CFLAGS for both headers
with no -l (each package self-links), run the messaging unit tests, and compile
the kernel tests.
Part of #106.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor: extract libwaku cgo bridge into internal/ffi
Move the C preamble, cgo shims, and callback plumbing from pkg/kernel/nwaku.go
into internal/ffi/libwaku.go, where #111 scaffolded them to live. The bridge
exposes Go-typed Waku* primitives (handle in, strings out) and owns the
handle->event-handler registry, so pkg/kernel is now pure Go: WakuNode keeps
its full API, logging, and error texts, and just calls ffi.
Behavior is unchanged. Dropped four C shims that had no Go callers
(cGoWakuContentTopic, cGoWakuPubsubTopic, cGoWakuDefaultPubsubTopic,
cGoWakuLightpushPublish). CGO flags still come from the environment
(Makefile/CI untouched).
Part of #106.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor: move libwaku bridge into internal/ffi/libwaku subpackage
One subpackage per C library so a binary links exactly the libraries it
imports: libwaku and liblogosdelivery carry overlapping symbols and must never
link together (until logos-delivery#3851). With the package named libwaku the
Waku* prefixes became stutter, so the exported primitives drop them
(libwaku.New/Start/RelayPublish/...). internal/ffi keeps an umbrella doc.go
stating the rule.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* refactor: adopt golang-standards/project-layout
Move the legacy kernel wrapper `waku/*` to `pkg/kernel/*` and rename its
package `waku` -> `kernel`; nothing outside the package imported it, so this is
a mechanical import-path/prefix change. Update the relocated Makefile's
relative dep path, the legacy CI workflows (CI/endurance/repeated) build paths,
README, and .gitignore accordingly (preserving the libwaku-cache CI from #109).
Add scaffolding for the upcoming Messaging API work: `internal/ffi` (cgo
bridge), `pkg/messaging` (high-level Node API), and `examples/`. Document
`pkg/kernel` as legacy until logos-delivery#3851 consolidates the C libraries.
Also stop tracking the accidentally-committed `waku-bindings` build artifact
and gitignore the kernel build output.
No behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore: cleanup
* fix: repair references to removed utils package
nwaku_test_utils.go now uses pkg/kernel/utils.GetRSSKB; the memory_record
tool is self-contained (local helpers, missing mutex restored).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore: rename module path to logos-delivery-go-bindings
The module path still read `logos-messaging-go-bindings`, mismatching the
repository name. Rename it to `github.com/logos-messaging/logos-delivery-go-bindings`
and update all in-repo imports. gofmt re-sorts a few import blocks as a result
(plus two files that were already unformatted on master).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* ci: add PR-gate workflow and golangci-lint config
The repo had no `on: pull_request` CI (only workflow_dispatch + nightly
schedule), so nothing validated PRs. Add `.github/workflows/pr.yml` that
builds libwaku and runs `go build`, `go vet`, golangci-lint, and a test-compile
pass on every PR. Add a baseline `.golangci.yml` (standard linters + gofmt).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* ci: scope golangci-lint to new code via new-from-merge-base
Run the full `standard` linter set but only report findings introduced since
the merge-base with master, so the legacy kernel wrapper's pre-existing issues
(unchecked defer-Close, dead helpers) don't drown the gate while new code still
gets full coverage. Fetch origin/master so the base ref is available in CI.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* ci: clone logos-delivery outside vendor/ and build in module mode
`go build` failed in CI because cloning logos-delivery into `vendor/` put Go
into vendor mode against an inconsistent `vendor/modules.txt`. Clone the
checkout into `.logos-delivery` instead and set `GOFLAGS=-mod=mod` so the gate
always builds in module mode.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* ci: use golangci-lint-action@v7 for golangci-lint v2
v6 of the action rejects golangci-lint v2 versions ("v2 is not supported by
golangci-lint-action v6"). Bump to v7.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* ci: cache libwaku, gate go mod tidy, rename LMN_DIR
- Rename LMN_DIR -> LOGOS_DELIVERY_DIR across the PR-gate and nightly
workflows, the waku Makefile, and the build docs.
- Cache the built logos-delivery kernel keyed on its upstream HEAD SHA,
skipping the clone + libwaku build while that commit is unchanged.
- Add a "go mod tidy is clean" step that fails if go.mod/go.sum drift.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>