github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/state/protocol/prg/customizers.go (about) 1 package prg 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 "math" 7 ) 8 9 // List of customizers used for different sub-protocol PRGs. 10 // These customizers help instantiate different PRGs from the 11 // same source of randomness. 12 // 13 // Customizers used by the Flow protocol should not be equal or 14 // prefixing each other to guarantee independent PRGs. This 15 // is enforced by test `TestProtocolConstants` in `./prg_test.go` 16 17 var ( 18 // ConsensusLeaderSelection is the customizer for consensus leader selection 19 ConsensusLeaderSelection = customizerFromIndices(0) 20 // VerificationChunkAssignment is the customizer for verification chunk assignment 21 VerificationChunkAssignment = customizerFromIndices(2) 22 // ExecutionEnvironment is the customizer for Flow's transaction execution environment 23 // (used for Cadence `random` function) 24 ExecutionEnvironment = customizerFromIndices(1, 0) 25 // ExecutionRandomSourceHistory is the customizer for Flow's transaction execution environment 26 // (used for the source of randomness history core-contract) 27 ExecutionRandomSourceHistory = customizerFromIndices(1, 1) 28 // 29 // clusterLeaderSelectionPrefix is the prefix used for CollectorClusterLeaderSelection 30 clusterLeaderSelectionPrefix = []uint16{3} 31 ) 32 33 // CollectorClusterLeaderSelection returns the indices for the leader selection for the i-th collector cluster 34 func CollectorClusterLeaderSelection(clusterIndex uint) []byte { 35 if uint(math.MaxUint16) < clusterIndex { 36 // sanity check to guarantee no overflows during type conversion -- this should never happen 37 panic(fmt.Sprintf("input cluster index (%d) exceeds max uint16 value %d", clusterIndex, math.MaxUint16)) 38 } 39 indices := append(clusterLeaderSelectionPrefix, uint16(clusterIndex)) 40 return customizerFromIndices(indices...) 41 } 42 43 // customizerFromIndices converts the input indices into a slice of bytes. 44 // The function has to be injective (no different indices map to the same customizer) 45 // 46 // The output is built as a concatenation of indices, each index is encoded over 2 bytes. 47 func customizerFromIndices(indices ...uint16) []byte { 48 customizerLen := 2 * len(indices) 49 customizer := make([]byte, customizerLen) 50 // concatenate the indices 51 for i, index := range indices { 52 binary.LittleEndian.PutUint16(customizer[2*i:2*i+2], index) 53 } 54 return customizer 55 }