Files
meshcore-analyzer/internal
Adam 4fdd494d9b fix(nodes): read the transport-direct path byte at offset 5 (#2225) (#2234)
Red commit: 3bb81254 (fails on assertions both ways: `zero-hop counts =
map[pk_relayed:map[SAT:1]], want map[pk_transport:map[AUS:1]]`)

Fixes #2225

## What this does

`nodeZeroHopRegionCounts` read the path byte at offset 1 for
`ROUTE_TYPE_TRANSPORT_DIRECT` adverts. Transport routes carry 4
transport-code bytes between the header and `path_length` (firmware
`docs/packet_format.md`), so offset 1 is the first byte of
`transport_code_1`. Two effects, both fixed:

- A transport-direct zero-hop advert counted as zero-hop only when that
code byte's low 6 bits happened to be 0, so the node usually got
`fewest_hops` instead of `zero_hop`, and #804 analytics missed it.
- A relayed transport-direct advert whose first code byte was `0x00` (or
`0x40`, `0x80`, …) counted as zero-hop.

## How

- New `packetpath.PathByte(rawHex) (routeType int, pathByte byte, ok
bool)` applies the transport-code offset in one place, next to the
existing `IsTransportRoute`, `HashSize` and `DecodePathFromRawHex`.
- Every reader of the path byte from `raw_hex` in `store.go` now uses
it:
  - `nodeZeroHopRegionCounts` (the bug);
  - `computeAnalyticsHashSizes`;
  - `computeNodeHashSizeInfo`;
  - `computeMultiByteCapability`.

The last three already had the right offset, each with its own copy of
the rule, so their behavior doesn't change. `packetpath.HashSize` uses
`PathByte` too.

## Performance

- `PathByte` runs once per advert on every recompute, so it must not
allocate. `hexByteAt` now decodes the two hex nibbles itself instead of
calling `hex.DecodeString`; `TestPathByteDoesNotAllocate` pins it at 0
allocs.
- Without that, `BenchmarkRecomputeNodeHomeRegionSets` went from 17,232
to 457,232 allocs/op. With it, the count is unchanged from master.
- Time on the same machine (Apple M5, Docker linux/arm64, `-count 3`):
~61 ms/op on master, ~54 ms/op here. Your hardware measured ~3x higher
on #2190, so expect proportionally more there; the change itself only
removes work.

## Tests

- `TestZeroHopCountsReadTransportDirectPathByte`: a transport-direct
zero-hop advert whose first code byte is `0xaa` counts, and a relayed
one (path byte `0x41`) whose first code byte is `0x00` doesn't. Checked
through both `nodeZeroHopRegionCounts` and `computeNodeHomeRegions`
(#804).
- `TestPathByte` covers all four route types, upper-case hex, and
too-short or malformed input. `TestPathByteDoesNotAllocate` pins the
allocation count.
- `go test` passes for `cmd/server`, `cmd/ingestor` and
`internal/packetpath` (`CGO_ENABLED=1`). `gofmt` and `go vet` are clean.

No API or UI change, no new `map[string]interface{}`, and no config.
2026-10-16 10:53:10 +02:00
..