Skip to content

feat(node): self-contained binary — embed Rholang resources, defaults.conf, eliminate kamon#492

Merged
spreston8 merged 2 commits intorust/stagingfrom
feat/self-contained-binary
Apr 30, 2026
Merged

feat(node): self-contained binary — embed Rholang resources, defaults.conf, eliminate kamon#492
spreston8 merged 2 commits intorust/stagingfrom
feat/self-contained-binary

Conversation

@spreston8
Copy link
Copy Markdown
Collaborator

@spreston8 spreston8 commented Apr 29, 2026

Summary

Make the Rust node binary fully self-contained at runtime: bake the genesis-ceremony Rholang sources and the HOCON defaults into the executable at compile time. After this lands, target/release/node run --data-dir <dir> works from any CWD with no `DEFAULT_DIR` env var, no workspace tree on disk, and no resource-file mounts in the runtime container.

This unblocks lighter-weight integration test infrastructure (subprocess-based provider, planned next) and removes a class of "works on my machine" CWD-dependency bugs.

What's in scope

Commit 1 (`d1290862`) — feat(node): self-contained binary

Area Change
Rholang resources All 11 `.rho` / `.rhox` genesis sources (Registry, ListOps, Either, NonNegativeNumber, MakeMint, AuthKey, SystemVault, MultiSigSystemVault, Stack, TokenMetadata, PoS) embedded via `include_str!` in a new `casper/src/rust/genesis/contracts/embedded_rho.rs`. `standard_deploys.rs` rewritten through a small `embedded_source` helper.
File-loading machinery removed `CompiledRholangSource::apply` / `apply_with_env` / `load_source` and `CompiledRholangTemplate::load_template` (the 8-path filesystem fallback ladder) deleted from production code. `CompiledRholangTemplate::new` now takes the template body as `&str`.
HOCON defaults `defaults.conf` embedded via `include_str!` + `HoconLoader::load_str`. The `default_dir: &Path` parameter dropped from `configuration::builder::build`; `DEFAULT_DIR` env var read in `main.rs` removed. Override semantics unchanged: `--config-file ` and `<data_dir>/rnode.conf` auto-load still apply on top of the embedded baseline.
Kamon eliminated `KamonConf` struct, `configuration/kamon.rs`, `kamon.conf`, `load_kamon_config` parsing path, and `KamonConf` plumbing through `main.rs` / `mod.rs` / `diagnostics/` all deleted. The two fields the Rust diagnostics actually consumed (`tick_interval` and the InfluxDB endpoint) moved into `NodeConf::Metrics` under a single `metrics { ... }` section in `defaults.conf`.
Dead JVM artifacts `logback.xml` and `logging-template/*` deleted (never read by any Rust code).
Test-side .rho loading Preserved via a new `casper/tests/util/rholang/test_rho_loader.rs::load_test_rho` (kept out of the production binary). 20 test files migrated.
Dockerfile Drops the COPY steps that staged `node/src/main/resources/`, `casper/src/main/resources/`, and `rholang/examples/` into the runtime image.

Net diff: ~80 LOC added, ~370 LOC deleted across 41 files.

Commit 2 (`58f5f776`) — docs(node): align README + Helm chart

