#!/usr/bin/env python3 # no idea if this still works (though I guess it should?) # maybe something here somebody can learn from # the 2023 goal was to learn how CIDs are generated, the 2025 goal is add my first tangled string import hashlib, base64, cbor2 from base64 import b32encode from dataclasses import dataclass from typing import Any DAG_CBOR_CID_TAG = 42 @dataclass class Link: cid: bytes def encode_cbor(val: Any) -> bytes: def dag_cbor_encoder(encoder, value): if isinstance(value, Link): return encoder.encode(cbor2.CBORTag(DAG_CBOR_CID_TAG, value.cid)) return cbor2.dumps(val, default=dag_cbor_encoder, canonical=True) def hash_obj(val: bytes) -> bytes: return hashlib.sha256(val).digest() def encode_b32(digest: bytes) -> str: return 'b' + b32encode(b'\x01\x71\x12\x20' + digest).decode().lower().rstrip('=') def encode_cid(val: dict) -> Link: digest = hash_obj(encode_cbor(val)) return Link(cid=b'\x00\x01\x71\x12\x20' + digest) record1 = { 'k': b'app.bsky.feed.post/3keyfhciqrr2j', 'p': 0, 'v': encode_cid({'text': 'hello world', '$type': 'app.bsky.feed.post', 'langs': ['en'], 'createdAt': '2023-11-25T04:53:44.772Z'}), 't': None, } record2 = { 'k': b'graph.follow/3keyfhsnwm72p', 'p': 9, 'v': encode_cid({'$type': 'app.bsky.graph.follow', 'subject': 'did:plc:4nsduwlpivpuur4mqkbfvm6a', 'createdAt': '2023-11-25T04:54:01.723Z'}), 't': None, } tree = { 'l': None, 'e': [record1, record2], } tree_cbor = encode_cbor(tree) tree_digest = hash_obj(tree_cbor) assert encode_b32(tree_digest) == 'bafyreif5wigbpxdo6kli4lltcrv47wndp23sknhulnoepe6vhze432oqoe'