Skip to content

Commit

Permalink
Add core package (min deps) and give root package full transitive dep…
Browse files Browse the repository at this point in the history
…s again.

The transitive dependencies in the root package are still managed by
this whole registry system (which now resides in the 'core' package),
so we have parity and *mostly* just one suite of code to maintain.

You can now use this 'core' package when interested in dependency
minimization.  In exchange, the "register/*" imports may be required.

You can just also just yank updates to go-multihash, and if you were
already using it (and happen to be using one of these
now-optional(-but-only-if-you-use-core))... nothing should actually
change; the "register/*" imports won't be required because the
root package does them for you.

Some constants are replicated.  This was the minimum step necessary
to avoid import cycles.  I'm not spending time prettifying it because
we really probably ought to be refactoring this to use the package
of constants in go-multicodec that's automatically generated, and
yet, that is a scope limit we're trying not to cross during this
changeset.
  • Loading branch information
warpfork committed Mar 11, 2021
1 parent 1a96911 commit cebc9f8
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 66 deletions.
File renamed without changes.
26 changes: 26 additions & 0 deletions core/magic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package multihash

import "errors"

// ErrSumNotSupported is returned when the Sum function code is not implemented
var ErrSumNotSupported = errors.New("no such hash registered")

// constants
const (
IDENTITY = 0x00
SHA1 = 0x11
SHA2_256 = 0x12
SHA2_512 = 0x13
SHA3_224 = 0x17
SHA3_256 = 0x16
SHA3_384 = 0x15
SHA3_512 = 0x14
KECCAK_224 = 0x1A
KECCAK_256 = 0x1B
KECCAK_384 = 0x1C
KECCAK_512 = 0x1D
SHAKE_128 = 0x18
SHAKE_256 = 0x19
MD5 = 0xd5
DBL_SHA2_256 = 0x56
)
77 changes: 77 additions & 0 deletions core/registry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
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 standard golang Hash interface.
//
// 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() hash.Hash)

// 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")
}
registry[indicator] = hasherFactory
DefaultLengths[indicator] = hasherFactory().Size()
}

// 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) {
factory, exists := registry[indicator]
if !exists {
return nil, fmt.Errorf("unknown multihash code %d (0x%x): %w", indicator, indicator, ErrSumNotSupported)
}
return factory(), 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() {
Register(IDENTITY, func() hash.Hash { return &identityMultihash{} })
Register(MD5, md5.New)
Register(SHA1, sha1.New)
Register(SHA2_256, sha256.New)
Register(SHA2_512, sha512.New)
Register(DBL_SHA2_256, func() hash.Hash { return &doubleSha256{sha256.New()} })
}
2 changes: 1 addition & 1 deletion register/blake2/multihash_blake2.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
"github.com/minio/blake2b-simd"
"golang.org/x/crypto/blake2s"

"github.com/multiformats/go-multihash"
"github.com/multiformats/go-multihash/core"
)

const (
Expand Down
2 changes: 1 addition & 1 deletion register/miniosha256/multihash_miniosha256.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ package miniosha256
import (
"github.com/minio/sha256-simd"

"github.com/multiformats/go-multihash"
"github.com/multiformats/go-multihash/core"
)

func init() {
Expand Down
2 changes: 1 addition & 1 deletion register/sha3/multihash_sha3.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (

"golang.org/x/crypto/sha3"

"github.com/multiformats/go-multihash"
"github.com/multiformats/go-multihash/core"
)

func init() {
Expand Down
78 changes: 16 additions & 62 deletions registry.go
Original file line number Diff line number Diff line change
@@ -1,77 +1,31 @@
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 standard golang Hash interface.
//
// 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() hash.Hash)
mhreg "github.com/multiformats/go-multihash/core"

// 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 .
_ "github.com/multiformats/go-multihash/register/all"
_ "github.com/multiformats/go-multihash/register/miniosha256"
)

// Register is an alias for Register in the core package.
//
// 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.
// 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) {
if hasherFactory == nil {
panic("not sensible to attempt to register a nil function")
}
registry[indicator] = hasherFactory
DefaultLengths[indicator] = hasherFactory().Size()
mhreg.Register(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.
// Register is an alias for Register in the core package.
//
// If an error is returned, it will match `errors.Is(err, ErrSumNotSupported)`.
// 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) {
factory, exists := registry[indicator]
if !exists {
return nil, fmt.Errorf("unknown multihash code %d (0x%x): %w", indicator, indicator, ErrSumNotSupported)
}
return factory(), nil
return mhreg.GetHasher(indicator)
}

// 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() {
Register(IDENTITY, func() hash.Hash { return &identityMultihash{} })
Register(MD5, md5.New)
Register(SHA1, sha1.New)
Register(SHA2_256, sha256.New)
Register(SHA2_512, sha512.New)
Register(DBL_SHA2_256, func() hash.Hash { return &doubleSha256{sha256.New()} })
}
var DefaultLengths = mhreg.DefaultLengths
4 changes: 3 additions & 1 deletion sum.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package multihash
import (
"errors"
"fmt"

mhreg "github.com/multiformats/go-multihash/core"
)

// ErrSumNotSupported is returned when the Sum function code is not implemented
var ErrSumNotSupported = errors.New("no such hash registered")
var ErrSumNotSupported = mhreg.ErrSumNotSupported

var ErrLenTooLarge = errors.New("requested length was too large for digest")

Expand Down

0 comments on commit cebc9f8

Please sign in to comment.