-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor record validation #17
Conversation
Instead of re-implementing the key splitting logic everywhere, we might as well expose it.
When generalizing routing, I noticed a couple of issues: 1. Passing around separate validators/selectors is annoying. All records should support both validation and selection. 2. We already need validators with state (e.g., access to the peerstore) so we might as well define them in terms of an interface. 3. Not all record stores will use the record protobuf type and tying validation to it is kind of annoying. 4. Using the same interface for the namespaced validator and the sub-validators is really convenient. The cost of having to re-split the key is minimal.
// Validate validates the given record, returning an error if it's | ||
// invalid (e.g., expired, signed by the wrong key, etc.). | ||
Validate(key string, value []byte) error | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it worth making the Select
function look more like the less
parameter to Sort
's Slice
function?
Otherwise every Select
implementation will need to implement similar functionality to iterate over the values, return an error if the list is empty, or if there is no value found etc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO, that can be implemented as a wrapper. Defining Select
as we have here allows us to halve the number of times we have to deserialize the values when comparing multiple values.
Wrapper:
func Less(key string, values [][]byte, v Validator) func(i, j int) bool { /* ... */ }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Stebalien agreed. this is less a full sort and more a min function. unless there is use for a full priority sorted list of entries, i think this approach is fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good! would only consider leveraging SplitN if that makes sense!
|
||
// SplitKey takes a key in the form `/$namespace/$path` and splits it into | ||
// `$namespace` and `$path`. | ||
func SplitKey(key string) (string, string, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could simplify this a bit i think!
parts := strings.SplitN(key, "/", 3)
if len(parts) < 3 || len(parts[0]) > 0 || len(parts[1]) == 0 || len(parts[2]) == 0 {
return "", "", ErrInvalidRecordType
}
return parts[1], parts[2], nil
dno if this matters tho!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I first wrote that function, I chose not to use SplitN
to save on allocations. Basically, I want to make that function as fast as possible so we can call it with impunity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sgtm. impl is strong as stands, then.
validator.go
Outdated
|
||
// ErrBadRecord is returned any time a dht record is found to be | ||
// incorrectly formatted or signed. | ||
var ErrBadRecord = errors.New("bad dht record") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps for purposes of more specific logging, we could separate into
var ErrBadRecord = errors.New("bad dht record: improperly formatted")
var ErrBadSignature = errors.New("bad dht record: improperly signed")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, it looks like ErrBadRecord isn't even used. Validators return different errors depending on what went wrong. I'll just remove that error.
// Validate validates the given record, returning an error if it's | ||
// invalid (e.g., expired, signed by the wrong key, etc.). | ||
Validate(key string, value []byte) error | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Stebalien agreed. this is less a full sort and more a min function. unless there is use for a full priority sorted list of entries, i think this approach is fine.
fa9cc59
to
b3dd0d6
Compare
When generalizing routing, I noticed a couple of issues: