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  }