Skip to content
This repository was archived by the owner on Aug 12, 2026. It is now read-only.
This repository was archived by the owner on Aug 12, 2026. It is now read-only.

Proposal for CASL (Content-Addressed Storage Layout) specification #89

Description

@johnbenac

I'm already using some components from DASL in my project, and needed to shard and store some blobs, so I tried to do it the IPFS way! I'm documenting my approach, and suggesting that it be a new standard. Here is the proposed standard:

CASL defines a deterministic mapping from a CID ([[cid]]) to a sharded storage path, suitable for filesystems and object stores that need to store large numbers of content-addressed payloads. CASL standardizes only the “where does this CID live in the store?” question; it does not define chunking, DAG layouts, replication, or transport.
Introduction

Storing hundreds of thousands (or millions) of CID-addressed resources in a single directory (or under a small number of object-store prefixes) is operationally expensive and can become a performance bottleneck. CASL provides a deterministic sharding rule so that independent implementations can store and locate content-addressed payloads consistently.

The key words “MUST”, “MUST NOT”, “SHOULD”, “SHOULD NOT”, and “MAY” are to be interpreted as described in RFC 2119 ([[rfc2119]]).

CASL is intentionally narrow in scope. It does not define block chunking, Merkle DAG layout, or retrieval/replication behavior. CASL is only about mapping a CID to a storage path.
Terminology

Storage root
An implementation-defined directory or object-store prefix under which CASL paths are constructed.
CASL key
A deterministic string derived from the CID’s multihash bytes. It is used for sharding and for the leaf name by default.
Shard
A short string used as a directory (or prefix) component to distribute objects across buckets.

Deriving a CASL Key

CASL sharding operates over a CASL key, derived from the CID’s multihash bytes. CASL does not shard on the CID’s string form.

Use the following steps to derive a CASL key:

Accept a CID in either string form or bytes form ([[cid]]).
Decode the CID to obtain its multihash bytes (hash function code, digest length, and digest) ([[cid]]).
Base32-encode the multihash bytes using the base32 algorithm from RFC 4648 ([[rfc4648]]) with:
    the RFC 4648 alphabet (A–Z and 2–7),
    no padding characters,
    and an uppercase output.
Store the resulting string in key.
Return key.

NOTE: This style of key is compatible with the character restrictions used by FlatFS-style filesystem datastores (e.g. the FlatFS implementation used by Kubo).
Sharding

CASL’s default sharding rule is next-to-last/2: it takes the two characters immediately preceding the last character of the CASL key.

Use the following steps to compute a next-to-last shard:

Accept a string key and an integer suffixLen.
If suffixLen is less than 1, throw an error.
If the length of key is less than suffixLen + 1, prepend _ characters to key until its length is suffixLen + 1.
Return the substring of key that consists of the suffixLen characters immediately preceding the final character of key.

Use the following steps to derive a CASL shard:

Let key be the result of running the steps to derive a CASL key.
Let shard be the result of running the steps to compute a next-to-last shard with suffixLen set to 2.
Return shard.

NOTE: The next-to-last/2 rule matches the FlatFS default sharding function used in Kubo’s FlatFS block storage (as defined by the FlatFS implementation’s default shard constant).
Path Construction

A CASL path is constructed from a storage root, a shard, and a leaf name.

Use the following steps to construct a CASL path:

Accept a string root and a CID cid.
Let key be the result of running the steps to derive a CASL key on cid.
Let shard be the result of running the steps to derive a CASL shard on key.
Let name be key. Implementations MAY append a deterministic, store-wide extension (for example, .data), but if they do, it MUST be applied consistently for all objects in that store.
Return the concatenation: <root>/<shard>/<name>.

Example

Given CID: bafkreifn5yxi7nkftsn46b6x26grda57ict7md2xuvfbsgkiahe2e7vnq4

The CASL key (base32 of the multihash bytes, uppercase, no padding) is: CIQK33ROR62ULHE3Z4D5PV4NCGB36QFH6YHVPJKKDEMUQAOJUJ7K3BY
The CASL shard (next-to-last/2) is: 3B
The CASL path (for some chosen root) is: <root>/3B/CIQK33ROR62ULHE3Z4D5PV4NCGB36QFH6YHVPJKKDEMUQAOJUJ7K3BY

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions