Files
meshcore-analyzer/internal/packetpath/advert.go
T
n30nex b9fb3d244c feat(analytics): split adverts using recorded route evidence (#2088)
Red commits: `dc7dcbe`, `76e3217` ([assertion
failures](https://github.com/Kpa-clawbot/CoreScope/actions/runs/37059977385)).

Fixes #2041; supplies #2085's backend contract.

Records at most two route bits per retained advert. Node flood counts
now use the same evidence, including mixed and transport-flood adverts.
Analytics failures log/count errors while core observation, path and
liveness writes continue. The unrelated recent-advert limit clamp is
removed.

Direct adverts (empty path) describes the observed remaining path across
valid hash widths. Firmware can forward an advert down to an empty path;
this cannot establish original send mode or RF distance. The `zero_hop`
API spelling remains compatible.

Successful post-upgrade evidence writes survive observation replacement
and restart. Older overwritten frames and failed writes can leave gaps.
The UI explains automatic background backfill.

## Measured validation

Synthetic Windows workloads; timings are not production guarantees:

- 300K retained adverts, one-hour window: median 64.35→39.84 ms; 13.98
MB→145 KB allocated. Seven-day allocations unchanged; five paired
samples.
- 1M transmissions/11M observations: backfill 5m43s. Simple 10 Hz
writer: all 3,423 observations persisted; p99 28 ms, maximum 323 ms.
- Simulated pre-backfill cursor: retained evidence ready 4m21s; full
catch-up 6m41s, 122 cache invalidations. Normal completed-migration
startup bulk-loads current evidence.

Portable opt-in scale tests and window benchmarks are included. All 183
frontend suites, full server tests, targeted races, lint and real-API
desktop/mobile checks passed. Full [Linux
CI](https://github.com/Kpa-clawbot/CoreScope/actions/runs/37063210229)
passed at `36def9c`; three independent reviews are clear. Local Windows
testing hit the unchanged symlink-privilege test. No configuration
changes.

Preflight overrides: external script/OpenClaw profile unavailable;
repository checks and Chromium used.
2026-10-03 12:16:55 +02:00

66 lines
1.9 KiB
Go

package packetpath
import "encoding/hex"
const (
AdvertFlood uint8 = 1
AdvertDirectEmptyPath uint8 = 2
)
// AdvertRouteEvidence classifies one received wire frame, independently of a
// canonical transmission's metadata. Mesh::sendZeroHop writes path_len = 0;
// Mesh::onRecvPacket -> removeSelfFromPath -> retransmit can also leave an
// empty remaining path, preserving the hash-size flags. Neither encoding
// proves an original zero-hop send or RF distance. Transport
// routes carry four bytes before path_len (firmware Packet.cpp / Mesh.cpp).
// The fixed buffer bounds both work and allocation to a radio-sized frame.
func AdvertRouteEvidence(raw string) uint8 {
var frame [256]byte
if len(raw)%2 != 0 || len(raw) > len(frame)*2 {
return 0
}
n, err := hex.Decode(frame[:], []byte(raw))
if err != nil || n < 3 || (frame[0]>>2)&15 != 4 {
return 0
}
route := int(frame[0] & 3)
pathOffset := 1
if IsTransportRoute(route) {
pathOffset += 4
}
if n <= pathOffset+1 {
return 0
}
path := frame[pathOffset]
hashSize := int(path>>6) + 1
pathBytes := int(path&63) * hashSize
payloadBytes := n - pathOffset - 1 - pathBytes
if hashSize == 4 || pathBytes > 64 || payloadBytes < 1 || payloadBytes > 184 {
return 0
}
if route == RouteFlood || route == RouteTransportFlood {
return AdvertFlood
}
if path&63 == 0 {
return AdvertDirectEmptyPath
}
return 0
}
// AdvertKind describes the union of known evidence, not exclusive historical
// use: legacy observations may already have been overwritten before upgrade,
// or evidence writes may have failed. The API spelling "zero_hop" is retained
// for compatibility and denotes observed direct empty-path frames only.
func AdvertKind(evidence uint8) string {
switch evidence & (AdvertFlood | AdvertDirectEmptyPath) {
case AdvertFlood:
return "flood"
case AdvertDirectEmptyPath:
return "zero_hop"
case AdvertFlood | AdvertDirectEmptyPath:
return "mixed"
default:
return "other"
}
}