Skip to content

[PQ-5] Extend ZAP wire schema with signature_alg + signature fields #38

@Pattermesh

Description

@Pattermesh

Part of #33. Built on #TBD (PQ-4).

Deliverables

Modify switchboard/zap_transport.py. Append two fields to both OFFER_SCHEMA and PROOF_SCHEMA (append-only keeps old readers ignoring them):

def _build_offer_schema():
    return (
        StructBuilder("SwitchboardPaymentOffer")
        # … existing fields …
        .uint8("signature_alg")    # registry tag (0x00 = none)
        .bytes("signature")        # variable-length, raw bytes
        .build()
    )

Update encode_offer / decode_offer / encode_proof / decode_proof to read and write the new fields. When signature_alg == 0x00, the signature bytes field is empty.

Pin alg-tag mapping at the top of the file (mirrors _SCHEME_TO_WIRE):

_PQ_ALG_TO_TAG = {
    "none": 0x00,
    "ecdsa-secp256k1": 0x01,
    "ml-dsa-44": 0x10,
    "ml-dsa-65": 0x11,
    "ml-dsa-87": 0x12,
    "slh-dsa-128s": 0x20,
    "slh-dsa-128f": 0x21,
    "hybrid-ecdsa-ml-dsa-65": 0x80,
}

signing_transcript() for ZAP payloads MUST zero the signature_alg and signature field bytes before hashing (spec §11).

Tests

  • Round-trip per alg: encode → decode → verify field equality.
  • Old reader (schema without new fields) decodes a new-format payload OK (ignores trailing fields).
  • New reader decodes an old-format payload with signature_alg="none", signature=b"".

Done when

  • pytest tests/test_zap_transport.py -v green with new cases.
  • Wire offset constants documented inline as table comment.
  • Go-side luxfi/zap interop tracked in PQ-11 (not blocking this issue).

Depends on: #TBD (PQ-4).

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions