Skip to content

python: add new pigeonhole API#43

Merged
david415 merged 182 commits into
mainfrom
update_python_pigeonhole
May 5, 2026
Merged

python: add new pigeonhole API#43
david415 merged 182 commits into
mainfrom
update_python_pigeonhole

Conversation

@david415
Copy link
Copy Markdown
Member

@david415 david415 commented Feb 7, 2026

No description provided.

…cancel tests

- Add error codes 14-24 to Rust thin client (matching Go daemon)
- Fix Python error strings for codes 19/20 to match Go
- Add unit test for error code completeness (no daemon required)
- Add integration tests for cancel_resending
- Add PigeonholeGeometry to ConfigFile and Config structs
- Fix serde rename to use MaxPlaintextPayloadLength (matching Go)
- Add ThinClient::pigeonhole_geometry() accessor method
- Update testdata config to match generated mixnet config
- Fix tombstone tests to use geometry from config instead of hardcoded values
The replica_epoch is already embedded in the EnvelopeDescriptor,
making the parameter redundant.

- Python: Remove replica_epoch from encrypt_read, encrypt_write,
  start_resending_encrypted_message, and tombstone_box
- Rust: Remove replica_epoch from structs and function signatures
- Tests: Update all call sites to use new API signatures
- Fix cancel tests: Reduce sleep time to 0.1s to call cancel before
  mixnet ACK arrives
david415 added 23 commits April 21, 2026 13:36
Expand the thinnest method docstrings on ThinClient (new_message_id,
new_surb_id, new_query_id, pki_document, is_connected, get_service) to
include # Arguments / # Errors sections where relevant, and document the
distinction between "daemon connected" and "daemon connected to mixnet".

Add doc comments to the previously-undocumented ThinClientError variants
(IoError, CborError, ConnectError, MissingPkiDocument, ServiceNotFound,
OfflineMode, Timeout, Other), so each variant's docs.rs entry explains
when it is produced rather than being empty.

No API or behaviour changes.
Expand the thinnest method docstrings on ThinClient (is_connected,
pki_document, get_service, new_message_id, new_surb_id, new_query_id)
to explain when each error is raised and document the distinction
between "daemon connected" and "daemon connected to mixnet".

No API or behaviour changes.
Introduces a new katzenpost_thinclient.transport package with
UnixDialConfig / TcpDialConfig dataclasses and a DialConfig
discriminator matching the Go reference. ConfigFile.load() now parses
[Dial.Unix] / [Dial.Tcp] subtables rather than flat Network/Address
fields; ThinClient resolves the dialer via DialConfig.resolve() rather
than dispatching on a lowercased network string.

No protocol changes — the thin-client wire format (4-byte BE length
prefix + CBOR) is unchanged. Integration tests against the refactored
Go kpclientd pass end-to-end.
Introduces src/transport/ with a Dialer trait and subtable-
discriminated DialConfig { unix, tcp }, mirroring the Go reference and
Python port. ConfigFile.load and Config::new parse [Dial.Unix] /
[Dial.Tcp] subtables rather than flat Network/Address fields;
ThinClient::new and its reconnect path resolve the dialer through
DialConfig::dial() rather than matching on a lowercased network
string.

No protocol changes — the thin-client wire format (4-byte BE length
prefix + CBOR) is unchanged. 13 lib unit tests cover DialConfig
validation and subtable parsing; 23 integration tests against the
refactored Go kpclientd pass end-to-end.
The recent transport modularisation changed the thinclient config
format (flat Network/Address keys → [Dial.Unix]/[Dial.Tcp] subtables).
Old configs were silently accepted, producing surprising failures
later in mixnet operations rather than a clear error at load time.

Rust: add serde(deny_unknown_fields) to ConfigFile, DialConfig,
UnixDialConfig, TcpDialConfig, Geometry, and PigeonholeGeometry so
any unknown or misspelled key fails the TOML parse with a pinpointed
line/column diagnostic.

Python: introduce ConfigError; rewrite ConfigFile.load with explicit
checks for unknown / missing top-level keys, type-validate each
subtable, and reject unknown keys within [Dial], [Dial.Unix],
[Dial.Tcp], and [PigeonholeGeometry]. Also load PigeonholeGeometry
(previously silently dropped) and expose it on Config. Replace the
assert on SphinxGeometry shape (disabled under python -O) with an
explicit raise.
The parallel-heavy thin_client CI (pytest -n 5 alongside cargo test
--test-threads=5) pushes enough concurrent load at the 3-service-node
docker mixnet that multi-chunk copy flows occasionally exceed 30s
for their temp-stream boxes to propagate and become shard-readable.
Raise the ten post-write / post-copy sleeps in
test_new_pigeonhole_api.py from 30s to 45s. Shorter polling sleeps
(1s/5s/10s) and the one pre-existing 60s sleep are untouched.

Sends remain ARQ-backed; this bump is strictly propagation-wall-
clock slack, not a workaround for a dropped send.
Mirror the daemon's GetMessageBoxIndexCounter request added in
katzenpost commit 66891b7e. Callers that persist MessageBoxIndex blobs
across sessions (katzenqt is the current example) can now read the
BACAP Idx64 counter through the thin client instead of peeking at the
first 8 bytes of the blob themselves — the layout
(little-endian uint64) is an hpqc/bacap implementation detail the thin
client should not rely on.

pigeonhole.py grows `get_message_box_index_counter(mbi) -> int`,
shaped symmetrically with `next_message_box_index`. __init__.py
imports and attaches it to ThinClient alongside the other pigeonhole
helpers.

Smoke-verified by importing katzenpost_thinclient and asserting
ThinClient.get_message_box_index_counter is bound.
genkey emits caps; send streams a CBOR FileMetaData header followed
by file bytes; receive reverses it. Behind the cli feature.
Round-trips a 4 KiB file across three boxes.
@david415 david415 force-pushed the update_python_pigeonhole branch from aa8e89b to 2995a6f Compare April 27, 2026 16:47
@david415 david415 force-pushed the update_python_pigeonhole branch from 2995a6f to fe379bf Compare April 27, 2026 16:51
@david415 david415 merged commit 046a54b into main May 5, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant