multiformats / multiformats/py-multihash

No `FuncReg.RegisterVariableSize()` or `DefaultLengths` map

Open
#55 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
17
Forks
17
Avg merge
1h 5m
Merged PRs (30d)
3

Description

Go's registry provides RegisterVariableSize() for hash functions that accept a size hint (like SHAKE, BLAKE3), and exposes a DefaultLengths map mapping code → default output size. Python's FuncReg has neither.

Problem

Go's core/registry.go:

// RegisterVariableSize adds a variable-sized hasher factory that takes a size hint.
func RegisterVariableSize(indicator uint64,
    hasherFactory func(sizeHint int) (hash.Hash, bool)) { ... }

// DefaultLengths maps code → default output size in bytes.
var DefaultLengths = map[uint64]int{}

Python's FuncReg only has:

  • register(code, name, hash_name, hash_new) — fixed-size only
  • hash_from_func(func, length=None) — special-cases SHAKE internally
  • No DefaultLengths equivalent

This means:

  1. Custom variable-size hash functions can't be properly registered
  2. Users can't query the default output length for a hash code
  3. The SHAKE special case in hash_from_func() is a workaround, not a general solution
Proposed Solution
  1. Add DefaultLengths dict to FuncReg:

    class FuncReg:
        default_lengths: ClassVar[dict[int, int]] = {}
    

    Populate it during reset() by calling hash_new().digest_size for each registered function.

  2. Add register_variable_size() classmethod:

    @classmethod
    def register_variable_size(cls, code, name, factory):
        """Register a variable-size hash function.
    
        factory(length: int) -> hash_obj
        When length is -1, return default-length hasher.
        When length is >= 0, return hasher producing at least that many bytes.
        """
        # Get default length
        default_hasher = factory(-1)
        cls.default_lengths[code] = default_hasher.digest_size
        # Store factory
        cls._func_hash[code] = cls._hash(name, factory)
    
  3. Update hash_from_func() to use the factory's size hint:

    @classmethod
    def hash_from_func(cls, func, length=None):
        entry = cls._func_hash[func]
        if callable(entry.new) and func in cls.default_lengths:
            # Variable-size: pass length hint
            return entry.new(length or -1)
        # Fixed-size
        return entry.new()
    
Related

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Locate the Python FuncReg implementation and inspect reset(), register(), hash_from_func(), and the existing SHAKE handling first. Add default-length tracking and variable-size registration without regressing fixed-size behavior, then verify that registered factories receive the requested length and that default lengths are available.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend-api-design
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
66/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.