mirror of
https://github.com/agessaman/meshcore-bot.git
synced 2026-10-22 22:11:15 +00:00
fix(template): stop pathbytes_min reading a hopless packet as multibyte
{path_distance|pathbytes_min:2|prefix_if_nonempty: | Path Dist: } printed
"| Path Dist: N/A" on a direct message. bytes_per_hop_from_routing_and_nodes
returned routing_info's bytes_per_hop before it ever looked at whether there
were any hops, so a 0-hop packet whose format happens to use 2-byte hops
reported 2, the gate passed, and prefix_if_nonempty found "N/A" waiting for
it and dutifully attached the label.
bytes_per_hop describes how a path is encoded. A direct packet has no path
for it to describe, so the format field is not evidence of a wide path and
must not stand in for one. Both docstrings already promised 1 for the direct
case—"Returns 1 when no nodes (direct / unknown)"—so this is the code
catching up to its stated contract rather than a change of policy.
Latent until now: channel messages never had routing_info attached, so the
field was absent and the fallback returned 1 by accident. Direct DMs have
been hitting it all along.
This commit is contained in:
1 parent
ba23899c31
commit
f9f65037a8
3 files changed
+70
-5
No files matched your search
@@ -8,6 +8,14 @@ semantic versioning.
|
||||
|
||||
### Fixed
|
||||
|
||||
- `pathbytes_min` no longer treats a direct message as a multi-byte path, so
|
||||
`{path_distance|pathbytes_min:2|prefix_if_nonempty: | Path Dist: }` stops printing
|
||||
`| Path Dist: N/A` on a hopless packet. `bytes_per_hop` describes how a path is
|
||||
encoded, and a direct packet has no path for it to describe, so
|
||||
`bytes_per_hop_from_routing_and_nodes` now returns 1 whenever the packet reports no
|
||||
hops—which is what its docstring already claimed. The bug was latent until channel
|
||||
messages started carrying routing info.
|
||||
|
||||
- Channel messages are now tied to their own RF packet, so `{packet_hash}`, `{path}`
|
||||
and `{connection_info}` resolve on a channel instead of coming back empty or
|
||||
`Unknown`. MeshCore's CHAN event carries neither `raw_hex` nor a pubkey prefix, so
|
||||
|
||||
+15
-5
@@ -1892,10 +1892,20 @@ def bytes_per_hop_from_routing_and_nodes(
|
||||
) -> int:
|
||||
"""Bytes per hop from packet routing metadata, else inferred from hex node width.
|
||||
|
||||
When ``routing_info`` includes ``bytes_per_hop`` in 1..3, that value wins.
|
||||
Otherwise uses minimum half-byte width among ``node_ids`` (comma or path_nodes).
|
||||
Returns ``1`` when no nodes (direct / unknown).
|
||||
When the packet carries a path and ``routing_info`` includes ``bytes_per_hop``
|
||||
in 1..3, that value wins. Otherwise uses minimum half-byte width among
|
||||
``node_ids`` (comma or path_nodes). Returns ``1`` when no nodes (direct /
|
||||
unknown).
|
||||
|
||||
A hopless packet always reports ``1``, whatever ``bytes_per_hop`` says.
|
||||
``bytes_per_hop`` describes how a path is *encoded*, and a direct packet has no
|
||||
path for it to describe, so letting the format field through would make
|
||||
``pathbytes_min:2`` treat "Direct" as a multi-byte path and print a label for a
|
||||
distance that does not exist.
|
||||
"""
|
||||
path_length = (routing_info or {}).get('path_length')
|
||||
if not node_ids and not path_length:
|
||||
return 1
|
||||
if routing_info:
|
||||
bph = routing_info.get('bytes_per_hop')
|
||||
if isinstance(bph, int) and 1 <= bph <= 3:
|
||||
@@ -1912,8 +1922,8 @@ def message_path_bytes_per_hop(message: Any, *, prefix_hex_chars: int = 2) -> in
|
||||
:func:`extract_path_node_ids_from_message`, then comma/continuous hex via
|
||||
:func:`node_ids_from_path_string` using ``prefix_hex_chars`` for legacy paths.
|
||||
|
||||
Returns ``1`` when no usable path (direct / unparseable) so conservative gates
|
||||
(e.g. ``pathbytes_min:2``) do not treat unknown as multibyte.
|
||||
Returns ``1`` when there is no usable path (direct / unparseable) so conservative
|
||||
gates (e.g. ``pathbytes_min:2``) treat neither unknown nor hopless as multibyte.
|
||||
"""
|
||||
routing_info = getattr(message, 'routing_info', None)
|
||||
node_ids = extract_path_node_ids_from_message(message)
|
||||
|
||||
@@ -22,6 +22,53 @@ def test_message_path_bytes_per_hop_from_routing():
|
||||
assert message_path_bytes_per_hop(msg) == 2
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_hopless_packet_is_never_multibyte():
|
||||
"""bytes_per_hop describes how a path is encoded; a direct packet has no path for
|
||||
it to describe, so pathbytes_min must not read the format field as a wide path."""
|
||||
msg = MeshMessage(
|
||||
content="test",
|
||||
channel="c",
|
||||
path="Direct",
|
||||
routing_info={"bytes_per_hop": 2, "path_length": 0, "path_nodes": []},
|
||||
)
|
||||
assert message_path_bytes_per_hop(msg) == 1
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_pathbytes_min_hides_label_on_a_direct_message():
|
||||
"""A direct message has no path distance, so the whole clause must disappear
|
||||
rather than render "Path Dist: N/A"."""
|
||||
msg = MeshMessage(
|
||||
content="test",
|
||||
channel="c",
|
||||
path="Direct",
|
||||
routing_info={"bytes_per_hop": 2, "path_length": 0, "path_nodes": []},
|
||||
)
|
||||
out = format_piped_template(
|
||||
"ack{path_distance|pathbytes_min:2|prefix_if_nonempty: | Path Dist: }",
|
||||
{"path_distance": "N/A"},
|
||||
message=msg,
|
||||
)
|
||||
assert out == "ack"
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_pathbytes_min_still_passes_a_real_multibyte_path():
|
||||
msg = MeshMessage(
|
||||
content="test",
|
||||
channel="c",
|
||||
path="7a2a,0102 (2 hops)",
|
||||
routing_info={"bytes_per_hop": 2, "path_length": 2, "path_nodes": ["7A2A", "0102"]},
|
||||
)
|
||||
out = format_piped_template(
|
||||
"ack{path_distance|pathbytes_min:2|prefix_if_nonempty: | Path Dist: }",
|
||||
{"path_distance": "12.4km"},
|
||||
message=msg,
|
||||
)
|
||||
assert out == "ack | Path Dist: 12.4km"
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_message_path_bytes_per_hop_infers_from_nodes():
|
||||
msg = MeshMessage(
|
||||
|
||||
Reference in new issue
Block a user