Skip to content
Merged
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
258 changes: 3 additions & 255 deletions multicodec/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from __future__ import annotations

from .constants import CODE_TABLE, CODECS, NAME_TABLE
from .constants import CODE_TABLE, CODECS, NAME_TABLE, TAG_TABLE

# ReservedStart is the (inclusive) start of the reserved range of codes that
# are safe to use for internal purposes.
Expand Down Expand Up @@ -188,260 +188,8 @@ def tag(self) -> str:


def _get_tag(code: int) -> str:
"""Get the tag for a codec code (mirrors go-multicodec's Tag() method)."""
name = CODE_TABLE.get(code, "")

# CID
if name in ("cidv1", "cidv2", "cidv3"):
return "cid"

# Encryption
if name in ("aes-gcm-256",):
return "encryption"

# Filecoin
if name in ("fil-commitment-unsealed", "fil-commitment-sealed"):
return "filecoin"

# Hash (non-multihash)
if name in (
"murmur3-x64-64",
"murmur3-32",
"murmur3-128",
"crc32",
"crc64-ecma",
"crc64-nvme",
"murmur3-x64-128",
"sha256a",
"xxh-32",
"xxh-64",
"xxh3-64",
"xxh3-128",
):
return "hash"

# Holochain
if "holochain" in name:
return "holochain"

# IPLD
if name in (
"cbor",
"raw",
"dag-pb",
"dag-cbor",
"libp2p-key",
"git-raw",
"torrent-info",
"torrent-file",
"blake3-hashseq",
"leofcoin-block",
"leofcoin-tx",
"leofcoin-pr",
"dag-jose",
"dag-cose",
"eth-block",
"eth-block-list",
"eth-tx-trie",
"eth-tx",
"eth-tx-receipt-trie",
"eth-tx-receipt",
"eth-state-trie",
"eth-account-snapshot",
"eth-storage-trie",
"eth-receipt-log-trie",
"eth-receipt-log",
"bitcoin-block",
"bitcoin-tx",
"bitcoin-witness-commitment",
"zcash-block",
"zcash-tx",
"stellar-block",
"stellar-tx",
"decred-block",
"decred-tx",
"dash-block",
"dash-tx",
"swarm-manifest",
"swarm-feed",
"beeson",
"dag-json",
"swhid-1-snp",
"json",
"rdfc-1",
"json-jcs",
):
return "ipld"

# Key
if any(
k in name
for k in (
"-pub",
"-priv",
"secp256k1",
"bls12_381",
"x25519",
"ed25519",
"p256",
"p384",
"p521",
"ed448",
"x448",
"sr25519",
"rsa",
"sm2",
"mlkem",
"jwk",
)
):
return "key"

# Libp2p
if name in ("libp2p-peer-record", "libp2p-relay-rsvp"):
return "libp2p"

# Multiaddr
if name in (
"ip4",
"tcp",
"dccp",
"ip6",
"ip6zone",
"ipcidr",
"dns",
"dns4",
"dns6",
"dnsaddr",
"sctp",
"udp",
"p2p-webrtc-star",
"p2p-webrtc-direct",
"p2p-stardust",
"p2p-circuit",
"udt",
"utp",
"unix",
"thread",
"p2p",
"https",
"onion",
"onion3",
"garlic64",
"garlic32",
"tls",
"sni",
"noise",
"shs",
"quic",
"quic-v1",
"webtransport",
"certhash",
"ws",
"wss",
"p2p-websocket-star",
"http",
"http-path",
"webrtc-direct",
"webrtc",
"plaintextv2",
"scion",
"memory",
):
return "multiaddr"

# Multiformat
if name in ("multicodec", "multihash", "multiaddr", "multibase", "varsig"):
return "multiformat"

# Multihash
if any(
h in name
for h in (
"identity",
"sha1",
"sha2-",
"sha3-",
"shake-",
"keccak-",
"blake2b-",
"blake2s-",
"blake3",
"dbl-sha2-",
"md4",
"md5",
"bmt",
"ripemd-",
"x11",
"kangarootwelve",
"sm3-",
"poseidon-",
"skein",
)
):
return "multihash"

# Namespace
if name in (
"path",
"lbry",
"streamid",
"ipld-ns",
"ipfs-ns",
"swarm-ns",
"ipns-ns",
"zeronet",
"dnslink",
"skynet-ns",
"arweave-ns",
"subspace-ns",
"kumandra-ns",
):
return "namespace"

