83 lines
5.3 KiB
Markdown
83 lines
5.3 KiB
Markdown
|
|
No, I don’t need `SPEC.md` or `SOURCES.md` for this first report. I used the checked-out LXMF source directly. I did not edit `SPEC.md` or any other file.
|
|||
|
|
|
|||
|
|
**LXMessage Serialized Structure**
|
|||
|
|
|
|||
|
|
Source inspected: LXMF commit `fab12ad9bf9f997797034950f289fe41a79dcf5a`
|
|||
|
|
|
|||
|
|
Core `lxmf_bytes` layout:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
destination_hash || source_hash || signature || msgpack_payload
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Where `msgpack_payload` is:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
[
|
|||
|
|
timestamp,
|
|||
|
|
title,
|
|||
|
|
content,
|
|||
|
|
fields,
|
|||
|
|
optional_stamp
|
|||
|
|
]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
The fifth element is only present when a normal message stamp is generated and appended.
|
|||
|
|
|
|||
|
|
| Field | Serialized position | Type / size | Source origin | Test vector confirmed |
|
|||
|
|
|---|---:|---|---|---|
|
|||
|
|
| `destination_hash` | bytes `0..15` | 16 bytes | [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:383), length from [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:40) and RNS 128-bit truncated hashes in [Reticulum.py](/usr/local/src/reticulum/Reticulum/RNS/Reticulum.py:146) | No |
|
|||
|
|
| `source_hash` | bytes `16..31` | 16 bytes | [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:384) | No |
|
|||
|
|
| `signature` | bytes `32..95` | 64 bytes | [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:378), [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:385); RNS signature length from [Identity.py](/usr/local/src/reticulum/Reticulum/RNS/Identity.py:59) and [Identity.py](/usr/local/src/reticulum/Reticulum/RNS/Identity.py:80) | No |
|
|||
|
|
| `msgpack_payload` | bytes `96..end` | msgpack list | [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:362), packed at [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:381) | No |
|
|||
|
|
| `timestamp` | payload index `0` | Python float, normally msgpack float64 on this RNS umsgpack | [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:357), [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:362); float64 behavior from [umsgpack.py](/usr/local/src/reticulum/Reticulum/RNS/vendor/umsgpack.py:1177) and [umsgpack.py](/usr/local/src/reticulum/Reticulum/RNS/vendor/umsgpack.py:325) | No |
|
|||
|
|
| `title` | payload index `1` | bytes | [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:130), [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:193), [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:362) | No |
|
|||
|
|
| `content` | payload index `2` | bytes | [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:135), [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:202), [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:362) | No |
|
|||
|
|
| `fields` | payload index `3` | dict, default `{}` | [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:215), [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:362) | No |
|
|||
|
|
| `stamp` | payload index `4`, optional | bytes, only if generated | [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:371), [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:373); extracted on unpack at [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:754) | No |
|
|||
|
|
|
|||
|
|
**Hash And Signature**
|
|||
|
|
|
|||
|
|
`message_id` / `hash` is:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
SHA256(destination_hash || source_hash || msgpack([timestamp, title, content, fields]))
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Source: [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:364), [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:368), RNS SHA-256 at [Identity.py](/usr/local/src/reticulum/Reticulum/RNS/Identity.py:238).
|
|||
|
|
|
|||
|
|
The signature is over:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
destination_hash || source_hash || msgpack([timestamp, title, content, fields]) || message_id
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Source: [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:375), [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:378), RNS signing at [Identity.py](/usr/local/src/reticulum/Reticulum/RNS/Identity.py:767).
|
|||
|
|
|
|||
|
|
Important: the optional normal `stamp` is excluded from both `message_id` and signature. Unpack removes payload index `4` before recomputing hash/signature material: [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:754).
|
|||
|
|
|
|||
|
|
**Outer Representations**
|
|||
|
|
|
|||
|
|
Direct/link/resource delivery uses full `self.packed` unchanged: [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:636), [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:654).
|
|||
|
|
|
|||
|
|
Opportunistic packet delivery omits the destination hash from the packet payload because the RNS packet destination already implies it:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
source_hash || signature || msgpack_payload
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Source: [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:633).
|
|||
|
|
|
|||
|
|
Propagated and paper messages wrap/encrypt everything after the destination hash:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
destination_hash || encrypted(source_hash || signature || msgpack_payload)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Source: propagated [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:429), paper [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:449). Propagation transit additionally msgpacks `[time.time(), [lxmf_data]]`: [LXMessage.py](/usr/local/src/reticulum/LXMF/LXMF/LXMessage.py:436).
|
|||
|
|
|
|||
|
|
**Notes**
|
|||
|
|
|
|||
|
|
The README is not authoritative here: it describes payload order as timestamp, content, title, fields, but current code serializes timestamp, title, content, fields.
|
|||
|
|
|
|||
|
|
No test vector confirmation exists in this checkout. There is no `tools/` directory and no tracked `SPEC.md` or `SOURCES.md`, so every “Test vector confirmed” entry above is marked `No`.
|