Tail-end documentation and config-template cleanup that the first commit implied but didn't touch.

  • `README.md`: clarifies that the built-in `defaults.conf` is embedded into the binary at compile time via `include_str!` (not a runtime file lookup).
  • `docs/node/README.md`: config build pipeline corrected to `HoconLoader::new().load_str(EMBEDDED_DEFAULTS)`; notes that no `node/src/main/resources/` directory is required at runtime.
  • `defaults.conf`: drops the stale `kamon-influxdb` reference from the metrics-section comment (since the embedded file's text now ships in the binary, even comment changes get compiled in).
  • Helm chart cleanup: deleted the dead `logback.xml` ConfigMap entry and `/var/lib/rnode/logback.xml` subPath mount; rewrote the Kamon-era explainer comment in the embedded `defaults.conf` template (deployable + observer ConfigMaps) to describe the new `metrics { ... }` schema.

`Justfile` audited — already correct. Recipes pass `--config-file=...` explicitly; no `DEFAULT_DIR` env var, no CWD requirement. Zero changes needed there.

Why this approach

Embed-only (rather than "embed first, fall back to file") was chosen as the production approach. Rationale:

  • Single source of truth: everything that ships in the binary ships in the binary. No sidecar files, no fs probing, no CWD dependency.
  • Compile-time guarantees: `include_str!` fails the build if the file is missing. The previous code failed at runtime with a multi-path search-error string. Compile-time > runtime for missing-asset bugs.
  • Honest dependencies: the binary really does depend on these specific files at compile time; `include_str!` makes that visible to the compiler and to anyone reading the source.
  • Smaller code surface: ~290 LOC net deleted (the 8-path fallback ladder + `apply` + `apply_with_env` + file-based template loading + `KamonConf` plumbing).
  • No "works on my machine" CWD bugs: the previous fallback ladder (`casper/src/main/resources/X`, `../casper/src/main/resources/X`, `rholang/examples/X`, …) was dev-machine-shaped, not production-shaped.

Test plan

  • `cargo build --release --tests --workspace` — clean
  • `cargo test --release -p casper --test mod` — 345 passed / 0 failed / 24 ignored (`finished in 61.36s`)
  • Standalone smoke test from arbitrary CWD with no env vars: `./target/release/node run --standalone --data-dir /tmp/x --use-random-ports --no-upnp --allow-private-addresses` from `/tmp` (no workspace tree visible) — reaches `"isReady":true` on `/api/status` ~12s after launch; auto-generates self-signed TLS certs in the data dir; data-dir layout (rspace/, eval/, blockstorage/, dagstorage/, casperbuffer/, deploystorage/, reporting/, genesis/) created normally.
  • Integration tests against the new binary (planned via SubprocessProvider follow-up — building this PR's binary into the existing Docker image and re-running `integration-tests` is the next acceptance gate before this lands).

Compatibility notes

  • Operator-facing config flow unchanged: `--config-file ` and `<data_dir>/rnode.conf` continue to override the embedded defaults exactly as today. The Helm chart still mounts `rnode.conf` into `/var/lib/rnode/rnode.conf`. No deployment-side migration.
  • Test fixtures still load `.rho` from disk: tests in `casper/tests/genesis/contracts/` and `casper/tests/helper/rho_spec.rs` use a new test-only `load_test_rho` helper that preserves the historical 8-path search behavior. Test fixtures live in `casper/src/test/resources/` exactly as before.
  • Helm chart: removes one dead mount (`logback.xml` was already a no-op for Rust nodes). No operator action required.

Co-Authored-By: Claude noreply@anthropic.com

….conf, eliminate kamon

Bake the genesis-ceremony Rholang sources and the HOCON defaults into the
node binary at compile time so a node only needs --data-dir and ports to
run. Production CWD requirement (workspace tree at runtime), the
`DEFAULT_DIR` env var, and the kamon.conf parallel-config-file shim are
all gone.

Changes:

- Embed all 11 .rho/.rhox genesis resources via include_str! in a new
  casper/src/rust/genesis/contracts/embedded_rho.rs. Rewrite the call
  sites in standard_deploys.rs to use a small `embedded_source` helper.
  Delete CompiledRholangSource::apply / apply_with_env / load_source and
  CompiledRholangTemplate::load_template (the file-loading machinery
  that walked an 8-path search ladder relative to CWD). Production code
  no longer touches the filesystem for Rholang sources; missing-asset
  bugs become build errors.

- Embed defaults.conf via include_str! + hocon::HoconLoader::load_str.
  Drop the `default_dir: &Path` parameter from
  configuration::builder::build and the `DEFAULT_DIR` env var read in
  main.rs. Override semantics unchanged: --config-file <path> and
  <data_dir>/rnode.conf auto-load still apply on top of the embedded
  baseline.

- Eliminate kamon.conf entirely. The InfluxDB and Zipkin reporters in
  node/src/rust/diagnostics/ are hand-rolled Rust — they only borrowed
  the JVM-Kamon HOCON schema for migration compatibility. Move the two
  fields the Rust code actually consumed (tick_interval and the
  InfluxDB endpoint) into NodeConf::Metrics under defaults.conf. Delete
  KamonConf, configuration/kamon.rs, kamon.conf, the load_kamon_config
  parsing path, and KamonConf plumbing through main.rs / mod.rs /
  diagnostics.

- Delete unreferenced JVM logging artifacts: logback.xml,
  logging-template/* (never read by any Rust code).

- Test-side filesystem .rho loading is preserved via a new
  casper/tests/util/rholang/test_rho_loader.rs (load_test_rho), kept
  out of the production binary. The 20 test files that loaded
  .rho fixtures from disk are migrated.

- Dockerfile: drop the COPY steps that staged
  node/src/main/resources/, casper/src/main/resources/, and
  rholang/examples/ into the runtime image. The binary is now fully
  self-contained.

Verified:
  cargo build --release --tests --workspace        clean
  cargo test  --release -p casper --test mod       345 passed / 0 failed
  ./target/release/node run --standalone           reaches isReady:true
                                                    from /tmp with no
                                                    DEFAULT_DIR env var
                                                    and no workspace
                                                    tree on disk
Tail-end documentation and config-template cleanup that the
self-contained-binary commit (d129086) implied but didn't touch.

- README.md: clarify that the built-in defaults.conf is embedded into
  the binary at compile time via include_str! (not a runtime file
  lookup), so operators understand that the on-disk file is the source
  of the embed rather than a runtime dependency.

- docs/node/README.md: update the config build pipeline description.
  Step 1 now describes `HoconLoader::new().load_str(EMBEDDED_DEFAULTS)`
  with a note that no `node/src/main/resources/` directory is required
  at runtime. Step 2 is reworded for accuracy.

- node/src/main/resources/defaults.conf: drop the stale
  `kamon-influxdb` reference from the metrics-section comment.

- Helm chart cleanup:
    * docker/helm/f1r3fly/configs/common/logback.xml: deleted (the
      JVM-Logback config was never read by the Rust binary; the
      enclosing `node/src/main/resources/logback.xml` was deleted in
      d129086, but the Helm chart still mounted a sibling copy).
    * docker/helm/f1r3fly/templates/statefulsets.yaml: drop the
      /var/lib/rnode/logback.xml subPath mount that pointed at the
      now-removed ConfigMap entry.
    * docker/helm/f1r3fly/templates/{deployable,observer}-rnode-configmaps.yaml:
      rewrite the Kamon-era comment in the embedded defaults.conf
      template; metrics endpoints (tick-interval, influxdb-endpoint)
      now live under the same `metrics` section in NodeConf.

No code changes; binary rebuilt to verify the embedded HOCON still
parses cleanly. Justfile already used --config-file overrides
correctly (no DEFAULT_DIR env var, no CWD requirement); no recipe
changes needed.
@spreston8 spreston8 marked this pull request as ready for review April 30, 2026 02:53
@spreston8 spreston8 merged commit bfaa2c8 into rust/staging Apr 30, 2026
20 checks passed
@spreston8 spreston8 deleted the feat/self-contained-binary branch April 30, 2026 02:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant