From fe13692268f67eb03f6f2b7ec7c7f83c1c2e8283 Mon Sep 17 00:00:00 2001 From: Danny Willems Date: Tue, 2 Sep 2025 17:40:29 +0200 Subject: [PATCH 1/2] poseidon: make Item public with nbits and as_bigint This will be used for testing --- poseidon/src/hash.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poseidon/src/hash.rs b/poseidon/src/hash.rs index 1f08ac5dd0..00d005a024 100644 --- a/poseidon/src/hash.rs +++ b/poseidon/src/hash.rs @@ -3,7 +3,7 @@ use mina_curves::pasta::Fp; use crate::{PlonkSpongeConstantsKimchi, Sponge, SpongeParamsForField}; -enum Item { +pub enum Item { Bool(bool), U2(u8), U8(u8), @@ -26,7 +26,7 @@ impl std::fmt::Debug for Item { } impl Item { - fn nbits(&self) -> u32 { + pub fn nbits(&self) -> u32 { match self { Item::Bool(_) => 1, Item::U2(_) => 2, @@ -37,7 +37,7 @@ impl Item { } } - fn as_bigint(&self) -> u64 { + pub fn as_bigint(&self) -> u64 { match self { Item::Bool(v) => *v as u64, Item::U2(v) => *v as u64, From c7f5fa1e905f70213200e5dd1fee77c2736f4408 Mon Sep 17 00:00:00 2001 From: Danny Willems Date: Tue, 2 Sep 2025 17:41:29 +0200 Subject: [PATCH 2/2] poseidon: implement unit tests for test_item_as_bigint --- poseidon/tests/test_item_as_bigint.rs | 142 ++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 poseidon/tests/test_item_as_bigint.rs diff --git a/poseidon/tests/test_item_as_bigint.rs b/poseidon/tests/test_item_as_bigint.rs new file mode 100644 index 0000000000..688ab353eb --- /dev/null +++ b/poseidon/tests/test_item_as_bigint.rs @@ -0,0 +1,142 @@ +use poseidon::hash::Item; + +#[test] +fn test_item_bool_as_bigint() { + let item_true = Item::Bool(true); + let item_false = Item::Bool(false); + + assert_eq!(item_true.as_bigint(), 1); + assert_eq!(item_false.as_bigint(), 0); +} + +#[test] +fn test_item_u2_as_bigint() { + let item_0 = Item::U2(0); + let item_1 = Item::U2(1); + let item_2 = Item::U2(2); + let item_3 = Item::U2(3); + + assert_eq!(item_0.as_bigint(), 0); + assert_eq!(item_1.as_bigint(), 1); + assert_eq!(item_2.as_bigint(), 2); + assert_eq!(item_3.as_bigint(), 3); +} + +#[test] +fn test_item_u8_as_bigint() { + let item_0 = Item::U8(0); + let item_max = Item::U8(u8::MAX); + let item_mid = Item::U8(128); + + assert_eq!(item_0.as_bigint(), 0); + assert_eq!(item_max.as_bigint(), 255); + assert_eq!(item_mid.as_bigint(), 128); +} + +#[test] +fn test_item_u32_as_bigint() { + let item_0 = Item::U32(0); + let item_max = Item::U32(u32::MAX); + let item_mid = Item::U32(0x80000000); + + assert_eq!(item_0.as_bigint(), 0); + assert_eq!(item_max.as_bigint(), u32::MAX as u64); + assert_eq!(item_mid.as_bigint(), 0x80000000); +} + +#[test] +fn test_item_u64_as_bigint() { + let item_0 = Item::U64(0); + let item_max = Item::U64(u64::MAX); + let item_mid = Item::U64(0x8000000000000000); + + assert_eq!(item_0.as_bigint(), 0); + assert_eq!(item_max.as_bigint(), u64::MAX); + assert_eq!(item_mid.as_bigint(), 0x8000000000000000); +} + +#[test] +fn test_item_u48_as_bigint() { + // Test with all zeros + let item_zeros = Item::U48([0, 0, 0, 0, 0, 0]); + assert_eq!(item_zeros.as_bigint(), 0); + + // Test with all ones (max 48-bit value) + let item_max = Item::U48([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]); + // 48 bits all set = 0xFFFFFFFFFFFF + assert_eq!(item_max.as_bigint(), 0xFFFFFFFFFFFF); + + // Test with specific pattern - little-endian bytes + let item_pattern = Item::U48([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]); + // In big-endian format: 0x060504030201 + assert_eq!(item_pattern.as_bigint(), 0x060504030201); + + // Test with high byte set + let item_high = Item::U48([0x00, 0x00, 0x00, 0x00, 0x00, 0x80]); + assert_eq!(item_high.as_bigint(), 0x800000000000); +} + +#[test] +fn test_item_u48_edge_cases() { + // Test powers of 2 + let item_1 = Item::U48([0x01, 0x00, 0x00, 0x00, 0x00, 0x00]); + assert_eq!(item_1.as_bigint(), 1); + + let item_256 = Item::U48([0x00, 0x01, 0x00, 0x00, 0x00, 0x00]); + assert_eq!(item_256.as_bigint(), 0x0100); + + let item_65536 = Item::U48([0x00, 0x00, 0x01, 0x00, 0x00, 0x00]); + assert_eq!(item_65536.as_bigint(), 0x010000); + + // Test byte boundary values + let item_boundary = Item::U48([0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00]); + assert_eq!(item_boundary.as_bigint(), 0x00FF00FF00FF); +} + +#[test] +fn test_item_nbits() { + assert_eq!(Item::Bool(true).nbits(), 1); + assert_eq!(Item::Bool(false).nbits(), 1); + + assert_eq!(Item::U2(0).nbits(), 2); + assert_eq!(Item::U2(3).nbits(), 2); + + assert_eq!(Item::U8(0).nbits(), 8); + assert_eq!(Item::U8(255).nbits(), 8); + + assert_eq!(Item::U32(0).nbits(), 32); + assert_eq!(Item::U32(u32::MAX).nbits(), 32); + + assert_eq!(Item::U48([0; 6]).nbits(), 48); + assert_eq!(Item::U48([0xFF; 6]).nbits(), 48); + + assert_eq!(Item::U64(0).nbits(), 64); + assert_eq!(Item::U64(u64::MAX).nbits(), 64); +} + +#[test] +fn test_item_u48_byte_order() { + // Test that U48 uses correct byte order interpretation + // The bytes should be interpreted as: [byte0, byte1, byte2, byte3, byte4, byte5] + // And converted to big-endian u64 + + let test_cases = vec![ + ([0x01, 0x00, 0x00, 0x00, 0x00, 0x00], 0x000000000001u64), + ([0x00, 0x01, 0x00, 0x00, 0x00, 0x00], 0x000000000100u64), + ([0x00, 0x00, 0x01, 0x00, 0x00, 0x00], 0x000000010000u64), + ([0x00, 0x00, 0x00, 0x01, 0x00, 0x00], 0x000001000000u64), + ([0x00, 0x00, 0x00, 0x00, 0x01, 0x00], 0x000100000000u64), + ([0x00, 0x00, 0x00, 0x00, 0x00, 0x01], 0x010000000000u64), + ]; + + for (bytes, expected) in test_cases { + let item = Item::U48(bytes); + assert_eq!( + item.as_bigint(), + expected, + "U48({:02X?}) should equal 0x{:012X}", + bytes, + expected + ); + } +}