Skip to content

Commit

Permalink
fix shuffled sequence
Browse files Browse the repository at this point in the history
  • Loading branch information
pantrif committed Nov 19, 2024
1 parent 621e1b8 commit 8a2fb36
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 14 deletions.
9 changes: 2 additions & 7 deletions internal/common/shuffling.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,8 @@ import (
var serializer = serialization.NewSerializer(codec.NewJamCodec())

// DeterministicShuffle performs a deterministic shuffle of the sequence s based on the hash h (appendix F)
func DeterministicShuffle(length uint32, h crypto.Hash) ([]uint32, error) {
s := make([]uint32, length)
for i := uint32(0); i < length; i++ {
s[i] = i
}

r, err := generateRandomNumbers(h, length)
func DeterministicShuffle(s []uint32, h crypto.Hash) ([]uint32, error) {
r, err := generateRandomNumbers(h, uint32(len(s)))
if err != nil {
return nil, err
}
Expand Down
12 changes: 10 additions & 2 deletions internal/statetransition/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -726,15 +726,23 @@ func RotateSequence(sequence []uint32, n uint32) []uint32 {
// PermuteAssignments generates the core assignments for validators.
// Implements Equation (134 v0.4.5): P(e, t) ≡ R(F([⌊C ⋅ i/V⌋ ∣i ∈ NV], e), ⌊t mod E/R⌋)
func PermuteAssignments(entropy crypto.Hash, timeslot jamtime.Timeslot) ([]uint32, error) {
shuffledSequence, err := common.DeterministicShuffle(uint32(common.NumberOfValidators), entropy)
// [⌊C ⋅ i/V⌋ ∣i ∈ NV]
coreIndices := make([]uint32, common.NumberOfValidators)
for i := uint32(0); i < common.NumberOfValidators; i++ {
coreIndices[i] = (uint32(common.TotalNumberOfCores) * i) / common.NumberOfValidators
}

// F([⌊C ⋅ i/V⌋ ∣i ∈ NV], e)
shuffledSequence, err := common.DeterministicShuffle(coreIndices, entropy)
if err != nil {
return nil, err
}

// Calculate rotation amount: ⌊(t mod E) / R⌋
// ⌊(t mod E) / R⌋
timeslotModEpoch := timeslot % jamtime.TimeslotsPerEpoch
rotationAmount := uint32(timeslotModEpoch / common.ValidatorRotationPeriod)

// R(F([⌊C ⋅ i/V⌋ ∣i ∈ NV], e), ⌊t mod E/R⌋)
rotatedSequence := RotateSequence(shuffledSequence, rotationAmount)

return rotatedSequence, nil
Expand Down
8 changes: 4 additions & 4 deletions internal/statetransition/state_transition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -581,10 +581,10 @@ func TestCalculateNewCoreAssignments(t *testing.T) {
entropyPool := state.EntropyPool{}
// Hardcoded entropy that assigns first 2 validators to the same core
entropyPool[2] = crypto.Hash{
0, 0, 0, 0, 0, 0, 1, 155,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
205, 167, 205, 130, 4, 58, 89, 170,
187, 59, 155, 75, 28, 244, 251, 244,
38, 86, 243, 94, 236, 132, 54, 199,
105, 143, 117, 14, 216, 45, 68, 156,
}

// Compute core assignments based on the suitable entropy and timeslot
Expand Down
7 changes: 6 additions & 1 deletion tests/integration/shuffling_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ func TestShuffleVectors(t *testing.T) {
entropyBytes, err := hex.DecodeString(testCase.Entropy)
require.NoError(t, err)

shuffledSequence, err := common.DeterministicShuffle(testCase.Input, crypto.Hash(entropyBytes))
ss := make([]uint32, testCase.Input)
for i := uint32(0); i < testCase.Input; i++ {
ss[i] = i
}

shuffledSequence, err := common.DeterministicShuffle(ss, crypto.Hash(entropyBytes))
require.NoError(t, err)

assert.Equal(t, testCase.ExpectedOutput, shuffledSequence)
Expand Down

0 comments on commit 8a2fb36

Please sign in to comment.