diff --git a/src/lean_spec/subspecs/poseidon2/constants.py b/src/lean_spec/subspecs/poseidon2/constants.py new file mode 100644 index 00000000..462bfed0 --- /dev/null +++ b/src/lean_spec/subspecs/poseidon2/constants.py @@ -0,0 +1,380 @@ +"""Round constants for the Poseidon2 permutation over the KoalaBear field.""" + +from typing import List + +from ..koalabear.field import Fp + +_RAW_CONSTANTS_16: List[int] = [ + 2128964168, + 288780357, + 316938561, + 2126233899, + 426817493, + 1714118888, + 1045008582, + 1738510837, + 889721787, + 8866516, + 681576474, + 419059826, + 1596305521, + 1583176088, + 1584387047, + 1529751136, + 1863858111, + 1072044075, + 517831365, + 1464274176, + 1138001621, + 428001039, + 245709561, + 1641420379, + 1365482496, + 770454828, + 693167409, + 757905735, + 136670447, + 436275702, + 525466355, + 1559174242, + 1030087950, + 869864998, + 322787870, + 267688717, + 948964561, + 740478015, + 679816114, + 113662466, + 2066544572, + 1744924186, + 367094720, + 1380455578, + 1842483872, + 416711434, + 1342291586, + 1692058446, + 1493348999, + 1113949088, + 210900530, + 1071655077, + 610242121, + 1136339326, + 2020858841, + 1019840479, + 678147278, + 1678413261, + 1361743414, + 61132629, + 1209546658, + 64412292, + 1936878279, + 1980661727, + 1423960925, + 2101391318, + 1915532054, + 275400051, + 1168624859, + 1141248885, + 356546469, + 1165250474, + 1320543726, + 932505663, + 1204226364, + 1452576828, + 1774936729, + 926808140, + 1184948056, + 1186493834, + 843181003, + 185193011, + 452207447, + 510054082, + 1139268644, + 630873441, + 669538875, + 462500858, + 876500520, + 1214043330, + 383937013, + 375087302, + 636912601, + 307200505, + 390279673, + 1999916485, + 1518476730, + 1606686591, + 1410677749, + 1581191572, + 1004269969, + 143426723, + 1747283099, + 1016118214, + 1749423722, + 66331533, + 1177761275, + 1581069649, + 1851371119, + 852520128, + 1499632627, + 1820847538, + 150757557, + 884787840, + 619710451, + 1651711087, + 505263814, + 212076987, + 1482432120, + 1458130652, + 382871348, + 417404007, + 2066495280, + 1996518884, + 902934924, + 582892981, + 1337064375, + 1199354861, + 2102596038, + 1533193853, + 1436311464, + 2012303432, + 839997195, + 1225781098, + 2011967775, + 575084315, + 1309329169, + 786393545, + 995788880, + 1702925345, + 1444525226, + 908073383, + 1811535085, + 1531002367, + 1635653662, + 1585100155, + 867006515, + 879151050, +] + +_RAW_CONSTANTS_24: List[int] = [ + 487143900, + 1829048205, + 1652578477, + 646002781, + 1044144830, + 53279448, + 1519499836, + 22697702, + 1768655004, + 230479744, + 1484895689, + 705130286, + 1429811285, + 1695785093, + 1417332623, + 1115801016, + 1048199020, + 878062617, + 738518649, + 249004596, + 1601837737, + 24601614, + 245692625, + 364803730, + 1857019234, + 1906668230, + 1916890890, + 835590867, + 557228239, + 352829675, + 515301498, + 973918075, + 954515249, + 1142063750, + 1795549558, + 608869266, + 1850421928, + 2028872854, + 1197543771, + 1027240055, + 1976813168, + 963257461, + 652017844, + 2113212249, + 213459679, + 90747280, + 1540619478, + 324138382, + 1377377119, + 294744504, + 512472871, + 668081958, + 907306515, + 518526882, + 1907091534, + 1152942192, + 1572881424, + 720020214, + 729527057, + 1762035789, + 86171731, + 205890068, + 453077400, + 1201344594, + 986483134, + 125174298, + 2050269685, + 1895332113, + 749706654, + 40566555, + 742540942, + 1735551813, + 162985276, + 1943496073, + 1469312688, + 703013107, + 1979485151, + 1278193166, + 548674995, + 2118718736, + 749596440, + 1476142294, + 1293606474, + 918523452, + 890353212, + 1691895663, + 1932240646, + 1180911992, + 86098300, + 1592168978, + 895077289, + 724819849, + 1697986774, + 1608418116, + 1083269213, + 691256798, + 328586442, + 1572520009, + 1375479591, + 322991001, + 967600467, + 1172861548, + 1973891356, + 1503625929, + 1881993531, + 40601941, + 1155570620, + 571547775, + 1361622243, + 1495024047, + 1733254248, + 964808915, + 763558040, + 1887228519, + 994888261, + 718330940, + 213359415, + 603124968, + 1038411577, + 2099454809, + 949846777, + 630926956, + 1168723439, + 222917504, + 1527025973, + 1009157017, + 2029957881, + 805977836, + 1347511739, + 540019059, + 589807745, + 440771316, + 1530063406, + 761076336, + 87974206, + 1412686751, + 1230318064, + 514464425, + 1469011754, + 1770970737, + 1510972858, + 965357206, + 209398053, + 778802532, + 40567006, + 1984217577, + 1545851069, + 879801839, + 1611910970, + 1215591048, + 330802499, + 1051639108, + 321036, + 511927202, + 591603098, + 1775897642, + 115598532, + 278200718, + 233743176, + 525096211, + 1335507608, + 830017835, + 1380629279, + 560028578, + 598425701, + 302162385, + 567434115, + 1859222575, + 958294793, + 1582225556, + 1781487858, + 1570246000, + 1067748446, + 526608119, + 1666453343, + 1786918381, + 348203640, + 1860035017, + 1489902626, + 1904576699, + 860033965, + 1954077639, + 1685771567, + 971513929, + 1877873770, + 137113380, + 520695829, + 806829080, + 1408699405, + 1613277964, + 793223662, + 648443918, + 893435011, + 403879071, + 1363789863, + 1662900517, + 2043370, + 2109755796, + 931751726, + 2091644718, + 606977583, + 185050397, + 946157136, + 1350065230, + 1625860064, + 122045240, + 880989921, + 145137438, + 1059782436, + 1477755661, + 335465138, + 1640704282, + 1757946479, + 1551204074, + 681266718, +] + +# For width 16 (needs 8*16 + 20 = 148 constants). +ROUND_CONSTANTS_16: List[Fp] = [Fp(value=v) for v in _RAW_CONSTANTS_16] + +# For width 24 (needs 8*24 + 23 = 215 constants). +ROUND_CONSTANTS_24: List[Fp] = [Fp(value=v) for v in _RAW_CONSTANTS_24] diff --git a/src/lean_spec/subspecs/poseidon2/permutation.py b/src/lean_spec/subspecs/poseidon2/permutation.py index 188e28c2..d8488fac 100644 --- a/src/lean_spec/subspecs/poseidon2/permutation.py +++ b/src/lean_spec/subspecs/poseidon2/permutation.py @@ -13,6 +13,10 @@ from pydantic import BaseModel, ConfigDict, Field, model_validator from ..koalabear.field import Fp +from .constants import ( + ROUND_CONSTANTS_16, + ROUND_CONSTANTS_24, +) # ================================================================= # Poseidon2 Parameter Definitions @@ -29,19 +33,9 @@ class Poseidon2Params(BaseModel): - """ - Encapsulates all necessary parameters for a specific Poseidon2 instance. + """Parameters for a specific Poseidon2 instance.""" - This structure holds the configuration for a given state width, including - the number of rounds and the constants for the internal linear layer. - """ - - # Configuration to make the model immutable and prevent extra arguments. - model_config = ConfigDict( - frozen=True, - extra="forbid", - arbitrary_types_allowed=True, - ) + model_config = ConfigDict(frozen=True, arbitrary_types_allowed=True) width: int = Field(gt=0, description="The size of the state (t).") rounds_f: int = Field(gt=0, description="Total number of 'full' rounds.") @@ -55,41 +49,24 @@ class Poseidon2Params(BaseModel): "internal linear layer matrix (M_I)." ), ) + round_constants: List[Fp] = Field( + min_length=1, + description="The list of pre-computed constants for all rounds.", + ) @model_validator(mode="after") - def check_vector_length(self) -> "Poseidon2Params": - """Length of the diagonal vector should match the state width.""" + def check_lengths(self) -> "Poseidon2Params": + """Ensures vector lengths match the configuration.""" if len(self.internal_diag_vectors) != self.width: raise ValueError( - f"Length of internal diagonal vector " - "({len(self.internal_diag_vectors)}) " - f"must be equal to width ({self.width})." + "Length of internal_diag_vectors must equal width." ) - return self - -def _generate_spec_test_round_constants(params: Poseidon2Params) -> List[Fp]: - """ - Generates a deterministic list of round constants for testing the spec. - - !!! WARNING !!! - This function produces a simple, predictable sequence of integers for the - sole purpose of testing the permutation's algebraic structure. Production - implementations MUST use constants generated from a secure, - unpredictable source. - - Args: - params: The object defining the permutation's configuration. + expected_constants = (self.rounds_f * self.width) + self.rounds_p + if len(self.round_constants) != expected_constants: + raise ValueError("Incorrect number of round constants provided.") - Returns: - A list of Fp elements to be used as round constants for tests. - """ - # The total number of constants needed for the entire permutation. - total_constants = (params.rounds_f * params.width) + params.rounds_p - - # For the specification, we generate the constants as a deterministic - # sequence of integers. This is sufficient to define the mechanics. - return [Fp(value=i) for i in range(total_constants)] + return self # Parameters for WIDTH = 16 @@ -115,6 +92,7 @@ def _generate_spec_test_round_constants(params: Poseidon2Params) -> List[Fp]: Fp(value=-1) / Fp(value=16), Fp(value=-1) / Fp(value=2**24), ], + round_constants=ROUND_CONSTANTS_16, ) # Parameters for WIDTH = 24 @@ -148,6 +126,7 @@ def _generate_spec_test_round_constants(params: Poseidon2Params) -> List[Fp]: Fp(value=-1) / Fp(value=2**9), Fp(value=-1) / Fp(value=2**24), ], + round_constants=ROUND_CONSTANTS_24, ) # Base 4x4 matrix, used in the external linear layer. @@ -287,7 +266,7 @@ def permute(state: List[Fp], params: Poseidon2Params) -> List[Fp]: raise ValueError(f"Input state must have length {params.width}") # Generate the deterministic round constants for this parameter set. - round_constants = _generate_spec_test_round_constants(params) + round_constants = params.round_constants # The number of full rounds is split between the beginning and end. half_rounds_f = params.rounds_f // 2 # Initialize index for accessing the flat list of round constants. diff --git a/tests/lean_spec/subspecs/poseidon2/test_permutation.py b/tests/lean_spec/subspecs/poseidon2/test_permutation.py index 4dc539a1..b81f6d92 100644 --- a/tests/lean_spec/subspecs/poseidon2/test_permutation.py +++ b/tests/lean_spec/subspecs/poseidon2/test_permutation.py @@ -37,22 +37,22 @@ ] # Expected output for width 16. EXPECTED_16 = [ - Fp(value=675842289), - Fp(value=66192714), - Fp(value=579861851), - Fp(value=1465025982), - Fp(value=810227449), - Fp(value=1161478289), - Fp(value=1411410716), - Fp(value=1917188212), - Fp(value=80707562), - Fp(value=1051450322), - Fp(value=1441355554), - Fp(value=1096596517), - Fp(value=1967136522), - Fp(value=1656393635), - Fp(value=1897269296), - Fp(value=218235760), + Fp(value=1934285469), + Fp(value=604889435), + Fp(value=133449501), + Fp(value=1026180808), + Fp(value=1830659359), + Fp(value=176667110), + Fp(value=1391183747), + Fp(value=351743874), + Fp(value=1238264085), + Fp(value=1292768839), + Fp(value=2023573270), + Fp(value=1201586780), + Fp(value=1360691759), + Fp(value=1230682461), + Fp(value=748270449), + Fp(value=651545025), ] # Input vector for width 24 @@ -84,30 +84,30 @@ ] # Expected output for width 24. EXPECTED_24 = [ - Fp(value=545335348), - Fp(value=483654611), - Fp(value=76149348), - Fp(value=1039423716), - Fp(value=273226798), - Fp(value=1112250891), - Fp(value=1803002062), - Fp(value=283727456), - Fp(value=1270538134), - Fp(value=740691354), - Fp(value=824972956), - Fp(value=1586235276), - Fp(value=1576922813), - Fp(value=300527652), - Fp(value=1319772393), - Fp(value=1464054027), - Fp(value=624250646), - Fp(value=2110444609), - Fp(value=213054218), - Fp(value=830776390), - Fp(value=257630621), - Fp(value=1575823798), - Fp(value=546963080), - Fp(value=850531490), + Fp(value=382801106), + Fp(value=82839311), + Fp(value=1503190615), + Fp(value=1987418517), + Fp(value=854076995), + Fp(value=1862291425), + Fp(value=262755189), + Fp(value=1050814217), + Fp(value=722724562), + Fp(value=741265943), + Fp(value=1026879332), + Fp(value=754316749), + Fp(value=1966025564), + Fp(value=1518878196), + Fp(value=502200188), + Fp(value=1368172258), + Fp(value=845459257), + Fp(value=1711434837), + Fp(value=724453836), + Fp(value=171032289), + Fp(value=655223446), + Fp(value=1098636135), + Fp(value=407832555), + Fp(value=1707498914), ]