Skip to content

test: cross-check RPO test vectors with Python reference implementation#822

Merged
bobbinth merged 2 commits into0xMiden:nextfrom
Farukest:feat/verify-rpo-test-vectors-768
Feb 14, 2026
Merged

test: cross-check RPO test vectors with Python reference implementation#822
bobbinth merged 2 commits into0xMiden:nextfrom
Farukest:feat/verify-rpo-test-vectors-768

Conversation

@Farukest
Copy link
Contributor

Summary

After the state layout change in #755 ([CAPACITY, RATE0, RATE1][RATE0, RATE1, CAPACITY]), the RPO test vectors were updated but not verified against the reference implementation.

This PR adds a Python verification script adapted from the original RPO reference that uses the current state layout and confirms all 19 test vectors match the Rust implementation.

  • Add generate_test_vectors.py implementing RPO hash with the current layout
  • All 19 vectors verified: python3 generate_test_vectors.py → all OK
  • Add doc comment on EXPECTED noting the cross-check

Closes #768

Test plan

  • python3 generate_test_vectors.py — 19/19 vectors match
  • cargo test -p miden-crypto hash_test_vectors — passes
  • cargo +nightly fmt --check
  • cargo clippy -p miden-crypto
  • cargo doc -p miden-crypto --no-deps

Copy link
Collaborator

@Al-Kindi-0 Al-Kindi-0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to double, check the .py implementation is exactly the reference one, except for the state re-mapping, right?
Otherwise looks great to me, thank you@

@Farukest
Copy link
Contributor Author

Just to double, check the .py implementation is exactly the reference one, except for the state re-mapping, right? Otherwise looks great to me, thank you@

Not exactly
The permutation itself (MDS, sbox, inv_sbox, round constants, round structure) is identical to the reference. But the hash function wrapper has two additional differences beyond the state re-mapping:

  1. Domain separation uses len % rate (as in our Rust code) instead of the reference's binary 0/1 flag
  2. Padding uses only zeros instead of the reference's [1, 0, ...]

Both of these match our Rust implementation which follows the padding rule from the 2023/1045 paper rather than the original reference. The 19 test vectors confirm it's consistent with our Rust code

@Al-Kindi-0
Copy link
Collaborator

Just to double, check the .py implementation is exactly the reference one, except for the state re-mapping, right? Otherwise looks great to me, thank you@

Not exactly The permutation itself (MDS, sbox, inv_sbox, round constants, round structure) is identical to the reference. But the hash function wrapper has two additional differences beyond the state re-mapping:

1. Domain separation uses `len % rate` (as in our Rust code) instead of the reference's binary 0/1 flag

2. Padding uses only zeros instead of the reference's `[1, 0, ...]`

Both of these match our Rust implementation which follows the padding rule from the 2023/1045 paper rather than the original reference. The 19 test vectors confirm it's consistent with our Rust code

Thank you! Indeed, the padding rule has changed from the one that was used in the RPO paper.

@Farukest Farukest force-pushed the feat/verify-rpo-test-vectors-768 branch from b92422c to a4b28a6 Compare February 11, 2026 13:17
Add a Python script that implements the RPO hash function with the
current state layout [RATE0, RATE1, CAPACITY] and verifies all 19
test vectors match the Rust implementation. This addresses the concern
raised in issue 0xMiden#768 that test vectors were not cross-checked with the
reference implementation after the state layout change in PR 0xMiden#755.

Closes 0xMiden#768
@Farukest Farukest force-pushed the feat/verify-rpo-test-vectors-768 branch from a4b28a6 to 0bf6ccb Compare February 14, 2026 05:58
@@ -0,0 +1,288 @@
#!/usr/bin/env python3
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a nice verification script. Since the Python script isn't part of CI, a future change to RPO could break consistency without detection. Would be worth considering either adding this to CI or generating test vectors from Python as the source of truth.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't spend effort on this right now as with v0.21 VM, we no longer use RPO/RPX and we may be dropping RPO/RPX from this repo in the near future.

Copy link
Contributor

@bobbinth bobbinth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Thank you.

This was a fairly low priority issue as RPO/RPX may be dropped from this repo soon. But since the work has already been done, I'll merge it.

@@ -0,0 +1,288 @@
#!/usr/bin/env python3
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't spend effort on this right now as with v0.21 VM, we no longer use RPO/RPX and we may be dropping RPO/RPX from this repo in the near future.

@bobbinth bobbinth merged commit ed3c13c into 0xMiden:next Feb 14, 2026
22 checks passed
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.

Generate the expected hash outputs of RPO using reference implementation

4 participants