py-jam-erasure-bindings
Native Python bindings for the Graypaper 0.7.2 Appendix H erasure transform. The package has no Python runtime dependencies and no dependency on PyJAMaz. It exposes Python functions; no public Rust crate API is supported.
Install and use
python -m pip install py-jam-erasure-bindings==0.1.0
CPython 3.12, 3.13, and 3.14 use the same cp312-abi3 binary on each supported
platform: Linux x86_64/ARM64 (manylinux2014) and macOS x86_64/ARM64 (11.0+).
Published wheels need no Rust compiler. Building the source distribution needs
Rust 1.82 or newer and a C toolchain; CI uses Rust 1.85.0.
from jam_erasure import encode_shards, recover_shards
data = b"Appendix H"
shards = encode_shards(data, 2, 4) # Tiny: 2 originals, 4 recovery shards
padded = recover_shards(2, 4, [(2, shards[2]), (5, shards[5])])
assert padded[:len(data)] == data
assert padded[len(data):] == bytes(len(padded) - len(data))
Binding contract
encode_shards(data, original_count, recovery_count) -> list[bytes]accepts the existing PyO3 byte-vector inputs.datamust be non-empty. Both shard counts must be positive and supported byreed-solomon-simd=3.1.0.- Input is zero-padded to a multiple of
2 * original_count. Output is systematic-first:original_countcontiguous data shards followed byrecovery_countparity shards. Shard size is2 * ceil(len(data) / (2 * original_count)). recover_shards(original_count, recovery_count, shards) -> bytesrequires exactlyoriginal_count(global_index, shard_bytes)pairs. Indexes are unique and lie in0 .. original_count + recovery_count - 1; order is immaterial. Shards must share a non-zero even size. The result includes zero padding and does not take an original-length argument.- Tiny uses
(2, 4)and Full uses(342, 681). Both may be used in one process; there is no ambient profile setting. This low-level API retains its original behavior, including accepting other count combinations supported by the backend. - Native validation/backend failures and caught unwinding panics become
ValueError; PyO3 argument conversion retainsTypeError/OverflowError. Computation releases the Python GIL.
Callers own protocol length limits before allocation, empty-blob conventions,
selection of a threshold set from extra shards, original-length/padding checks,
and commitment authentication. In PyJAMaz these remain in pyjamaz.erasure
and its availability layer. This binding recovers bytes; recovery alone does
not authenticate them. No shard data is read from disk or the network.
Specification and evidence
Normative source: Graypaper 0.7.2,
Appendix H, including H.1–H.3 prose and the referenced little-endian E2 encoding.
The implementation preserves the existing per-two-byte-column transform;
applying the backend once to multi-word shards changes protocol bytes.
| Rules | Implementation | Evidence |
|---|---|---|
| H.1–H.2; zero padding prose | encode_impl splits padded input; recover_impl joins systematic data |
test_boundaries_and_padding, all W3F cases |
| H.3 transposition | Per-word encode/decode loops; Tiny tables derive the identical linear map from the pinned backend | Rust batched_lanes_match_appendix_h_column_reference, W3F encoding |
| H.4 systematic-first chunks | encode_impl returns original shards then recovery shards |
test_w3f_encoding_vectors for six Tiny and six Full fixtures |
| H.5 indexed recovery | recover_impl validates threshold cardinality/indexes and reconstructs each column |
test_w3f_recovery_vectors with systematic, recovery-only and mixed selections; malformed-input tests |
| H.6–H.7 field polynomial | Pinned reed-solomon-simd=3.1.0, polynomial 0x1002D |
Every W3F encoded byte and recovered input |
| H.8–H.9 Cantor basis and LE words/indexes | Pinned backend plus two-byte slicing and little-endian Tiny tables | W3F vectors and Rust independent per-column comparison |
| H.10–H.11 interpolation and evaluation | Pinned backend encode/decode calls | W3F parity/recovery cases and Rust recovery-only roundtrip |
The complete-systematic fast path, deterministic selection from surplus shards, and rejection of nonzero reconstructed padding remain caller responsibilities. All twelve fixtures retain their source commit and license. No protocol interpretation or compatibility setting is introduced by extraction.
Build and validate
python -m venv .venv
.venv/bin/python -m pip install '.[dev]'
cargo test --locked
.venv/bin/python -m pytest -q
.venv/bin/python -m build
.venv/bin/python scripts/check_artifacts.py dist
PEP-517 builds use release optimization, thin LTO, one codegen unit, a committed
Cargo lock, and abi3-py312; CI sets a portable CPU target. The source
distribution includes the Rust source, Cargo lock, tests, fixture provenance,
and license texts. Fixtures and tests are excluded from the binary wheel.
Publishing
The release workflow builds all four platform wheels from an sdist and tests
installed binaries outside the checkout on CPython 3.12, 3.13, and 3.14.
A matching vVERSION or pypi/vVERSION tag publishes only after all seventeen
validation jobs pass. The pypi GitHub environment uses the organization secret
PYPI_API_TOKEN; it must have permission to publish this PyPI project. Token
values are never committed or printed. Package author/contact metadata is
JAMdot Technologies devops@jamdot.tech.
The original GitHub-only v0.1.0 tag is retained as extraction evidence. The
first PyPI release uses pypi/v0.1.0, which includes the corrected author
contact and its newly built artifacts. Do not use the earlier GitHub assets as
PyPI release artifacts. The artifact checker enforces the approved author email.
If publishing fails after successful validation, run release.yml manually
with the original release_run_id and release_tag. Recovery verifies the
repository, workflow, tag commit, all required jobs, and immutable artifact IDs
before downloading and checking the exact artifacts. It does not rebuild or
move tags, and does not silently skip previously uploaded files.
Native upgrades require a new package release, lockfile review, regression
evidence, and an explicit consumer dependency change. Builds use --locked
and portable CPU targets. See PROVENANCE.md for source history
and licensing.
Release files for py-jam-erasure-bindings 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| py_jam_erasure_bindings-0.1.0.tar.gz | 186.2 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| py_jam_erasure_bindings-0.1.0-cp312-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl | CPython 3.12 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| py_jam_erasure_bindings-0.1.0-cp312-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl | CPython 3.12 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| py_jam_erasure_bindings-0.1.0-cp312-abi3-macosx_11_0_x86_64.whl | CPython 3.12 | abi3 | macOS 11.0+ x86-64 | Details |
| py_jam_erasure_bindings-0.1.0-cp312-abi3-macosx_11_0_arm64.whl | CPython 3.12 | abi3 | macOS 11.0+ ARM64 | Details |
Total release size: 1.3 MB
Release files / py_jam_erasure_bindings-0.1.0.tar.gz
| Download URL | py_jam_erasure_bindings-0.1.0.tar.gz |
|---|---|
| Size | 186.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
de6e89f3c1d8d21f40f3a257591909f4a00f5a75e82c6ae5ffea57187803b05b
|
|
BLAKE2b-256 checksum How to use checksums |
7899cbcf9758b86df68b6806772f626686bdfdccb77842cd3dd4d0298c5ccf45
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / py_jam_erasure_bindings-0.1.0-cp312-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
| Download URL | py_jam_erasure_bindings-0.1.0-cp312-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl |
|---|---|
| Size | 312.9 kB |
| Tags | CPython 3.12 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
f1d96351f01c0ce1a54a0dc5c77b7a5f7245407d2e3bb8ff884c6c29bd672e08
|
|
BLAKE2b-256 checksum How to use checksums |
6b45478732bd1293e86f4cd6d7e394d5cb27a106e7df2584d9bac79e47b1353d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / py_jam_erasure_bindings-0.1.0-cp312-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
| Download URL | py_jam_erasure_bindings-0.1.0-cp312-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl |
|---|---|
| Size | 288.2 kB |
| Tags | CPython 3.12 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
0c3e3d80031c5f58a57103f841364077fb9647c9563bb2103aba5abc80b3be7b
|
|
BLAKE2b-256 checksum How to use checksums |
24823cdec792a1a024f43e23982b324b57cd978cf66e40285dc3e1f3e4ecb776
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / py_jam_erasure_bindings-0.1.0-cp312-abi3-macosx_11_0_x86_64.whl
| Download URL | py_jam_erasure_bindings-0.1.0-cp312-abi3-macosx_11_0_x86_64.whl |
|---|---|
| Size | 287.7 kB |
| Tags | CPython 3.12 abi3 macOS 11.0+ x86-64 |
|
SHA-256 checksum How to use checksums |
3fbd35bb14ae74ca340cd6cea45a98a12cad6b643aa04ca617582e650a570941
|
|
BLAKE2b-256 checksum How to use checksums |
1cca85a76d5d821acd21e9dad6c049c5870e7ba570f58f356c859cde798fe9de
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / py_jam_erasure_bindings-0.1.0-cp312-abi3-macosx_11_0_arm64.whl
| Download URL | py_jam_erasure_bindings-0.1.0-cp312-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 266.3 kB |
| Tags | CPython 3.12 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
3c65aebf450da98263c6591328cd7f2e099c177a7918fcd7d72b70fd3a0898d4
|
|
BLAKE2b-256 checksum How to use checksums |
24cab3e7b34805ee3b11ea6f72110ee19057732032e4beb3c6a2714eea67981d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|