Skip to content

zap_transport: binary wire encoding for PaymentOffer / PaymentProof#21

Open
abhicris wants to merge 1 commit intomainfrom
zap-transport
Open

zap_transport: binary wire encoding for PaymentOffer / PaymentProof#21
abhicris wants to merge 1 commit intomainfrom
zap-transport

Conversation

@abhicris
Copy link
Copy Markdown
Contributor

What

Adds switchboard/zap_transport.py — encode/decode PaymentOffer and PaymentProof over the ZAP wire format (port 9999) as a zero-allocation alternative to the existing JSON-in-HTTP-headers path.

Why

The HTTP/JSON transport is fine for HTTP/REST agents but expensive for high-volume agent-to-agent traffic — every offer is parsed, allocated, and copied. When two agents sit on the same Lux network, ZAP lets them exchange offers and proofs with zero parse-time allocation and ~10× smaller payloads (sanity-checked in test_offer_wire_smaller_than_json).

This is the first real consumer of zap_py, the pure-stdlib Python port of the ZAP protocol. Validates the port end-to-end with a production switchboard data model.

Wire layout

Schemas are declared with zap_py.StructBuilder so a Go counterpart mirrors them exactly:

PaymentOffer:
  scheme(u8) | chain_id(u64) | expires_at(u64, 0=null)
  | recipient(address) | amount(bytes,uint256-be) | currency(text)
  | description(text) | endpoint(text) | nonce(text)

PaymentProof:
  chain_id(u64) | timestamp(u64) | payer(address) | tx_hash(hash32)
  | amount(bytes,uint256-be) | nonce(text)

amount is a 32-byte big-endian uint256 rather than a uint64, so realistic on-chain values aren't truncated. Otherwise types match the existing JSON shape 1:1.

Optional dependency

zap_py is an optional dependency. If it isn't installed, the module imports cleanly and encode_offer / decode_offer raise ZapNotAvailable so callers fall back to the JSON path. Tests use pytest.importorskip so the suite stays green either way.

Install path (until luxfi-zap is on PyPI):

pip install 'luxfi-zap @ git+https://github.com/luxfi/zap@main#subdirectory=python'

Test plan

  • pytest tests/test_zap_transport.py -v11 passed with zap_py installed
    • schema layout sanity
    • offer minimal + full roundtrip
    • every PaymentScheme value
    • uint256-max amount
    • overflow + negative rejection
    • proof roundtrip
    • invalid tx_hash length rejection
    • ZapNotAvailable gating when zap_py is forced off
    • ZAP wire size ≤ JSON size for a realistic offer
  • pytest tests/test_x402_middleware.py tests/test_gas_budget.py tests/test_gas_tracker.py40 passed (existing suite still green)
  • pytest tests/test_zap_transport.py with zap_py uninstalled — module imports cleanly, suite skips
  • Two pre-existing test files (test_nonce_manager.py, test_payment_protocol.py) have collection-time syntax errors on main, unrelated to this PR

Adds switchboard/zap_transport.py — encode/decode PaymentOffer and
PaymentProof over the ZAP wire format (luxfi/zap, port 9999) as a
zero-allocation alternative to the existing JSON-in-HTTP-headers path.

Why: switchboard's HTTP/JSON transport is fine for HTTP/REST agents
but expensive for high-volume agent-to-agent traffic (every offer
parsed, allocated, copied). When two agents sit on the same Lux
network, ZAP lets them exchange offers/proofs with zero parse-time
allocation and ~10x smaller payloads.

zap_py is an optional dependency. If it isn't installed, the module
still imports cleanly and encode/decode raise ZapNotAvailable so
callers can fall back to the JSON path. Tests use pytest.importorskip
so the suite stays green either way.

Wire layout uses zap_py.StructBuilder so the schema is pinned and a
Go counterpart can mirror it exactly:

  PaymentOffer:
    scheme(u8) | chain_id(u64) | expires_at(u64, 0=null)
    | recipient(address) | amount(bytes,uint256-be) | currency(text)
    | description(text) | endpoint(text) | nonce(text)

  PaymentProof:
    chain_id(u64) | timestamp(u64) | payer(address) | tx_hash(hash32)
    | amount(bytes,uint256-be) | nonce(text)

amount is a 32-byte big-endian uint256 rather than a uint64 so realistic
on-chain values aren't truncated.

11 tests cover: schema layout sanity, minimal+full offer roundtrip,
each PaymentScheme value, uint256-max amount, overflow/negative
rejection, proof roundtrip, invalid tx_hash length, ZapNotAvailable
gating, and a wire-size-vs-JSON sanity check.

Existing 40-test switchboard suite remains green. Two pre-existing
test files (test_nonce_manager.py, test_payment_protocol.py) had
collection-time syntax errors before this branch; they remain
unchanged.
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