Metadata-Version: 2.4
Name: hash-frx
Version: 0.1.0
Summary: hash-frx — FRX-native hash primitives (Poseidon, Poseidon2, SHA-256, sponge and compression constructions), each lowering to a single fused kernel.
Author: The hash-frx Authors
License: Apache-2.0
Project-URL: Repository, https://github.com/fractalyze/hash-frx
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy
Requires-Dist: blake3
Requires-Dist: frx!=0.10.1,>=0.10.1.dev20260812040018
Dynamic: license-file

# hash-frx

FRX-native hash primitives — algebraic permutations and byte hashes, each written
to lower to a **single fused kernel**.

`hash-frx` sits between **FRX** — Fractalyze's fork of
[JAX](https://github.com/jax-ml/jax) — and everything that hashes: the proving
blocks in [`zorch`](https://github.com/fractalyze/zorch), the signature schemes in
`sig-frx`, and any other FRX consumer. FRX provides tracing and codegen, lowered
through **Fractalyze XLA**, its fork of stock [XLA](https://github.com/openxla/xla)
that adds native field and elliptic-curve types.

## Design philosophy

- **Two seams, no concrete hash in the consumer.** `Permutation` is a fixed-width
  permutation over a single dtype — a field one for the algebraic hashes
  (Poseidon, Poseidon2), a machine word for the bit-oriented ones
  (Keccak-f[1600]); `ByteHash` maps a batch of
  equal-length byte messages to digests (SHA-256, BLAKE3, SHA-3). A
  consumer reads `width`/`dtype` or `digest_size` and calls `permute`/`digest` —
  it never names the hash it runs on.
- **Fusion by construction.** A permutation call, a digest call, and each
  sponge `absorb`/`squeeze` lower to one fused kernel *by construction* — a
  `lax.composite` marker an XLA emitter recognizes — never by a per-primitive
  compiler pattern-match.
- **Application-agnostic.** No proving scheme, signature scheme, or blockchain
  leaks in. Domain separation, parameter choice, and padding conventions belong
  to the consumer.
- **Byte-exact with the standard.** A byte hash reproduces its specification
  exactly (SHA-256 = FIPS 180-4, BLAKE3 = the BLAKE3 spec, SHA-3/SHAKE = FIPS
  202), verified against the published test vectors.

## Installation

Releases are on PyPI, so nothing else has to be configured:

```sh
pip install hash-frx
```

Dev builds also publish to the Fractalyze package index on every green build of
`main`. They are timestamped `X.Y.Z.devYYYYMMDDHHMMSS` and exist so a consuming
workspace can pin the exact build it tested against, which means naming both the
index and the version:

```sh
pip install hash-frx==0.1.0.dev20260730045722 \
    --extra-index-url https://fractalyze.github.io/pypi/simple/
```

Both carry the runtime tree only — the `testing/` packages, including the
reference fixtures, are not package API.

A Bazel consumer takes the module directly and needs no wheel:

```python
bazel_dep(name = "hash_frx", version = "0.0.0")
git_override(
    module_name = "hash_frx",
    commit = "<sha>",
    remote = "https://github.com/fractalyze/hash-frx.git",
)
```

## Status

Bootstrapping. The symmetric layer is being extracted from `zorch/hash` and
extended with BLAKE3 and the Keccak family; `zorch` then consumes this repo.
Work is tracked on the [issues](https://github.com/fractalyze/hash-frx/issues).

## Development

**Python 3.11.** `frxlib` publishes cp311 wheels only, and both the hermetic
Bazel toolchain and `.python-version` pin that version.

Bazel is the build, and the whole suite is one command — the same one CI's CPU
leg runs:

```sh
bazel test //...
```

Tests are backend-agnostic and default to CPU (`.bazelrc` sets
`FRX_PLATFORMS=cpu`), so a plain run is deterministic on any machine. Run them
on the device to exercise the fusion markers — that leg is the only one that
reports a lost marker, because an unrecognized marker still produces the right
bytes:

```sh
bazel test --test_env=FRX_PLATFORMS=cuda \
    --test_env=XLA_PYTHON_CLIENT_PREALLOCATE=false //...
```

`cuda` is strict — there is no CPU fallback — so a green run really did execute
on the device. Preallocation is off because Bazel runs the test actions
concurrently against the one device, and each process would otherwise claim most
of its memory.

For interactive work outside Bazel, the same pinned toolchain in a virtualenv:

```sh
python3.11 -m venv .venv && . .venv/bin/activate
pip install -r requirements.in \
    --extra-index-url https://fractalyze.github.io/pypi/simple/
```

The extra index carries the `frx` builds and the CUDA plugin wheels, which are
too large for PyPI's per-file limit. `requirements.in` holds the pins;
regenerate the lock with `bazel run //:requirements.update` instead of editing
it by hand.

Install the git hooks with both stages named. Plain `pre-commit install` wires
only the `pre-commit` stage, which leaves the commit-message linter inactive —
formatting hooks fire while a malformed commit message sails through to CI:

```sh
pre-commit install --install-hooks --hook-type pre-commit --hook-type commit-msg
```

Commit messages follow [Conventional Commits](https://www.conventionalcommits.org):
a valid type, a lowercase summary with no trailing period, a
header of at most 80 characters, and a body on everything but `docs`. Scope is
free-form. The same linter runs in CI over the pull request title and every
commit in it.

The rest of the dev loop — backend selection, the CUDA version the GPU path
requires, running against an unreleased Fractalyze XLA, and the compile-cache
rule — is in
[`docs/reference/development.md`](docs/reference/development.md).

## Documentation

- **Task-indexed hub:** [`docs/README.md`](docs/README.md) — indexes the seams,
  constructions, and implementations by what you are trying to do, and states
  the [fusion contract](docs/README.md#the-fusion-contract) they all share.
- **Contributing with Claude Code:** [`CLAUDE.md`](CLAUDE.md) — the same map,
  plus the two rules every change must respect.

## License

Licensed under the Apache License, Version 2.0 (see [LICENSE](LICENSE)).
