Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "spec/multihash"]
path = spec/multihash
url = https://github.com/multiformats/multihash.git
[submodule "spec/multicodec"]
path = spec/multicodec
url = https://github.com/multiformats/multicodec
457 changes: 229 additions & 228 deletions multihash/constants.py

Large diffs are not rendered by default.

242 changes: 239 additions & 3 deletions multihash/funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ class Func(IntEnum):
True
"""

# Blake2 variants (sorted alphabetically)
# Standard multihash functions, sorted by name
bcrypt_pbkdf = HASH_CODES["bcrypt-pbkdf"] # 0xD00D
bittorrent_pieces_root = HASH_CODES["bittorrent-pieces-root"] # 0xB702
blake2b_8 = HASH_CODES["blake2b-8"] # 0xB201
blake2b_16 = HASH_CODES["blake2b-16"] # 0xB202
blake2b_24 = HASH_CODES["blake2b-24"] # 0xB203
Expand Down Expand Up @@ -144,22 +146,29 @@ class Func(IntEnum):
blake2s_256 = HASH_CODES["blake2s-256"] # 0xB260
blake3 = HASH_CODES["blake3"] # 0x1E
dbl_sha2_256 = HASH_CODES["dbl-sha2-256"] # 0x56
identity = HASH_CODES["id"] # 0x00
ed2k = HASH_CODES["ed2k"] # 0xED20
fr32_sha256_trunc254_padbintree = HASH_CODES["fr32-sha256-trunc254-padbintree"] # 0x1011
identity = HASH_CODES["identity"] # 0x00
keccak_224 = HASH_CODES["keccak-224"] # 0x1A
keccak_256 = HASH_CODES["keccak-256"] # 0x1B
keccak_384 = HASH_CODES["keccak-384"] # 0x1C
keccak_512 = HASH_CODES["keccak-512"] # 0x1D
kt_128 = HASH_CODES["kt-128"] # 0x1D01
kt_256 = HASH_CODES["kt-256"] # 0x1D02
md4 = HASH_CODES["md4"] # 0xD4
md5 = HASH_CODES["md5"] # 0xD5
murmur3_128 = HASH_CODES["murmur3-128"] # 0x22
murmur3_32 = HASH_CODES["murmur3-32"] # 0x23
murmur3_128 = HASH_CODES["murmur3-128"] # 0x22
poseidon_bls12_381_a2_fc1 = HASH_CODES["poseidon-bls12_381-a2-fc1"] # 0xB401
poseidon_bls12_381_a2_fc1_sc = HASH_CODES["poseidon-bls12_381-a2-fc1-sc"] # 0xB402
ripemd_128 = HASH_CODES["ripemd-128"] # 0x1052
ripemd_160 = HASH_CODES["ripemd-160"] # 0x1053
ripemd_256 = HASH_CODES["ripemd-256"] # 0x1054
ripemd_320 = HASH_CODES["ripemd-320"] # 0x1055
sha1 = HASH_CODES["sha1"] # 0x11
sha2_224 = HASH_CODES["sha2-224"] # 0x1013
sha2_256 = HASH_CODES["sha2-256"] # 0x12
sha2_256_chunked = HASH_CODES["sha2-256-chunked"] # 0xB510
sha2_256_trunc254_padded = HASH_CODES["sha2-256-trunc254-padded"] # 0x1012
sha2_384 = HASH_CODES["sha2-384"] # 0x20
sha2_512 = HASH_CODES["sha2-512"] # 0x13
Expand All @@ -171,6 +180,233 @@ class Func(IntEnum):
sha3_512 = HASH_CODES["sha3-512"] # 0x14
shake_128 = HASH_CODES["shake-128"] # 0x18
shake_256 = HASH_CODES["shake-256"] # 0x19
skein256_8 = HASH_CODES["skein256-8"] # 0xB301
skein256_16 = HASH_CODES["skein256-16"] # 0xB302
skein256_24 = HASH_CODES["skein256-24"] # 0xB303
skein256_32 = HASH_CODES["skein256-32"] # 0xB304
skein256_40 = HASH_CODES["skein256-40"] # 0xB305
skein256_48 = HASH_CODES["skein256-48"] # 0xB306
skein256_56 = HASH_CODES["skein256-56"] # 0xB307
skein256_64 = HASH_CODES["skein256-64"] # 0xB308
skein256_72 = HASH_CODES["skein256-72"] # 0xB309
skein256_80 = HASH_CODES["skein256-80"] # 0xB30A
skein256_88 = HASH_CODES["skein256-88"] # 0xB30B
skein256_96 = HASH_CODES["skein256-96"] # 0xB30C
skein256_104 = HASH_CODES["skein256-104"] # 0xB30D
skein256_112 = HASH_CODES["skein256-112"] # 0xB30E
skein256_120 = HASH_CODES["skein256-120"] # 0xB30F
skein256_128 = HASH_CODES["skein256-128"] # 0xB310
skein256_136 = HASH_CODES["skein256-136"] # 0xB311
skein256_144 = HASH_CODES["skein256-144"] # 0xB312
skein256_152 = HASH_CODES["skein256-152"] # 0xB313
skein256_160 = HASH_CODES["skein256-160"] # 0xB314
skein256_168 = HASH_CODES["skein256-168"] # 0xB315
skein256_176 = HASH_CODES["skein256-176"] # 0xB316
skein256_184 = HASH_CODES["skein256-184"] # 0xB317
skein256_192 = HASH_CODES["skein256-192"] # 0xB318
skein256_200 = HASH_CODES["skein256-200"] # 0xB319
skein256_208 = HASH_CODES["skein256-208"] # 0xB31A
skein256_216 = HASH_CODES["skein256-216"] # 0xB31B
skein256_224 = HASH_CODES["skein256-224"] # 0xB31C
skein256_232 = HASH_CODES["skein256-232"] # 0xB31D
skein256_240 = HASH_CODES["skein256-240"] # 0xB31E
skein256_248 = HASH_CODES["skein256-248"] # 0xB31F
skein256_256 = HASH_CODES["skein256-256"] # 0xB320
skein512_8 = HASH_CODES["skein512-8"] # 0xB321
skein512_16 = HASH_CODES["skein512-16"] # 0xB322
skein512_24 = HASH_CODES["skein512-24"] # 0xB323
skein512_32 = HASH_CODES["skein512-32"] # 0xB324
skein512_40 = HASH_CODES["skein512-40"] # 0xB325
skein512_48 = HASH_CODES["skein512-48"] # 0xB326
skein512_56 = HASH_CODES["skein512-56"] # 0xB327
skein512_64 = HASH_CODES["skein512-64"] # 0xB328
skein512_72 = HASH_CODES["skein512-72"] # 0xB329
skein512_80 = HASH_CODES["skein512-80"] # 0xB32A
skein512_88 = HASH_CODES["skein512-88"] # 0xB32B
skein512_96 = HASH_CODES["skein512-96"] # 0xB32C
skein512_104 = HASH_CODES["skein512-104"] # 0xB32D
skein512_112 = HASH_CODES["skein512-112"] # 0xB32E
skein512_120 = HASH_CODES["skein512-120"] # 0xB32F
skein512_128 = HASH_CODES["skein512-128"] # 0xB330
skein512_136 = HASH_CODES["skein512-136"] # 0xB331
skein512_144 = HASH_CODES["skein512-144"] # 0xB332
skein512_152 = HASH_CODES["skein512-152"] # 0xB333
skein512_160 = HASH_CODES["skein512-160"] # 0xB334
skein512_168 = HASH_CODES["skein512-168"] # 0xB335
skein512_176 = HASH_CODES["skein512-176"] # 0xB336
skein512_184 = HASH_CODES["skein512-184"] # 0xB337
skein512_192 = HASH_CODES["skein512-192"] # 0xB338
skein512_200 = HASH_CODES["skein512-200"] # 0xB339
skein512_208 = HASH_CODES["skein512-208"] # 0xB33A
skein512_216 = HASH_CODES["skein512-216"] # 0xB33B
skein512_224 = HASH_CODES["skein512-224"] # 0xB33C
skein512_232 = HASH_CODES["skein512-232"] # 0xB33D
skein512_240 = HASH_CODES["skein512-240"] # 0xB33E
skein512_248 = HASH_CODES["skein512-248"] # 0xB33F
skein512_256 = HASH_CODES["skein512-256"] # 0xB340
skein512_264 = HASH_CODES["skein512-264"] # 0xB341
skein512_272 = HASH_CODES["skein512-272"] # 0xB342
skein512_280 = HASH_CODES["skein512-280"] # 0xB343
skein512_288 = HASH_CODES["skein512-288"] # 0xB344
skein512_296 = HASH_CODES["skein512-296"] # 0xB345
skein512_304 = HASH_CODES["skein512-304"] # 0xB346
skein512_312 = HASH_CODES["skein512-312"] # 0xB347
skein512_320 = HASH_CODES["skein512-320"] # 0xB348
skein512_328 = HASH_CODES["skein512-328"] # 0xB349
skein512_336 = HASH_CODES["skein512-336"] # 0xB34A
skein512_344 = HASH_CODES["skein512-344"] # 0xB34B
skein512_352 = HASH_CODES["skein512-352"] # 0xB34C
skein512_360 = HASH_CODES["skein512-360"] # 0xB34D
skein512_368 = HASH_CODES["skein512-368"] # 0xB34E
skein512_376 = HASH_CODES["skein512-376"] # 0xB34F
skein512_384 = HASH_CODES["skein512-384"] # 0xB350
skein512_392 = HASH_CODES["skein512-392"] # 0xB351
skein512_400 = HASH_CODES["skein512-400"] # 0xB352
skein512_408 = HASH_CODES["skein512-408"] # 0xB353
skein512_416 = HASH_CODES["skein512-416"] # 0xB354
skein512_424 = HASH_CODES["skein512-424"] # 0xB355
skein512_432 = HASH_CODES["skein512-432"] # 0xB356
skein512_440 = HASH_CODES["skein512-440"] # 0xB357
skein512_448 = HASH_CODES["skein512-448"] # 0xB358
skein512_456 = HASH_CODES["skein512-456"] # 0xB359
skein512_464 = HASH_CODES["skein512-464"] # 0xB35A
skein512_472 = HASH_CODES["skein512-472"] # 0xB35B
skein512_480 = HASH_CODES["skein512-480"] # 0xB35C
skein512_488 = HASH_CODES["skein512-488"] # 0xB35D
skein512_496 = HASH_CODES["skein512-496"] # 0xB35E
skein512_504 = HASH_CODES["skein512-504"] # 0xB35F
skein512_512 = HASH_CODES["skein512-512"] # 0xB360
skein1024_8 = HASH_CODES["skein1024-8"] # 0xB361
skein1024_16 = HASH_CODES["skein1024-16"] # 0xB362
skein1024_24 = HASH_CODES["skein1024-24"] # 0xB363
skein1024_32 = HASH_CODES["skein1024-32"] # 0xB364
skein1024_40 = HASH_CODES["skein1024-40"] # 0xB365
skein1024_48 = HASH_CODES["skein1024-48"] # 0xB366
skein1024_56 = HASH_CODES["skein1024-56"] # 0xB367
skein1024_64 = HASH_CODES["skein1024-64"] # 0xB368
skein1024_72 = HASH_CODES["skein1024-72"] # 0xB369
skein1024_80 = HASH_CODES["skein1024-80"] # 0xB36A
skein1024_88 = HASH_CODES["skein1024-88"] # 0xB36B
skein1024_96 = HASH_CODES["skein1024-96"] # 0xB36C
skein1024_104 = HASH_CODES["skein1024-104"] # 0xB36D
skein1024_112 = HASH_CODES["skein1024-112"] # 0xB36E
skein1024_120 = HASH_CODES["skein1024-120"] # 0xB36F
skein1024_128 = HASH_CODES["skein1024-128"] # 0xB370
skein1024_136 = HASH_CODES["skein1024-136"] # 0xB371
skein1024_144 = HASH_CODES["skein1024-144"] # 0xB372
skein1024_152 = HASH_CODES["skein1024-152"] # 0xB373
skein1024_160 = HASH_CODES["skein1024-160"] # 0xB374
skein1024_168 = HASH_CODES["skein1024-168"] # 0xB375
skein1024_176 = HASH_CODES["skein1024-176"] # 0xB376
skein1024_184 = HASH_CODES["skein1024-184"] # 0xB377
skein1024_192 = HASH_CODES["skein1024-192"] # 0xB378
skein1024_200 = HASH_CODES["skein1024-200"] # 0xB379
skein1024_208 = HASH_CODES["skein1024-208"] # 0xB37A
skein1024_216 = HASH_CODES["skein1024-216"] # 0xB37B
skein1024_224 = HASH_CODES["skein1024-224"] # 0xB37C
skein1024_232 = HASH_CODES["skein1024-232"] # 0xB37D
skein1024_240 = HASH_CODES["skein1024-240"] # 0xB37E
skein1024_248 = HASH_CODES["skein1024-248"] # 0xB37F
skein1024_256 = HASH_CODES["skein1024-256"] # 0xB380
skein1024_264 = HASH_CODES["skein1024-264"] # 0xB381
skein1024_272 = HASH_CODES["skein1024-272"] # 0xB382
skein1024_280 = HASH_CODES["skein1024-280"] # 0xB383
skein1024_288 = HASH_CODES["skein1024-288"] # 0xB384
skein1024_296 = HASH_CODES["skein1024-296"] # 0xB385
skein1024_304 = HASH_CODES["skein1024-304"] # 0xB386
skein1024_312 = HASH_CODES["skein1024-312"] # 0xB387
skein1024_320 = HASH_CODES["skein1024-320"] # 0xB388
skein1024_328 = HASH_CODES["skein1024-328"] # 0xB389
skein1024_336 = HASH_CODES["skein1024-336"] # 0xB38A
skein1024_344 = HASH_CODES["skein1024-344"] # 0xB38B
skein1024_352 = HASH_CODES["skein1024-352"] # 0xB38C
skein1024_360 = HASH_CODES["skein1024-360"] # 0xB38D
skein1024_368 = HASH_CODES["skein1024-368"] # 0xB38E
skein1024_376 = HASH_CODES["skein1024-376"] # 0xB38F
skein1024_384 = HASH_CODES["skein1024-384"] # 0xB390
skein1024_392 = HASH_CODES["skein1024-392"] # 0xB391
skein1024_400 = HASH_CODES["skein1024-400"] # 0xB392
skein1024_408 = HASH_CODES["skein1024-408"] # 0xB393
skein1024_416 = HASH_CODES["skein1024-416"] # 0xB394
skein1024_424 = HASH_CODES["skein1024-424"] # 0xB395
skein1024_432 = HASH_CODES["skein1024-432"] # 0xB396
skein1024_440 = HASH_CODES["skein1024-440"] # 0xB397
skein1024_448 = HASH_CODES["skein1024-448"] # 0xB398
skein1024_456 = HASH_CODES["skein1024-456"] # 0xB399
skein1024_464 = HASH_CODES["skein1024-464"] # 0xB39A
skein1024_472 = HASH_CODES["skein1024-472"] # 0xB39B
skein1024_480 = HASH_CODES["skein1024-480"] # 0xB39C
skein1024_488 = HASH_CODES["skein1024-488"] # 0xB39D
skein1024_496 = HASH_CODES["skein1024-496"] # 0xB39E
skein1024_504 = HASH_CODES["skein1024-504"] # 0xB39F
skein1024_512 = HASH_CODES["skein1024-512"] # 0xB3A0
skein1024_520 = HASH_CODES["skein1024-520"] # 0xB3A1
skein1024_528 = HASH_CODES["skein1024-528"] # 0xB3A2
skein1024_536 = HASH_CODES["skein1024-536"] # 0xB3A3
skein1024_544 = HASH_CODES["skein1024-544"] # 0xB3A4
skein1024_552 = HASH_CODES["skein1024-552"] # 0xB3A5
skein1024_560 = HASH_CODES["skein1024-560"] # 0xB3A6
skein1024_568 = HASH_CODES["skein1024-568"] # 0xB3A7
skein1024_576 = HASH_CODES["skein1024-576"] # 0xB3A8
skein1024_584 = HASH_CODES["skein1024-584"] # 0xB3A9
skein1024_592 = HASH_CODES["skein1024-592"] # 0xB3AA
skein1024_600 = HASH_CODES["skein1024-600"] # 0xB3AB
skein1024_608 = HASH_CODES["skein1024-608"] # 0xB3AC
skein1024_616 = HASH_CODES["skein1024-616"] # 0xB3AD
skein1024_624 = HASH_CODES["skein1024-624"] # 0xB3AE
skein1024_632 = HASH_CODES["skein1024-632"] # 0xB3AF
skein1024_640 = HASH_CODES["skein1024-640"] # 0xB3B0
skein1024_648 = HASH_CODES["skein1024-648"] # 0xB3B1
skein1024_656 = HASH_CODES["skein1024-656"] # 0xB3B2
skein1024_664 = HASH_CODES["skein1024-664"] # 0xB3B3
skein1024_672 = HASH_CODES["skein1024-672"] # 0xB3B4
skein1024_680 = HASH_CODES["skein1024-680"] # 0xB3B5
skein1024_688 = HASH_CODES["skein1024-688"] # 0xB3B6
skein1024_696 = HASH_CODES["skein1024-696"] # 0xB3B7
skein1024_704 = HASH_CODES["skein1024-704"] # 0xB3B8
skein1024_712 = HASH_CODES["skein1024-712"] # 0xB3B9
skein1024_720 = HASH_CODES["skein1024-720"] # 0xB3BA
skein1024_728 = HASH_CODES["skein1024-728"] # 0xB3BB
skein1024_736 = HASH_CODES["skein1024-736"] # 0xB3BC
skein1024_744 = HASH_CODES["skein1024-744"] # 0xB3BD
skein1024_752 = HASH_CODES["skein1024-752"] # 0xB3BE
skein1024_760 = HASH_CODES["skein1024-760"] # 0xB3BF
skein1024_768 = HASH_CODES["skein1024-768"] # 0xB3C0
skein1024_776 = HASH_CODES["skein1024-776"] # 0xB3C1
skein1024_784 = HASH_CODES["skein1024-784"] # 0xB3C2
skein1024_792 = HASH_CODES["skein1024-792"] # 0xB3C3
skein1024_800 = HASH_CODES["skein1024-800"] # 0xB3C4
skein1024_808 = HASH_CODES["skein1024-808"] # 0xB3C5
skein1024_816 = HASH_CODES["skein1024-816"] # 0xB3C6
skein1024_824 = HASH_CODES["skein1024-824"] # 0xB3C7
skein1024_832 = HASH_CODES["skein1024-832"] # 0xB3C8
skein1024_840 = HASH_CODES["skein1024-840"] # 0xB3C9
skein1024_848 = HASH_CODES["skein1024-848"] # 0xB3CA
skein1024_856 = HASH_CODES["skein1024-856"] # 0xB3CB
skein1024_864 = HASH_CODES["skein1024-864"] # 0xB3CC
skein1024_872 = HASH_CODES["skein1024-872"] # 0xB3CD
skein1024_880 = HASH_CODES["skein1024-880"] # 0xB3CE
skein1024_888 = HASH_CODES["skein1024-888"] # 0xB3CF
skein1024_896 = HASH_CODES["skein1024-896"] # 0xB3D0
skein1024_904 = HASH_CODES["skein1024-904"] # 0xB3D1
skein1024_912 = HASH_CODES["skein1024-912"] # 0xB3D2
skein1024_920 = HASH_CODES["skein1024-920"] # 0xB3D3
skein1024_928 = HASH_CODES["skein1024-928"] # 0xB3D4
skein1024_936 = HASH_CODES["skein1024-936"] # 0xB3D5
skein1024_944 = HASH_CODES["skein1024-944"] # 0xB3D6
skein1024_952 = HASH_CODES["skein1024-952"] # 0xB3D7
skein1024_960 = HASH_CODES["skein1024-960"] # 0xB3D8
skein1024_968 = HASH_CODES["skein1024-968"] # 0xB3D9
skein1024_976 = HASH_CODES["skein1024-976"] # 0xB3DA
skein1024_984 = HASH_CODES["skein1024-984"] # 0xB3DB
skein1024_992 = HASH_CODES["skein1024-992"] # 0xB3DC
skein1024_1000 = HASH_CODES["skein1024-1000"] # 0xB3DD
skein1024_1008 = HASH_CODES["skein1024-1008"] # 0xB3DE
skein1024_1016 = HASH_CODES["skein1024-1016"] # 0xB3DF
skein1024_1024 = HASH_CODES["skein1024-1024"] # 0xB3E0
sm3_256 = HASH_CODES["sm3-256"] # 0x534D
ssz_sha2_256_bmt = HASH_CODES["ssz-sha2-256-bmt"] # 0xB502
x11 = HASH_CODES["x11"] # 0x1100


class IdentityHash:
Expand Down
1 change: 1 addition & 0 deletions newsfragments/52.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add missing multihash functions from the upstream ``multicodec`` table, including the full Skein-256/512/1024 families and KangarooTwelve, and add a spec compliance test that validates the supported hash codes against ``multicodec/table.csv``. The identity hash is now named ``identity`` (previously ``id``) to match the upstream table.
1 change: 1 addition & 0 deletions ruff.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ exclude = [
"build",
"dist",
"docs",
"spec",
"*.egg",
]

Expand Down
1 change: 1 addition & 0 deletions spec/multicodec
Submodule multicodec added at fbd77e
2 changes: 1 addition & 1 deletion tests/test_funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class FuncTestCase:

def test_values_match_constants(self):
assert Func.sha2_256 == HASH_CODES["sha2-256"]
assert Func.identity == HASH_CODES["id"]
assert Func.identity == HASH_CODES["identity"]

def test_is_int_enum(self):
assert isinstance(Func.sha2_256, int)
Expand Down
26 changes: 26 additions & 0 deletions tests/test_spec.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import csv
import os

from multihash.constants import HASH_CODES
from multihash.funcs import Func


def test_spec_table_completeness():
"""Every multihash entry in table.csv should be in HASH_CODES and Func."""
spec_path = os.path.join(os.path.dirname(__file__), "..", "spec", "multicodec", "table.csv")

with open(spec_path) as f:
reader = csv.DictReader(f, skipinitialspace=True)
for row in reader:
if row["tag"].strip() != "multihash":
continue

name = row["name"].strip()
code = int(row["code"].strip(), 16)

assert name in HASH_CODES, f"Missing hash in HASH_CODES: {name} (0x{code:x})"
assert HASH_CODES[name] == code, f"Code mismatch in HASH_CODES for {name}"

# Check if any Enum member has this value
values = [f.value for f in Func]
assert code in values, f"Missing code in Func enum for {name} (0x{code:x})"
Loading