Skip to content

Repository files navigation

poseidon

A Zig implementation of the Poseidon2 cryptographic hash function.

Supported Configurations

This implementation provides:

Finite Fields

  • BabyBear field (p = 2³¹ - 2²⁷ + 1 = 0x78000001)

    • Width: 16 elements
    • S-Box degree: 7
    • Internal rounds: 13
    • External rounds: 8
    • Use case: Ethereum Lean chain
  • KoalaBear field (p = 2³¹ - 2²⁴ + 1 = 0x7f000001)

    • Width: 16 elements
    • S-Box degree: 3
    • Internal rounds: 20
    • External rounds: 8
    • Use case: plonky3, Rust hash-sig compatibility

Features

  • Generic Montgomery form implementation for finite fields of 31 bits or less
  • Compression mode (recommended for Merkle Trees)
  • Both naive and optimized (Montgomery) implementations for verification
  • Comprehensive test suite ensuring consistency between implementations

Installation

Add zig-poseidon as a dependency in your build.zig.zon:

.dependencies= .{
.poseidon= .{
.url="https://github.com/blockblaz/zig-poseidon/archive/v0.2.0.tar.gz",
.hash="122...", // Get hash by running: zig fetch --save <url>
},
},

Get the correct hash:

zig fetch --save https://github.com/blockblaz/zig-poseidon/archive/v0.2.0.tar.gz

Latest version: See Releases for the most recent version.

Usage

Using BabyBear16

conststd=@import("std");
constbabybear16=@import("babybear16");
pubfnmain() !void {
constField=babybear16.Poseidon2BabyBear.Field;
// Prepare input state (16 field elements)varinput_state: [16]u32= .{0} **16;
input_state[0] =42;
// Convert to Montgomery formvarmont_state: [16]Field.MontFieldElem=undefined;
for (0..16) |i| {
Field.toMontgomery(&mont_state[i], input_state[i]);
}
// Apply permutationbabybear16.Poseidon2BabyBear.permutation(&mont_state);
// Convert back to normal formvaroutput_state: [16]u32=undefined;
for (0..16) |i| {
output_state[i] =Field.toNormal(mont_state[i]);
}
std.debug.print("Output: {any}\n", .{output_state});
}

Using KoalaBear16 (Rust hash-sig compatible)

conststd=@import("std");
constkoalabear16=@import("koalabear16");
pubfnmain() !void {
constField=koalabear16.Poseidon2KoalaBear.Field;
// Prepare input state (16 field elements)varinput_state: [16]u32= .{0} **16;
input_state[0] =42;
// Convert to Montgomery formvarmont_state: [16]Field.MontFieldElem=undefined;
for (0..16) |i| {
Field.toMontgomery(&mont_state[i], input_state[i]);
}
// Apply permutationkoalabear16.Poseidon2KoalaBear.permutation(&mont_state);
// Convert back to normal formvaroutput_state: [16]u32=undefined;
for (0..16) |i| {
output_state[i] =Field.toNormal(mont_state[i]);
}
std.debug.print("Output: {any}\n", .{output_state});
}

Building and Testing

# Build the library
zig build
# Run all tests (includes BabyBear and KoalaBear)
zig build test

Field Comparison

FeatureBabyBearKoalaBear
Prime2³¹ - 2²⁷ + 12³¹ - 2²⁴ + 1
Hex Value0x780000010x7f000001
Width1616
S-Box Degree73
Internal Rounds1320
External Rounds88
Compatible WithEthereum Leanplonky3, Rust hash-sig

Important: Different fields produce completely different hash outputs! Choose the field that matches your target system.

Project Motivation

This repository was created primarily to support the upcoming Ethereum Lean chain. The KoalaBear field was added to enable compatibility with Rust's hash-sig implementation and plonky3.

Compatibility

Both implementations include tests ensuring the naive and optimized (Montgomery) implementations produce identical outputs.

Future Enhancements

  • Add support for more finite fields
  • Add support for the sponge construction
  • Add benchmarks and performance optimizations
  • Add more S-Box degrees as needed

Versioning and Releases

This project follows Semantic Versioning.

Current version:0.2.0

Release Process

Releases are automatically created when Pull Requests from main are merged to the release branch:

  1. Develop and merge features to main branch
  2. When ready to release, update the VERSION file on main
  3. Create a PR from main to release branch
  4. After merge to release, the workflow automatically:
    • Creates a Git tag (e.g., v0.2.0)
    • Generates a changelog
    • Creates a GitHub Release
    • Calculates the tarball hash for dependencies

Why a release branch?

  • ✅ Control when releases happen
  • ✅ Not every feature triggers a release
  • ✅ Batch multiple features into one release

See RELEASING.md for detailed release instructions.

Using Specific Versions

Always pin to a specific version in your build.zig.zon:

.poseidon= .{
.url="https://github.com/blockblaz/zig-poseidon/archive/v0.2.0.tar.gz",
.hash="122...", // specific hash for v0.2.0
},

Find releases:GitHub Releases

License

MIT

References

About

A Zig implementation of Poseidon2 hash function.

Topics

Resources

Stars

19 stars

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages