-
Notifications
You must be signed in to change notification settings - Fork 511
feat: Change sampling algorithm to use feistel permutations #15938
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
setOverrideValue(sampledIndices[i], 0); | ||
} | ||
// Use a Feistel network to create a permutation of [0, _indexCount) | ||
uint256 permutedIndex = feistelPermute(_index, _indexCount, _seed); |
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.
Seems like we should be using the do/while structure here that's done in the batch function instead of calling feistelPermute
and doing redundant setup.
} | ||
|
||
function testConstantTimeNoDuplicates(uint8 _committeeSize, uint16 _indexCount, uint256 _seed) public { | ||
vm.assume(_committeeSize <= _indexCount); |
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.
bound
would be better here.
assertEq(sampler.computeSampleIndex(_index, 0, _seed), 0); | ||
} | ||
|
||
function testConstantTimeCommitteeMember() public { |
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.
test name is a little misleading I think?
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 like what the test is doing though!
function testConstantTimeNoDuplicates(uint8 _committeeSize, uint16 _indexCount, uint256 _seed) public { | ||
vm.assume(_committeeSize <= _indexCount); | ||
vm.assume(_committeeSize > 0 && _committeeSize <= 100); // Reasonable bounds for testing | ||
vm.assume(_indexCount > 0 && _indexCount <= 1000); |
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 think the index count should be closer to 20000 if it doesn't make it too slow.
uint256 validatorSetSize = StakingLib.getAttesterCountAtTime(Timestamp.wrap(ts)); | ||
uint256 targetCommitteeSize = store.targetCommitteeSize; | ||
|
||
if (targetCommitteeSize == 0 || validatorSetSize < targetCommitteeSize) { |
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.
Hm. This is actually a breaking change. Currently nodes expect getProposer/getCommittee to revert if the current set size is not large enough.
Unless we have a reason to change it, I think we should keep the current behavior.
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.
Nice! Curious how you prompted claude to this? I have some minor nits in the tests, an optimization, and a bigger one around reverting when the validator set is not large enough.
I asked it to look into SampleLib, and figure out a way to compute the sampling index of a single committee member without having to recompute all others. It started by keeping the same algorithm, but exiting early when it got to the requested index, so I prompted it to do it in constant time. Then it suggested feistel, and went all in. I was pleasantly surprised. |
Closing in favor of sending signers in calldata as discussed |
Feistel permutations remove the need for auxiliary storage for tracking replacements, and most importantly, allow us to compute a given index permutation in constant time, which allows us to get the proposer for a given committee without having to compute all indices.
Props to Claude for the idea and implementation.
Builds on #15813
Median propose cost is
306000
.