Conversation
codingllama
left a comment
There was a problem hiding this comment.
Travis looks unhappy, PTAL.
merkle/hashers/tree_hasher.go
Outdated
| } | ||
|
|
||
| var ( | ||
| maxHashers = trillian.HashStrategy(len(trillian.HashStrategy_value)) |
There was a problem hiding this comment.
There's a dangerous assumption here that len(trillian.HashStrategy_value) is greater than the highest proto tag used. This works for now, but will break if we retire a value from the enum or if we simply skip tag numbers.
There was a problem hiding this comment.
Good point. I'll replace this with a function that iterates through all the possible enums to find the max.
There was a problem hiding this comment.
I'd suggest a map[HashStrategy]XHasher instead. No need to worry about proto tags that way.
merkle/hashers/tree_hasher.go
Outdated
| // RegisterLogHasher registers a hasher for use. | ||
| func RegisterLogHasher(h trillian.HashStrategy, f LogHasher) { | ||
| if h < 0 || h >= maxHashers { | ||
| panic(fmt.Sprintf("RegisterLogHasher(%v) of unknown hasher", h)) |
There was a problem hiding this comment.
nit: If it's on the enum, then the value has to be known. On a related note, we probably shouldn't let people register hashers for UNKNOWN_HASH_STRATEGY.
I would probably prefer an error return to a panic as well.
Ditto for others.
There was a problem hiding this comment.
Good point. should I remove the check?
I'm following the style of golang's crypto package here. Since this function should only be called in an init method, I assumed that a panic was more ok (ish). Ie. it should only be triggered right on launch.
There was a problem hiding this comment.
I think we should check for:
- hash == UNKNOWN_HASH
- hasher == nil (possibly?)
- hash previously registered (ie, warn about overrides)
Re panic or non-panic, would all callers do:
if err := RegisterLogHash(h, hasher); err != nil {
panic(err)
}... or something to that effect? If yes, then I guess the panic inside Register() is appropriate.
There was a problem hiding this comment.
- We're checking for
UNKNOWN_HASH. hasher == nilis ok, and will be caught when requested.- I'll add a check for overrides.
| } | ||
|
|
||
| // NewLogHasher returns a LogHasher | ||
| func NewLogHasher(h trillian.HashStrategy) (LogHasher, error) { |
There was a problem hiding this comment.
nit: Technically, it's not a new hasher. GetLogHasher, maybe?
Ditto for NewMapHasher.
There was a problem hiding this comment.
Get* isn't very Go style friendly... How's LogHasher()?
There was a problem hiding this comment.
Turns out LogHasher conflicts with the interface name.
Even though this isn't technically create new objects (because there's no need to), it seems like it fits in the New* category because it's like a factory method. What do you think?
| ) | ||
|
|
||
| // RegisterLogHasher registers a hasher for use. | ||
| func RegisterLogHasher(h trillian.HashStrategy, f LogHasher) { |
There was a problem hiding this comment.
This solution assumes a hasher is a function of HashStrategy, but in fact it's a mix of HashAlgorithm and HashStrategy. We had this right on the (now deleted) trees functions.
I don't mind about the interface changes, but I'd strongly prefer if you kept trees.Hash and trees.XHasher as they were. I don't think we need a registry for hashers either; we've only got a few (hand-coded) of them anyway.
There was a problem hiding this comment.
I wanted to ask you about this. I saw hash algorithm being incorporated into the call to rfc6962.New.
HashAlgorithm is used to determine the signature algorithm -- that's why it's a subfield of DigitallySigned. Could we consider not overloading the HashAlgorith field? In my experience, its better to include algorithms into the suite identifier, eg. RFC69626_SHA256. Would you be open to that change? Happy to create a separate PR for it. This would greatly simplify several software level checks we do to determine compatibility between various fields since we'd only put permitted values in the enum.
|
Let's chat about this tomorrow. @Martin2112 Would love your thoughts as well. |
|
Still doesn't build. |
|
I'm not totally sold on the need for a hasher registry, specially considering that we're unlikely to have many variations. I'd probably stick to a simpler approach, eg, a switch-case hardcoded for each type. I won't hold you back if you prefer this, but could you explain why a simpler approach won't work? |
affc16b to
06a2820
Compare
Implements a hasher registry in the style of go's crypto package Moves tree_hasher.go to merkle/hashers to break some import cycles.
codingllama
left a comment
There was a problem hiding this comment.
No major comments, only a few nits and typos.
merkle/hashers/tree_hasher.go
Outdated
| // RegisterLogHasher registers a hasher for use. | ||
| func RegisterLogHasher(h trillian.HashStrategy, f LogHasher) { | ||
| if h == trillian.HashStrategy_UNKNOWN_HASH_STRATEGY { | ||
| panic(fmt.Sprintf("RegisterLogHasher(%v) of unknown hasher", h)) |
There was a problem hiding this comment.
nit: Either use %s or h.String(), so the message gets the enum name?
merkle/hashers/tree_hasher.go
Outdated
| panic(fmt.Sprintf("RegisterLogHasher(%v) of unknown hasher", h)) | ||
| } | ||
| if logHashers[h] != nil { | ||
| panic(fmt.Sprintf("%v already registred as a LogHasher", h)) |
There was a problem hiding this comment.
Ditto.
Same for others.
merkle/hashers/tree_hasher.go
Outdated
| panic(fmt.Sprintf("RegisterLogHasher(%v) of unknown hasher", h)) | ||
| } | ||
| if logHashers[h] != nil { | ||
| panic(fmt.Sprintf("%v already registred as a LogHasher", h)) |
merkle/hashers/tree_hasher.go
Outdated
| panic(fmt.Sprintf("RegisterMapHasher(%v) of unknown hasher", h)) | ||
| } | ||
| if mapHashers[h] != nil { | ||
| panic(fmt.Sprintf("%v already registred as a MapHasher", h)) |
merkle/hashers/tree_hasher.go
Outdated
| if f != nil { | ||
| return f, nil | ||
| } | ||
| return nil, fmt.Errorf("LogHasher(%v) is unknown hasher", h) |
There was a problem hiding this comment.
nit: "is unknown hasher" -> "is an unknown hasher".
Same below.
merkle/objhasher/objhasher.go
Outdated
| // NewMapHasher returns a new ObjectHasher based on the passed in MapHasher | ||
| func NewMapHasher(baseHasher merkle.MapHasher) merkle.MapHasher { | ||
| // GetMapHasher returns a new ObjectHasher based on the passed in MapHasher | ||
| func GetMapHasher(baseHasher hashers.MapHasher) hashers.MapHasher { |
There was a problem hiding this comment.
nit: I think this one was better named as NewMapHasher.
Same below (NewLogHasher).
| ktestonly "github.com/google/trillian/crypto/keys/testonly" | ||
| "github.com/google/trillian/crypto/keyspb" | ||
| spb "github.com/google/trillian/crypto/sigpb" | ||
| _ "github.com/google/trillian/merkle/maphasher" // TESET_MAP_HASHER |
There was a problem hiding this comment.
nit: Typo on TEST_MAP_HASHER
|
Updated. PTAL. |
Implements a hasher registry in the style of go's crypto package
Replaces
tree.Hasherwithhashers.NewLogHasherMoves tree_hasher.go to merkle/hashers to break some import cycles.