Need a record validator interface that handles equality
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 6.9k
- Forks
- 1.3k
- Avg merge
- 13d 21h
- Merged PRs (30d)
- 1
Description
The libp2p record validator interface has the function Select(key string, values [][]byte) (int, error)
Unfortunately, there's no way to figure out if given two records are the same using just the interface if we rely on the contract specified alone.
Some failed examples:
bytes.Equal(record1, record2)as done in go-libp2p-pubsub-router and go-ipns- This fails because certain serialization formats (e.g. Protocol Buffers) do not guarantee that the same record will serialize the same way twice.
Select(key, {record1, record2}) == Select(key, {record2, record1} == 0- Unfortunately, the only relevant specification on the interface is that we return the "best" record and that it be "stable". While stable is generally pretty well defined to mean that calling the same function with exactly the same inputs will produce the same results, "best" has no real restrictions especially when it comes to two equal value.
- The public key record just returns 0 for all records which might convince us that
record1 == record2even though they're totally different - I might choose to use
bytes.Equalto return the "better" of two equal records internally even though they're actually equal.
- The public key record just returns 0 for all records which might convince us that
- Unfortunately, the only relevant specification on the interface is that we return the "best" record and that it be "stable". While stable is generally pretty well defined to mean that calling the same function with exactly the same inputs will produce the same results, "best" has no real restrictions especially when it comes to two equal value.
Thankfully there are a number of ways to fix this of which a few are below:
- Add a
SelectMany(key string, values [][]byte)that returns an array of equal values (either [][]byte or []int) - Add an
Equals(key string, record1 []byte, record2 []byte)that will help in a more limited use case - Specify that if multiple values are equal we must return the index of the 1st value
Options that involve changing the interface are more painful if there are lots of consumers of the interface. However, we could work around this by creating a new interface that with a struct that wraps the old one into a new one, or by utilizing go's ability to specify interfaces where they're used instead of globally.
Options that involve changing the contract on the interface can be easier. However, it may lead to undetected problems as people who think they've implemented the interface turn out to have not implemented it properly.
@raulk @Stebalien what do you think? This may lead to wasted bandwidth in go-libp2p-pubsub-router unless we address this.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the validator interface in validator.go and compare its Select contract with the usages in go-libp2p-pubsub-router's pubsub.go and go-ipns's record.go. Review the proposed equality approaches and determine which interface or contract change maintainers accept; done means the equality behavior is specified and affected consumers are addressed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- networking
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100