Skip to content

fix(host-reporter): restore Cascade Kademlia byte reporting on HostReport (OPEN-4) - #319

Open
mateeullahmalik wants to merge 1 commit into
masterfrom
matee/open4-cascade-bytes-reporting
Open

fix(host-reporter): restore Cascade Kademlia byte reporting on HostReport (OPEN-4)#319
mateeullahmalik wants to merge 1 commit into
masterfrom
matee/open4-cascade-bytes-reporting

Conversation

@mateeullahmalik

Copy link
Copy Markdown
Collaborator

Summary

Restores the single line that populates CascadeKademliaDbBytes on the outgoing HostReport.

LEP-6 PR #286 removed it on the reading that "the audit module does not consume this value for its own consensus logic". That reading is incorrect: the field is a metric courier, not an audit input.

The chain proto (lumera/audit/v1/audit.proto, HostReport field 6) is explicit:

On successful epoch-report acceptance the audit handler bridges this value into x/supernode SupernodeMetricsState, which is the sole source consulted by Everlight payout / eligibility.

The field was never deprecated — it is still in the proto, still documented as required, and still the only writer path for Everlight weight.

Why this is severe

The chain-side bridge assigns unconditionally, with no zero-guard:

state.Metrics.CascadeKademliaDbBytes = cascadeBytes   // msg_submit_epoch_report.go:322

So a daemon that omits the field doesn't merely fail to update it — it actively overwrites a good stored value with 0 on every epoch.

At the mainnet default min_cascade_bytes_for_payment = 1073741824 (1 GiB), no v2.6.x SuperNode can ever qualify for a payout, because the numerator is pinned at zero regardless of how much real Cascade data it stores.

cascadeKademliaDBBytes() (service.go:415) was never deleted and still works correctly — it was simply no longer called.

Verified on a live devnet, not just in unit tests

Same validator on a running 5-validator devnet, swapping only this binary:

report_count cascade_kademlia_db_bytes
before (v2.6.3 shipped) 454 0
after (this PR) 455 893056

Matches on-disk ground truth byte-for-byte:

du -cb /root/.supernode/data/p2p/data*.sqlite3*  ->  893056

No manual MsgReportSupernodeMetrics injection was used — the value arrived purely through the daemon's own epoch-report path.

Tests

Adds supernode/host_reporter/cascade_bytes_reporting_test.go, asserting the wire contract (what SubmitEpochReport actually receives) rather than the helper in isolation.

This distinction is the whole point: the pre-existing tests proved cascadeKademliaDBBytes() computes a number, but nothing asserted that number reached the wire — which is exactly why the regression shipped unnoticed.

Mutation-verified

Each mutation is caught by a different subset, so no test is vacuous and none is solely load-bearing:

Mutation Result
Delete the assignment (exact v2.6.3 state) 3 tests fail
Hardcode a plausible constant (611842) 3 tests fail (empty-store, growth-tracking, no-data-dir)
Drop WAL/SHM sidecars from the glob (undercount, still non-zero) 2 tests fail

Note mutation 2 specifically: a naive "is it non-zero?" test would be satisfied by a hardcoded constant. The empty-store and growth-tracking cases prevent that.

Also adds a DO NOT REMOVE comment at the call site recording why the field is required, so the next reader doesn't repeat PR #286's inference.

Verification

go build ./...                      ok
go test ./supernode/...             all packages ok
go vet ./supernode/host_reporter/   clean

Risk

Low. One line of behavior change plus tests. It restores a field the chain already expects and already handles; nothing else on the report path changes. Reporting 0 for a genuinely empty store remains correct and is explicitly pinned by a test.

Note on scope

A chain-side zero-guard (rejecting a 0 overwrite of a non-zero stored value) was considered and deliberately deferred — it would mask, not fix, and on its own changes nothing since with no writer the value simply stays 0.

…port (OPEN-4)

LEP-6 PR #286 deleted the line that copies the Kademlia byte count onto the
outgoing HostReport, on the reading that "the audit module does not consume this
value for its own consensus logic".

That reading is incorrect. The field is a metric-COURIER, not an audit input.
The chain proto (lumera/audit/v1/audit.proto, HostReport field 6) is explicit:
on successful epoch-report acceptance the audit handler bridges this value into
x/supernode SupernodeMetricsState, "which is the sole source consulted by
Everlight payout / eligibility".

Impact: the chain-side bridge assigns unconditionally with no zero-guard, so a
daemon that omits the field does not merely fail to update it -- it actively
OVERWRITES the stored value with 0 every epoch. At the mainnet default
min_cascade_bytes_for_payment of 1 GiB, no v2.6.x SuperNode can ever qualify for
a payout, because the numerator is structurally zero.

The helper that computes the value, cascadeKademliaDBBytes(), was never removed
and still works; it was simply no longer called. This restores the call.

Verified on a live 5-validator devnet (not just in unit tests). Same validator,
before and after swapping only this binary:

  before:  report_count=454  cascade_kademlia_db_bytes=0
  after:   report_count=455  cascade_kademlia_db_bytes=893056

and the reported value matches on-disk ground truth byte-for-byte:

  du -cb /root/.supernode/data/p2p/data*.sqlite3* -> 893056

No manual legacy MsgReportSupernodeMetrics injection was used; the value arrived
purely through the daemon's own epoch-report path.

Tests: adds supernode/host_reporter/cascade_bytes_reporting_test.go, which
asserts the WIRE contract rather than the helper. The pre-existing tests only
proved cascadeKademliaDBBytes() computes a number -- nothing asserted that number
reached SubmitEpochReport, which is precisely why this regression shipped.

Mutation-verified (each mutation caught by a different subset, so no test is
vacuous and none is solely load-bearing):

  1. delete the assignment (exact v2.6.3 shipped state)
     -> 3 tests fail
  2. hardcode a plausible constant (611842)
     -> 3 tests fail (empty-store, growth-tracking, no-data-dir)
  3. drop WAL/SHM sidecars from the glob (undercount, still non-zero)
     -> 2 tests fail

Also adds a DO-NOT-REMOVE comment at the call site recording why the field is
required, so the next reader does not repeat PR #286's inference.

Verification:
  go build ./...                     ok
  go test ./supernode/...            all packages ok
  go vet ./supernode/host_reporter/  clean
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