fix(host-reporter): restore Cascade Kademlia byte reporting on HostReport (OPEN-4) - #319
Open
mateeullahmalik wants to merge 1 commit into
Open
fix(host-reporter): restore Cascade Kademlia byte reporting on HostReport (OPEN-4)#319mateeullahmalik wants to merge 1 commit into
mateeullahmalik wants to merge 1 commit into
Conversation
…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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Restores the single line that populates
CascadeKademliaDbByteson the outgoingHostReport.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,HostReportfield 6) is explicit: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:
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:
cascade_kademlia_db_bytesMatches on-disk ground truth byte-for-byte:
No manual
MsgReportSupernodeMetricsinjection 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 (whatSubmitEpochReportactually 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:
611842)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 REMOVEcomment at the call site recording why the field is required, so the next reader doesn't repeat PR #286's inference.Verification
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
0for 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.