-
Notifications
You must be signed in to change notification settings - Fork 838
Implement gossip.SetWithBloomFilter #4632
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
Conversation
JonathanOppenheimer
left a comment
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.
Someone else more knowledgeable should also review.
ARR4N
left a comment
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.
No need for me to re-review the requested changes.
| // is later modified. | ||
| salt := b.salt | ||
| return bloomBytes, salt[:] | ||
| func (b *BloomFilter) BloomFilter() (*bloom.Filter, ids.ID) { |
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.
For my understanding: why ids.ID? It seems like an odd overloading of the meaning of a type.
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.
I don't think there was a reason in the old code - I think we just went with hash = ids.ID. It would probably make more sense to make a type alias for salt or just use plain []byte
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.
I returned an array rather than a slice to avoid needing to do the copy.. It could just be [32]byte... We just typically use ids.ID throughout the repo for these... We could probably clean it up later
| } | ||
|
|
||
| // PushGossiperSet exposes whether hashes are still included in a set. | ||
| type PushGossiperSet interface { |
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.
(subjective) I understand (and agree with) the abstraction of the different set types, but their names feel unintuitive to me. Although they're named for how they're used, I think it would make more sense for them to be named for what they do. This, for example, could be a MembershipVerber (perhaps Reporter or Checker).
If you plan on coming back to this code later then I think it's better to just add a TODO so we don't block SAE on this.
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.
I added TODOs
network/p2p/gossip/set.go
Outdated
| // This value should always be at least as large as the number of items that | ||
| // can be iterated over with a call to Iterate. |
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.
Please elaborate on scenarios in which one might expect Iterate to yield fewer items.
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.
I reworded it to say it should be equal... Really it just must not be smaller.
network/p2p/gossip/set_test.go
Outdated
|
|
||
| // Add one to expectedResetCount to account for the initial creation | ||
| // of the bloom filter. | ||
| require.Equal(tt.expectedResetCount+1, testutil.ToFloat64(bs.metrics.ResetCount)) |
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.
| require.Equal(tt.expectedResetCount+1, testutil.ToFloat64(bs.metrics.ResetCount)) | |
| require.Equal(tt.expectedResetCount+1, testutil.ToFloat64(bs.metrics.ResetCount), "number of resets") |
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.
I'm curious on the rationale for these logs in require - isn't this generally self documenting?
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.
I also don't find the logs useful, but adding them doesn't matter to me
network/p2p/gossip/set_test.go
Outdated
| require.Equal(tt.expectedResetCount+1, testutil.ToFloat64(bs.metrics.ResetCount)) | ||
| b, h := bs.BloomFilter() | ||
| for _, expected := range tt.expected { | ||
| require.True(bloom.Contains(b, expected[:], h[:])) |
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.
| require.True(bloom.Contains(b, expected[:], h[:])) | |
| require.Truef(bloom.Contains(b, expected[:], h[:]), "%T.Contains(%#x)", bloom, expected) |
Also, assert is more appropriate for testing set membership, to provide a full picture and avoid whack-a-mole debugging. Just saying 😉
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.
I know people talk about whack-a-mole debugging... I have never experienced it myself
| // that were not included in the filter. | ||
| type PullGossiperSet[T Gossipable] interface { | ||
| // Add adds a value to the set. Returns an error if v was not added. | ||
| Add(v T) 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.
nit: I noticed we use this throughout the PR but did we intend to use v here? Should this be t?
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.
I felt like v for value was pretty normal
network/p2p/gossip/set_test.go
Outdated
|
|
||
| // Add one to expectedResetCount to account for the initial creation | ||
| // of the bloom filter. | ||
| require.Equal(tt.expectedResetCount+1, testutil.ToFloat64(bs.metrics.ResetCount)) |
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.
I'm curious on the rationale for these logs in require - isn't this generally self documenting?
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.
Pull request overview
This PR introduces gossip.BloomSet, a new implementation that simplifies bloom filter management by wrapping a Set implementation and automatically handling bloom filter creation, resetting, and synchronization. This eliminates the need for VM implementations to manually manage bloom filters.
Key changes:
- Adds
BloomSetas a generic wrapper that manages bloom filters for anySetimplementation - Deprecates the existing
BloomFiltertype in favor ofBloomSet - Updates interface definitions to separate concerns between handlers, push gossip, and pull gossip
Reviewed changes
Copilot reviewed 16 out of 17 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| network/p2p/gossip/set.go | Implements new BloomSet wrapper with automatic bloom filter management |
| network/p2p/gossip/set_test.go | Adds comprehensive tests for BloomSet including concurrency testing |
| network/p2p/gossip/gossip.go | Moves Gossipable and Marshaller definitions, adds new interface types for pull/push gossipers |
| network/p2p/gossip/handler.go | Updates to use new HandlerSet interface instead of full Set |
| network/p2p/gossip/bloom.go | Deprecates existing BloomFilter implementation and updates method signatures |
| network/p2p/gossip/gossipable.go | Removes file (definitions moved to gossip.go) |
| network/p2p/gossip/gossip_test.go | Updates tests to use BloomSet and refactors test doubles |
| network/p2p/gossip/bloom_test.go | Updates to use new BloomFilter() method signature |
| vms/platformvm/network/gossip.go | Updates to implement new BloomFilter() method signature |
| vms/avm/network/gossip.go | Updates to implement new BloomFilter() method signature |
| graft/coreth/plugin/evm/eth_gossiper.go | Updates to implement new interfaces and method signature |
| graft/coreth/plugin/evm/atomic/txpool/mempool.go | Updates to implement new interfaces and method signature |
| graft/coreth/plugin/evm/gossip/handler.go | Updates to use new HandlerSet interface |
| graft/coreth/plugin/evm/tx_gossip_test.go | Simplifies test to use new gossip utilities |
| graft/coreth/plugin/evm/atomic/vm/tx_gossip_test.go | Simplifies test to use new gossip utilities |
| go.mod | Updates dependency versions |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| DefaultMinTargetElements = 1000 | ||
| DefaultTargetFalsePositiveProbability = .01 | ||
| DefaultResetFalsePositiveProbability = .05 |
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.
Should we expose these under a single DefaultBloomSetConfig? It seems like it would make discoverability easier
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.
I did it this way so that the defaults can't be changed (As we can't expose a const DefaultBloomSetConfig).
Why this should be merged
Part of #4621
This allows VM implementations an alternative to the
gossip.BloomFilterimplementation. By using this implementation, users do not need to manage a bloom filter on their own.How this works
Provides a generic implementation similar to the implementations in the X-chain and the P-chain.
To speed up development, this PR does not include migrating the existing VMs to this new implementation.
How this was tested
Updated the integration test of the gossip package to utilize the simplified API.
Need to be documented in RELEASES.md?
No.