WIP: Save agent roles integration work before CHORUS rebrand

- Agent roles and coordination features
- Chat API integration testing
- New configuration and workspace management

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
anthonyrawlins
2025-08-01 02:21:11 +10:00
parent 81b473d48f
commit 5978a0b8f5
3713 changed files with 1103925 additions and 59 deletions

View File

@@ -0,0 +1 @@
.vscode/

View File

@@ -0,0 +1,6 @@
[submodule "spec/multicodec"]
path = spec/multicodec
url = https://github.com/multiformats/multicodec.git
[submodule "spec/multihash"]
path = spec/multihash
url = https://github.com/multiformats/multihash.git

21
vendor/github.com/multiformats/go-multihash/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 Juan Batiz-Benet
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

90
vendor/github.com/multiformats/go-multihash/README.md generated vendored Normal file
View File

@@ -0,0 +1,90 @@
# go-multihash
[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io)
[![](https://img.shields.io/badge/project-multiformats-blue.svg?style=flat-square)](https://github.com/multiformats/multiformats)
[![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](https://webchat.freenode.net/?channels=%23ipfs)
[![](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme)
[![GoDoc](https://godoc.org/github.com/multiformats/go-multihash?status.svg)](https://godoc.org/github.com/multiformats/go-multihash)
[![Travis CI](https://img.shields.io/travis/multiformats/go-multihash.svg?style=flat-square&branch=master)](https://travis-ci.org/multiformats/go-multihash)
[![codecov.io](https://img.shields.io/codecov/c/github/multiformats/go-multihash.svg?style=flat-square&branch=master)](https://codecov.io/github/multiformats/go-multihash?branch=master)
> [multihash](https://github.com/multiformats/multihash) implementation in Go
## Table of Contents
- [Install](#install)
- [Usage](#usage)
- [Maintainers](#maintainers)
- [Contribute](#contribute)
- [License](#license)
## Install
`go-multihash` is a standard Go module which can be installed with:
```sh
go get github.com/multiformats/go-multihash
```
## Usage
### Example
This example takes a standard hex-encoded data and uses `EncodeName` to calculate the SHA1 multihash value for the buffer.
The resulting hex-encoded data corresponds to: `<hash function code><digest size><hash function output>`, which could be re-parsed
with `Multihash.FromHexString()`.
```go
package main
import (
"encoding/hex"
"fmt"
"github.com/multiformats/go-multihash"
)
func main() {
// ignores errors for simplicity.
// don't do that at home.
// Decode a SHA1 hash to a binary buffer
buf, _ := hex.DecodeString("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33")
// Create a new multihash with it.
mHashBuf, _ := multihash.EncodeName(buf, "sha1")
// Print the multihash as hex string
fmt.Printf("hex: %s\n", hex.EncodeToString(mHashBuf))
// Parse the binary multihash to a DecodedMultihash
mHash, _ := multihash.Decode(mHashBuf)
// Convert the sha1 value to hex string
sha1hex := hex.EncodeToString(mHash.Digest)
// Print all the information in the multihash
fmt.Printf("obj: %v 0x%x %d %s\n", mHash.Name, mHash.Code, mHash.Length, sha1hex)
}
```
To run, copy to [example/foo.go](example/foo.go) and:
```
> cd example/
> go build
> ./example
hex: 11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33
obj: sha1 0x11 20 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33
```
## Contribute
Contributions welcome. Please check out [the issues](https://github.com/multiformats/go-multihash/issues).
Check out our [contributing document](https://github.com/multiformats/multiformats/blob/master/contributing.md) for more information on how we work, and about contributing in general. Please be aware that all interactions related to multiformats are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).
Small note: If editing the README, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification.
## License
[MIT](LICENSE) © 2014 Juan Batiz-Benet

View File

@@ -0,0 +1,3 @@
coverage:
range: "50...100"
comment: off

View File

@@ -0,0 +1,34 @@
package multihash
import (
"bytes"
"crypto/sha256"
"hash"
)
type identityMultihash struct {
bytes.Buffer
}
func (identityMultihash) BlockSize() int {
return 32 // A prefered block size is nonsense for the "identity" "hash". An arbitrary but unsurprising and positive nonzero number has been chosen to minimize the odds of fascinating bugs.
}
func (x *identityMultihash) Size() int {
return x.Len()
}
func (x *identityMultihash) Sum(digest []byte) []byte {
return x.Bytes()
}
type doubleSha256 struct {
hash.Hash
}
func (x doubleSha256) Sum(digest []byte) []byte {
digest = x.Hash.Sum(digest)
h2 := sha256.New()
h2.Write(digest)
return h2.Sum(digest[0:0])
}

View File

@@ -0,0 +1,35 @@
package multihash
import "errors"
// ErrSumNotSupported is returned when the Sum function code is not implemented
var ErrSumNotSupported = errors.New("no such hash registered")
// ErrLenTooLarge is returned when the hash function cannot produce the requested number of bytes
var ErrLenTooLarge = errors.New("requested length was too large for digest")
// constants
const (
IDENTITY = 0x00
SHA1 = 0x11
SHA2_224 = 0x1013
SHA2_256 = 0x12
SHA2_384 = 0x20
SHA2_512 = 0x13
SHA2_512_224 = 0x1014
SHA2_512_256 = 0x1015
SHA3_224 = 0x17
SHA3_256 = 0x16
SHA3_384 = 0x15
SHA3_512 = 0x14
KECCAK_224 = 0x1A
KECCAK_256 = 0x1B
KECCAK_384 = 0x1C
KECCAK_512 = 0x1D
BLAKE3 = 0x1E
SHAKE_128 = 0x18
SHAKE_256 = 0x19
MURMUR3X64_64 = 0x22
MD5 = 0xd5
DBL_SHA2_256 = 0x56
)

View File

@@ -0,0 +1,123 @@
package multihash
import (
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"fmt"
"hash"
)
// registry is a simple map which maps a multihash indicator number
// to a function : (size:int) -> ((hasher:hash.Hash), (bool:success))
// The function may error (i.e., return (nil, false)) to signify that the hasher can't return that many bytes.
//
// Multihash indicator numbers are reserved and described in
// https://github.com/multiformats/multicodec/blob/master/table.csv .
// The keys used in this map must match those reservations.
//
// Hashers which are available in the golang stdlib will be registered automatically.
// Others can be added using the Register function.
var registry = make(map[uint64]func(int) (h hash.Hash, ok bool))
// Register adds a new hash to the set available from GetHasher and Sum.
//
// Register has a global effect and should only be used at package init time to avoid data races.
//
// The indicator code should be per the numbers reserved and described in
// https://github.com/multiformats/multicodec/blob/master/table.csv .
//
// If Register is called with the same indicator code more than once, the last call wins.
// In practice, this means that if an application has a strong opinion about what implementation to use for a certain hash
// (e.g., perhaps they want to override the sha256 implementation to use a special hand-rolled assembly variant
// rather than the stdlib one which is registered by default),
// then this can be done by making a Register call with that effect at init time in the application's main package.
// This should have the desired effect because the root of the import tree has its init time effect last.
func Register(indicator uint64, hasherFactory func() hash.Hash) {
if hasherFactory == nil {
panic("not sensible to attempt to register a nil function")
}
maxSize := hasherFactory().Size()
registry[indicator] = func(size int) (hash.Hash, bool) {
if size > maxSize {
return nil, false
}
return hasherFactory(), true
}
DefaultLengths[indicator] = maxSize
}
// RegisterVariableSize is like Register, but adds a new variable-sized hasher factory that takes a
// size hint.
//
// When passed -1, the hasher should produce digests with the hash-function's default length. When
// passed a non-negative integer, the hasher should try to produce digests of at least the specified
// size.
func RegisterVariableSize(indicator uint64, hasherFactory func(sizeHint int) (hash.Hash, bool)) {
if hasherFactory == nil {
panic("not sensible to attempt to register a nil function")
}
if hasher, ok := hasherFactory(-1); !ok {
panic("failed to determine default hash length for hasher")
} else {
DefaultLengths[indicator] = hasher.Size()
}
registry[indicator] = hasherFactory
}
// GetHasher returns a new hash.Hash according to the indicator code number provided.
//
// The indicator code should be per the numbers reserved and described in
// https://github.com/multiformats/multicodec/blob/master/table.csv .
//
// The actual hashers available are determined by what has been registered.
// The registry automatically contains those hashers which are available in the golang standard libraries
// (which includes md5, sha1, sha256, sha384, sha512, and the "identity" mulithash, among others).
// Other hash implementations can be made available by using the Register function.
// The 'go-mulithash/register/*' packages can also be imported to gain more common hash functions.
//
// If an error is returned, it will match `errors.Is(err, ErrSumNotSupported)`.
func GetHasher(indicator uint64) (hash.Hash, error) {
return GetVariableHasher(indicator, -1)
}
// GetVariableHasher returns a new hash.Hash according to the indicator code number provided, with
// the specified size hint.
//
// NOTE: The size hint is only a hint. Hashers will attempt to produce at least the number of requested bytes, but may not.
//
// This function can fail if either the hash code is not registered, or the passed size hint is
// statically incompatible with the specified hash function.
func GetVariableHasher(indicator uint64, sizeHint int) (hash.Hash, error) {
factory, exists := registry[indicator]
if !exists {
return nil, fmt.Errorf("unknown multihash code %d (0x%x): %w", indicator, indicator, ErrSumNotSupported)
}
hasher, ok := factory(sizeHint)
if !ok {
return nil, ErrLenTooLarge
}
return hasher, nil
}
// DefaultLengths maps a multihash indicator code to the output size for that hash, in units of bytes.
//
// This map is populated when a hash function is registered by the Register function.
// It's effectively a shortcut for asking Size() on the hash.Hash.
var DefaultLengths = map[uint64]int{}
func init() {
RegisterVariableSize(IDENTITY, func(_ int) (hash.Hash, bool) { return &identityMultihash{}, true })
Register(MD5, md5.New)
Register(SHA1, sha1.New)
Register(SHA2_224, sha256.New224)
Register(SHA2_256, sha256.New)
Register(SHA2_384, sha512.New384)
Register(SHA2_512, sha512.New)
Register(SHA2_512_224, sha512.New512_224)
Register(SHA2_512_256, sha512.New512_256)
Register(DBL_SHA2_256, func() hash.Hash { return &doubleSha256{sha256.New()} })
}

98
vendor/github.com/multiformats/go-multihash/io.go generated vendored Normal file
View File

@@ -0,0 +1,98 @@
package multihash
import (
"errors"
"io"
"math"
"github.com/multiformats/go-varint"
)
// Reader is an io.Reader wrapper that exposes a function
// to read a whole multihash, parse it, and return it.
type Reader interface {
io.Reader
ReadMultihash() (Multihash, error)
}
// Writer is an io.Writer wrapper that exposes a function
// to write a whole multihash.
type Writer interface {
io.Writer
WriteMultihash(Multihash) error
}
// NewReader wraps an io.Reader with a multihash.Reader
func NewReader(r io.Reader) Reader {
return &mhReader{r}
}
// NewWriter wraps an io.Writer with a multihash.Writer
func NewWriter(w io.Writer) Writer {
return &mhWriter{w}
}
type mhReader struct {
r io.Reader
}
func (r *mhReader) Read(buf []byte) (n int, err error) {
return r.r.Read(buf)
}
func (r *mhReader) ReadByte() (byte, error) {
if br, ok := r.r.(io.ByteReader); ok {
return br.ReadByte()
}
var b [1]byte
n, err := r.r.Read(b[:])
if n == 1 {
return b[0], nil
}
if err == nil {
if n != 0 {
panic("reader returned an invalid length")
}
err = io.ErrNoProgress
}
return 0, err
}
func (r *mhReader) ReadMultihash() (Multihash, error) {
code, err := varint.ReadUvarint(r)
if err != nil {
return nil, err
}
length, err := varint.ReadUvarint(r)
if err != nil {
return nil, err
}
if length > math.MaxInt32 {
return nil, errors.New("digest too long, supporting only <= 2^31-1")
}
buf := make([]byte, varint.UvarintSize(code)+varint.UvarintSize(length)+int(length))
n := varint.PutUvarint(buf, code)
n += varint.PutUvarint(buf[n:], length)
if _, err := io.ReadFull(r.r, buf[n:]); err != nil {
return nil, err
}
return Cast(buf)
}
type mhWriter struct {
w io.Writer
}
func (w *mhWriter) Write(buf []byte) (n int, err error) {
return w.w.Write(buf)
}
func (w *mhWriter) WriteMultihash(m Multihash) error {
_, err := w.w.Write([]byte(m))
return err
}

View File

@@ -0,0 +1,322 @@
// Package multihash is the Go implementation of
// https://github.com/multiformats/multihash, or self-describing
// hashes.
package multihash
import (
"encoding/hex"
"errors"
"fmt"
"math"
b58 "github.com/mr-tron/base58/base58"
"github.com/multiformats/go-varint"
)
// errors
var (
ErrUnknownCode = errors.New("unknown multihash code")
ErrTooShort = errors.New("multihash too short. must be >= 2 bytes")
ErrTooLong = errors.New("multihash too long. must be < 129 bytes")
ErrLenNotSupported = errors.New("multihash does not yet support digests longer than 127 bytes")
ErrInvalidMultihash = errors.New("input isn't valid multihash")
ErrVarintBufferShort = errors.New("uvarint: buffer too small")
ErrVarintTooLong = errors.New("uvarint: varint too big (max 64bit)")
)
// ErrInconsistentLen is returned when a decoded multihash has an inconsistent length
type ErrInconsistentLen struct {
dm DecodedMultihash
lengthFound int
}
func (e ErrInconsistentLen) Error() string {
return fmt.Sprintf("multihash length inconsistent: expected %d; got %d", e.dm.Length, e.lengthFound)
}
// constants
const (
IDENTITY = 0x00
// Deprecated: use IDENTITY
ID = IDENTITY
SHA1 = 0x11
SHA2_256 = 0x12
SHA2_512 = 0x13
SHA3_224 = 0x17
SHA3_256 = 0x16
SHA3_384 = 0x15
SHA3_512 = 0x14
SHA3 = SHA3_512
KECCAK_224 = 0x1A
KECCAK_256 = 0x1B
KECCAK_384 = 0x1C
KECCAK_512 = 0x1D
BLAKE3 = 0x1E
SHAKE_128 = 0x18
SHAKE_256 = 0x19
BLAKE2B_MIN = 0xb201
BLAKE2B_MAX = 0xb240
BLAKE2S_MIN = 0xb241
BLAKE2S_MAX = 0xb260
MD5 = 0xd5
DBL_SHA2_256 = 0x56
MURMUR3X64_64 = 0x22
// Deprecated: use MURMUR3X64_64
MURMUR3 = MURMUR3X64_64
SHA2_256_TRUNC254_PADDED = 0x1012
X11 = 0x1100
POSEIDON_BLS12_381_A1_FC1 = 0xb401
)
func init() {
// Add blake2b (64 codes)
for c := uint64(BLAKE2B_MIN); c <= BLAKE2B_MAX; c++ {
n := c - BLAKE2B_MIN + 1
name := fmt.Sprintf("blake2b-%d", n*8)
Names[name] = c
Codes[c] = name
}
// Add blake2s (32 codes)
for c := uint64(BLAKE2S_MIN); c <= BLAKE2S_MAX; c++ {
n := c - BLAKE2S_MIN + 1
name := fmt.Sprintf("blake2s-%d", n*8)
Names[name] = c
Codes[c] = name
}
}
// Names maps the name of a hash to the code
var Names = map[string]uint64{
"identity": IDENTITY,
"sha1": SHA1,
"sha2-256": SHA2_256,
"sha2-512": SHA2_512,
"sha3": SHA3_512,
"sha3-224": SHA3_224,
"sha3-256": SHA3_256,
"sha3-384": SHA3_384,
"sha3-512": SHA3_512,
"dbl-sha2-256": DBL_SHA2_256,
"murmur3-x64-64": MURMUR3X64_64,
"keccak-224": KECCAK_224,
"keccak-256": KECCAK_256,
"keccak-384": KECCAK_384,
"keccak-512": KECCAK_512,
"blake3": BLAKE3,
"shake-128": SHAKE_128,
"shake-256": SHAKE_256,
"sha2-256-trunc254-padded": SHA2_256_TRUNC254_PADDED,
"x11": X11,
"md5": MD5,
"poseidon-bls12_381-a2-fc1": POSEIDON_BLS12_381_A1_FC1,
}
// Codes maps a hash code to it's name
var Codes = map[uint64]string{
IDENTITY: "identity",
SHA1: "sha1",
SHA2_256: "sha2-256",
SHA2_512: "sha2-512",
SHA3_224: "sha3-224",
SHA3_256: "sha3-256",
SHA3_384: "sha3-384",
SHA3_512: "sha3-512",
DBL_SHA2_256: "dbl-sha2-256",
MURMUR3X64_64: "murmur3-x64-64",
KECCAK_224: "keccak-224",
KECCAK_256: "keccak-256",
KECCAK_384: "keccak-384",
KECCAK_512: "keccak-512",
BLAKE3: "blake3",
SHAKE_128: "shake-128",
SHAKE_256: "shake-256",
SHA2_256_TRUNC254_PADDED: "sha2-256-trunc254-padded",
X11: "x11",
POSEIDON_BLS12_381_A1_FC1: "poseidon-bls12_381-a2-fc1",
MD5: "md5",
}
// reads a varint from buf and returns bytes read.
func uvarint(buf []byte) (uint64, []byte, error) {
n, c, err := varint.FromUvarint(buf)
if err != nil {
return n, buf, err
}
if c == 0 {
return n, buf, ErrVarintBufferShort
} else if c < 0 {
return n, buf[-c:], ErrVarintTooLong
} else {
return n, buf[c:], nil
}
}
// DecodedMultihash represents a parsed multihash and allows
// easy access to the different parts of a multihash.
type DecodedMultihash struct {
Code uint64
Name string
Length int // Length is just int as it is type of len() opearator
Digest []byte // Digest holds the raw multihash bytes
}
// Multihash is byte slice with the following form:
// <hash function code><digest size><hash function output>.
// See the spec for more information.
type Multihash []byte
// HexString returns the hex-encoded representation of a multihash.
func (m Multihash) HexString() string {
return hex.EncodeToString([]byte(m))
}
// String is an alias to HexString().
func (m Multihash) String() string {
return m.HexString()
}
// FromHexString parses a hex-encoded multihash.
func FromHexString(s string) (Multihash, error) {
b, err := hex.DecodeString(s)
if err != nil {
return Multihash{}, err
}
return Cast(b)
}
// B58String returns the B58-encoded representation of a multihash.
func (m Multihash) B58String() string {
return b58.Encode([]byte(m))
}
// FromB58String parses a B58-encoded multihash.
func FromB58String(s string) (m Multihash, err error) {
b, err := b58.Decode(s)
if err != nil {
return Multihash{}, ErrInvalidMultihash
}
return Cast(b)
}
// Cast casts a buffer onto a multihash, and returns an error
// if it does not work.
func Cast(buf []byte) (Multihash, error) {
_, err := Decode(buf)
if err != nil {
return Multihash{}, err
}
return Multihash(buf), nil
}
// Decode parses multihash bytes into a DecodedMultihash.
func Decode(buf []byte) (*DecodedMultihash, error) {
// outline decode allowing the &dm expression to be inlined into the caller.
// This moves the heap allocation into the caller and if the caller doesn't
// leak dm the compiler will use a stack allocation instead.
// If you do not outline this &dm always heap allocate since the pointer is
// returned which cause a heap allocation because Decode's stack frame is
// about to disapear.
dm, err := decode(buf)
if err != nil {
return nil, err
}
return &dm, nil
}
func decode(buf []byte) (dm DecodedMultihash, err error) {
rlen, code, hdig, err := readMultihashFromBuf(buf)
if err != nil {
return DecodedMultihash{}, err
}
dm = DecodedMultihash{
Code: code,
Name: Codes[code],
Length: len(hdig),
Digest: hdig,
}
if len(buf) != rlen {
return dm, ErrInconsistentLen{dm, rlen}
}
return dm, nil
}
// Encode a hash digest along with the specified function code.
// Note: the length is derived from the length of the digest itself.
//
// The error return is legacy; it is always nil.
func Encode(buf []byte, code uint64) ([]byte, error) {
// FUTURE: this function always causes heap allocs... but when used, this value is almost always going to be appended to another buffer (either as part of CID creation, or etc) -- should this whole function be rethought and alternatives offered?
newBuf := make([]byte, varint.UvarintSize(code)+varint.UvarintSize(uint64(len(buf)))+len(buf))
n := varint.PutUvarint(newBuf, code)
n += varint.PutUvarint(newBuf[n:], uint64(len(buf)))
copy(newBuf[n:], buf)
return newBuf, nil
}
// EncodeName is like Encode() but providing a string name
// instead of a numeric code. See Names for allowed values.
func EncodeName(buf []byte, name string) ([]byte, error) {
return Encode(buf, Names[name])
}
// readMultihashFromBuf reads a multihash from the given buffer, returning the
// individual pieces of the multihash.
// Note: the returned digest is a slice over the passed in data and should be
// copied if the buffer will be reused
func readMultihashFromBuf(buf []byte) (int, uint64, []byte, error) {
initBufLength := len(buf)
if initBufLength < 2 {
return 0, 0, nil, ErrTooShort
}
var err error
var code, length uint64
code, buf, err = uvarint(buf)
if err != nil {
return 0, 0, nil, err
}
length, buf, err = uvarint(buf)
if err != nil {
return 0, 0, nil, err
}
if length > math.MaxInt32 {
return 0, 0, nil, errors.New("digest too long, supporting only <= 2^31-1")
}
if int(length) > len(buf) {
return 0, 0, nil, errors.New("length greater than remaining number of bytes in buffer")
}
// rlen is the advertised size of the CID
rlen := (initBufLength - len(buf)) + int(length)
return rlen, code, buf[:length], nil
}
// MHFromBytes reads a multihash from the given byte buffer, returning the
// number of bytes read as well as the multihash
func MHFromBytes(buf []byte) (int, Multihash, error) {
nr, _, _, err := readMultihashFromBuf(buf)
if err != nil {
return 0, nil, err
}
return nr, Multihash(buf[:nr]), nil
}

View File

@@ -0,0 +1,24 @@
/*
This package has no purpose except to perform registration of mulithashes.
It is meant to be used as a side-effecting import, e.g.
import (
_ "github.com/multiformats/go-multihash/register/all"
)
This package registers many multihashes at once.
Importing it will increase the size of your dependency tree significantly.
It's recommended that you import this package if you're building some
kind of data broker application, which may need to handle many different kinds of hashes;
if you're building an application which you know only handles a specific hash,
importing this package may bloat your builds unnecessarily.
*/
package all
import (
_ "github.com/multiformats/go-multihash/register/blake2"
_ "github.com/multiformats/go-multihash/register/blake3"
_ "github.com/multiformats/go-multihash/register/murmur3"
_ "github.com/multiformats/go-multihash/register/sha3"
)

View File

@@ -0,0 +1,55 @@
/*
This package has no purpose except to perform registration of multihashes.
It is meant to be used as a side-effecting import, e.g.
import (
_ "github.com/multiformats/go-multihash/register/blake2"
)
This package registers several multihashes for the blake2 family
(both the 's' and the 'b' variants, and in a variety of sizes).
*/
package blake2
import (
"hash"
"golang.org/x/crypto/blake2b"
"golang.org/x/crypto/blake2s"
multihash "github.com/multiformats/go-multihash/core"
)
const (
blake2b_min = 0xb201
blake2b_max = 0xb240
blake2s_min = 0xb241
blake2s_max = 0xb260
)
func init() {
// blake2s
// This package only enables support for 32byte (256 bit) blake2s.
multihash.Register(blake2s_min+31, func() hash.Hash {
h, err := blake2s.New256(nil)
if err != nil {
panic(err)
}
return h
})
// blake2b
// There's a whole range of these.
for c := uint64(blake2b_min); c <= blake2b_max; c++ {
size := int(c - blake2b_min + 1)
multihash.Register(c, func() hash.Hash {
hasher, err := blake2b.New(size, nil)
if err != nil {
panic(err)
}
return hasher
})
}
}

View File

@@ -0,0 +1,33 @@
/*
This package has no purpose except to register the blake3 hash function.
It is meant to be used as a side-effecting import, e.g.
import (
_ "github.com/multiformats/go-multihash/register/blake3"
)
*/
package blake3
import (
"hash"
"lukechampine.com/blake3"
multihash "github.com/multiformats/go-multihash/core"
)
const DefaultSize = 32
const MaxSize = 128
func init() {
multihash.RegisterVariableSize(multihash.BLAKE3, func(size int) (hash.Hash, bool) {
if size == -1 {
size = DefaultSize
} else if size > MaxSize || size <= 0 {
return nil, false
}
h := blake3.New(size, nil)
return h, true
})
}

View File

@@ -0,0 +1,22 @@
//go:build go1.21
// This package has no purpose except to perform registration of multihashes.
//
// It is meant to be used as a side-effecting import, e.g.
//
// import (
// _ "github.com/multiformats/go-multihash/register/miniosha256"
// )
//
// This package registers alternative implementations for sha2-256, using
// the github.com/minio/sha256-simd library for go1.20 and bellow. Go 1.21 and
// later fallback to [github.com/multiformats/go-multihash/register/sha256].
//
// Deprecated: please switch to [github.com/multiformats/go-multihash/register/sha256]
// as of go1.21 the go std has a SHANI implementation that is just as fast. See https://go.dev/issue/50543.
// This will be removed shortly after go1.22 is released.
package miniosha256
import (
_ "github.com/multiformats/go-multihash/register/sha256"
)

View File

@@ -0,0 +1,29 @@
//go:build !go1.21
// This package has no purpose except to perform registration of multihashes.
//
// It is meant to be used as a side-effecting import, e.g.
//
// import (
// _ "github.com/multiformats/go-multihash/register/miniosha256"
// )
//
// This package registers alternative implementations for sha2-256, using
// the github.com/minio/sha256-simd library for go1.20 and bellow. Go 1.21 and
// later fallback to [github.com/multiformats/go-multihash/register/sha256].
//
// Note if you are using go1.21 or above this package is deprecated in favor of
// [github.com/multiformats/go-multihash/register/sha256] because as of go1.21
// the go std has a SHANI implementation that is just as fast. See https://go.dev/issue/50543.
// This will be removed shortly after go1.22 is released.
package miniosha256
import (
"github.com/minio/sha256-simd"
multihash "github.com/multiformats/go-multihash/core"
)
func init() {
multihash.Register(multihash.SHA2_256, sha256.New)
}

View File

@@ -0,0 +1,40 @@
/*
This package has no purpose except to perform registration of multihashes.
It is meant to be used as a side-effecting import, e.g.
import (
_ "github.com/multiformats/go-multihash/register/murmur3"
)
This package registers multihashes for murmur3
*/
package murmur3
import (
"hash"
multihash "github.com/multiformats/go-multihash/core"
"github.com/spaolacci/murmur3"
)
func init() {
multihash.Register(multihash.MURMUR3X64_64, func() hash.Hash { return murmur64{murmur3.New64()} })
}
// A wrapper is needed to export the correct size, because murmur3 incorrectly advertises Hash64 as a 128bit hash.
type murmur64 struct {
hash.Hash64
}
func (murmur64) BlockSize() int {
return 1
}
func (x murmur64) Size() int {
return 8
}
func (x murmur64) Sum(digest []byte) []byte {
return x.Hash64.Sum(digest)
}

View File

@@ -0,0 +1,21 @@
// This package has no purpose except to perform registration of multihashes.
//
// It is meant to be used as a side-effecting import, e.g.
//
// import (
// _ "github.com/multiformats/go-multihash/register/sha256"
// )
//
// This package an implementation of sha256 using the go std, this is recomanded
// if you are using go1.21 or above.
package sha256
import (
"crypto/sha256"
multihash "github.com/multiformats/go-multihash/core"
)
func init() {
multihash.Register(multihash.SHA2_256, sha256.New)
}

View File

@@ -0,0 +1,62 @@
/*
This package has no purpose except to perform registration of multihashes.
It is meant to be used as a side-effecting import, e.g.
import (
_ "github.com/multiformats/go-multihash/register/sha3"
)
This package registers several multihashes for the sha3 family.
This also includes some functions known as "shake" and "keccak",
since they share much of their implementation and come in the same repos.
*/
package sha3
import (
"hash"
"golang.org/x/crypto/sha3"
multihash "github.com/multiformats/go-multihash/core"
)
func init() {
multihash.Register(multihash.SHA3_512, sha3.New512)
multihash.Register(multihash.SHA3_384, sha3.New384)
multihash.Register(multihash.SHA3_256, sha3.New256)
multihash.Register(multihash.SHA3_224, sha3.New224)
multihash.Register(multihash.SHAKE_128, func() hash.Hash { return shakeNormalizer{sha3.NewShake128(), 128 / 8 * 2} })
multihash.Register(multihash.SHAKE_256, func() hash.Hash { return shakeNormalizer{sha3.NewShake256(), 256 / 8 * 2} })
multihash.Register(multihash.KECCAK_256, sha3.NewLegacyKeccak256)
multihash.Register(multihash.KECCAK_512, sha3.NewLegacyKeccak512)
}
// sha3.ShakeHash presents a somewhat odd interface, and requires a wrapper to normalize it to the usual hash.Hash interface.
//
// Some of the fiddly bits required by this normalization probably makes it undesirable for use in the highest performance applications;
// There's at least one extra allocation in constructing it (sha3.ShakeHash is an interface, so that's one heap escape; and there's a second heap escape when this normalizer struct gets boxed into a hash.Hash interface),
// and there's at least one extra allocation in getting a sum out of it (because reading a shake hash is a mutation (!) and the API only provides cloning as a way to escape this).
// Fun.
type shakeNormalizer struct {
sha3.ShakeHash
size int
}
func (shakeNormalizer) BlockSize() int {
return 32 // Shake doesn't have a prefered block size, apparently. An arbitrary but unsurprising and positive nonzero number has been chosen to minimize the odds of fascinating bugs.
}
func (x shakeNormalizer) Size() int {
return x.size
}
func (x shakeNormalizer) Sum(digest []byte) []byte {
if len(digest) < x.size {
digest = make([]byte, x.size)
}
digest = digest[0:x.size]
h2 := x.Clone() // clone it, because reading mutates this kind of hash (!) which is not the standard contract for a Hash.Sum method.
h2.Read(digest) // not capable of underreading. See sha3.ShakeSum256 for similar usage.
return digest
}

View File

@@ -0,0 +1,31 @@
package multihash
import (
"hash"
mhreg "github.com/multiformats/go-multihash/core"
_ "github.com/multiformats/go-multihash/register/all"
_ "github.com/multiformats/go-multihash/register/miniosha256"
)
// Register is an alias for Register in the core package.
//
// Consider using the core package instead of this multihash package;
// that package does not introduce transitive dependencies except for those you opt into,
// and will can result in smaller application builds.
func Register(indicator uint64, hasherFactory func() hash.Hash) {
mhreg.Register(indicator, hasherFactory)
}
// Register is an alias for Register in the core package.
//
// Consider using the core package instead of this multihash package;
// that package does not introduce transitive dependencies except for those you opt into,
// and will can result in smaller application builds.
func GetHasher(indicator uint64) (hash.Hash, error) {
return mhreg.GetHasher(indicator)
}
// DefaultLengths maps a multihash indicator code to the output size for that hash, in units of bytes.
var DefaultLengths = mhreg.DefaultLengths

66
vendor/github.com/multiformats/go-multihash/set.go generated vendored Normal file
View File

@@ -0,0 +1,66 @@
package multihash
// Set is a set of Multihashes, holding one copy per Multihash.
type Set struct {
set map[string]struct{}
}
// NewSet creates a new set correctly initialized.
func NewSet() *Set {
return &Set{
set: make(map[string]struct{}),
}
}
// Add adds a new multihash to the set.
func (s *Set) Add(m Multihash) {
s.set[string(m)] = struct{}{}
}
// Len returns the number of elements in the set.
func (s *Set) Len() int {
return len(s.set)
}
// Has returns true if the element is in the set.
func (s *Set) Has(m Multihash) bool {
_, ok := s.set[string(m)]
return ok
}
// Visit adds a multihash only if it is not in the set already. Returns true
// if the multihash was added (was not in the set before).
func (s *Set) Visit(m Multihash) bool {
_, ok := s.set[string(m)]
if !ok {
s.set[string(m)] = struct{}{}
return true
}
return false
}
// ForEach runs f(m) with each multihash in the set. If returns immediately if
// f(m) returns an error.
func (s *Set) ForEach(f func(m Multihash) error) error {
for elem := range s.set {
mh := Multihash(elem)
if err := f(mh); err != nil {
return err
}
}
return nil
}
// Remove removes an element from the set.
func (s *Set) Remove(m Multihash) {
delete(s.set, string(m))
}
// All returns a slice with all the elements in the set.
func (s *Set) All() []Multihash {
out := make([]Multihash, 0, len(s.set))
for m := range s.set {
out = append(out, Multihash(m))
}
return out
}

77
vendor/github.com/multiformats/go-multihash/sum.go generated vendored Normal file
View File

@@ -0,0 +1,77 @@
package multihash
import (
"fmt"
"hash"
"io"
mhreg "github.com/multiformats/go-multihash/core"
)
// ErrSumNotSupported is returned when the Sum function code is not implemented
var ErrSumNotSupported = mhreg.ErrSumNotSupported
var ErrLenTooLarge = mhreg.ErrLenTooLarge
// Sum obtains the cryptographic sum of a given buffer. The length parameter
// indicates the length of the resulting digest. Passing a negative value uses
// default length values for the selected hash function.
func Sum(data []byte, code uint64, length int) (Multihash, error) {
// Get the algorithm.
hasher, err := mhreg.GetVariableHasher(code, length)
if err != nil {
return nil, err
}
// Feed data in.
if _, err := hasher.Write(data); err != nil {
return nil, err
}
return encodeHash(hasher, code, length)
}
// SumStream obtains the cryptographic sum of a given stream. The length
// parameter indicates the length of the resulting digest. Passing a negative
// value uses default length values for the selected hash function.
func SumStream(r io.Reader, code uint64, length int) (Multihash, error) {
// Get the algorithm.
hasher, err := mhreg.GetVariableHasher(code, length)
if err != nil {
return nil, err
}
// Feed data in.
if _, err = io.Copy(hasher, r); err != nil {
return nil, err
}
return encodeHash(hasher, code, length)
}
func encodeHash(hasher hash.Hash, code uint64, length int) (Multihash, error) {
// Compute final hash.
// A new slice is allocated. FUTURE: see other comment below about allocation, and review together with this line to try to improve.
sum := hasher.Sum(nil)
// Deal with any truncation.
// Unless it's an identity multihash. Those have different rules.
if length < 0 {
length = hasher.Size()
}
if len(sum) < length {
return nil, ErrLenTooLarge
}
if length >= 0 {
if code == IDENTITY {
if length != len(sum) {
return nil, fmt.Errorf("the length of the identity hash (%d) must be equal to the length of the data (%d)", length, len(sum))
}
}
sum = sum[:length]
}
// Put the multihash metainfo bytes at the front of the buffer.
// FUTURE: try to improve allocations here. Encode does several which are probably avoidable, but it's the shape of the Encode method arguments that forces this.
return Encode(sum, code)
}

View File

@@ -0,0 +1,3 @@
{
"version": "v0.2.3"
}