# Serialization
if name in (
"protobuf",
"rlp",
"bencode",
"messagepack",
"car",
"car-index-sorted",
"car-multihash-index-sorted",
"ipns-record",
"x509-certificate",
"ssz",
):
return "serialization"

# Transport
if name in (
"transport-bitswap",
"transport-graphsync-filecoinv1",
"transport-ipfs-gateway-http",
):
return "transport"

# Varsig
if name in (
"nonstandard-sig",
"es256k",
"bls12_381-g1-sig",
"bls12_381-g2-sig",
"eddsa",
"eip-191",
"es256",
"es384",
"es512",
"rs256",
):
return "varsig"

# Zeroxcert
if name in ("zeroxcert-imprint-256",):
return "zeroxcert"

return "<unknown>"
"""Get the tag for a codec code from the generated TAG_TABLE."""
return TAG_TABLE.get(code, "<unknown>")


# Cache for known codes list
Expand Down
1 change: 1 addition & 0 deletions multicodec/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -3938,3 +3938,4 @@

NAME_TABLE: dict[str, int] = {name: cast(int, value["prefix"]) for name, value in CODECS.items()}
CODE_TABLE: dict[int, str] = {cast(int, value["prefix"]): name for name, value in CODECS.items()}
TAG_TABLE: dict[int, str] = {cast(int, value["prefix"]): cast(str, value["tag"]) for name, value in CODECS.items()}
1 change: 1 addition & 0 deletions newsfragments/37.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Return the correct ``multikey``, ``multisig``, ``nonce``, ``shelter``, ``softhash``, and ``vlad`` tags from ``Code.tag()``.
1 change: 1 addition & 0 deletions newsfragments/40.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Derive ``Code.tag()`` from the multicodec table so every codec returns its CSV tag.
1 change: 1 addition & 0 deletions newsfragments/42.misc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add tests verifying ``Code.tag()`` matches the multicodec table for every registered codec.
19 changes: 19 additions & 0 deletions tests/test_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,25 @@ def test_code_tag(self):
code = Code(0x55) # raw
assert code.tag() == "ipld"

# Previously missing categories (issue #37)
assert Code(0xA000).tag() == "multikey" # chacha20-poly1305
assert Code(0xD01300).tag() == "multisig" # es256k-msig
assert Code(0xD01301).tag() == "multisig" # bls12_381-g1-msig
assert Code(0x123B).tag() == "nonce"
assert Code(0x511E00).tag() == "shelter" # shelter-contract-manifest
assert Code(0xCC01).tag() == "softhash" # iscc
assert Code(0x1207).tag() == "vlad"

# Unknown code
assert Code(0x999999).tag() == "<unknown>"

def test_code_tag_matches_codecs_for_all(self):
"""Every registered codec's tag() matches CODECS metadata (issue #42)."""
from multicodec.constants import CODECS

for name, info in CODECS.items():
assert Code(info["prefix"]).tag() == info["tag"], name

def test_code_status(self):
"""Test Code.status property."""
# Permanent codec
Expand Down
9 changes: 8 additions & 1 deletion tests/test_constants_metadata.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Smoke tests for enriched CODECS metadata from update-table.py."""

from multicodec.constants import CODE_TABLE, CODECS, NAME_TABLE
from multicodec.constants import CODE_TABLE, CODECS, NAME_TABLE, TAG_TABLE


def test_codecs_include_csv_metadata_keys():
Expand All @@ -22,3 +22,10 @@ def test_identity_preserves_description():
def test_name_and_code_tables_still_use_prefix():
assert NAME_TABLE["sha2-256"] == 0x12
assert CODE_TABLE[0x12] == "sha2-256"


def test_tag_table_matches_codecs():
assert TAG_TABLE[0x12] == "multihash"
assert len(TAG_TABLE) == len(CODECS)
for name, info in CODECS.items():
assert TAG_TABLE[info["prefix"]] == info["tag"], name
3 changes: 3 additions & 0 deletions tools/update-table.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
CODE_TABLE: dict[int, str] = {
cast(int, value["prefix"]): name for name, value in CODECS.items()
}
TAG_TABLE: dict[int, str] = {
cast(int, value["prefix"]): cast(str, value["tag"]) for name, value in CODECS.items()
}
"""


Expand Down
Loading