github.com/koko1123/flow-go-1@v0.29.6/module/signature/signer_indices.go (about)

     1  package signature
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	"github.com/koko1123/flow-go-1/ledger/common/bitutils"
     8  	"github.com/koko1123/flow-go-1/model/flow"
     9  )
    10  
    11  // EncodeSignerToIndicesAndSigType encodes the given stakingSigners and beaconSigners into bit vectors for
    12  // signer indices and sig types.
    13  // PREREQUISITES:
    14  //   - The input `canonicalIdentifiers` must exhaustively list the set of authorized signers in their canonical order.
    15  //   - The inputs `stakingSigners` and `beaconSigners` are treated as sets, i.e. they
    16  //     should not contain any duplicates.
    17  //   - A node can be listed in either `stakingSigners` or `beaconSigners`. A node appearing in both lists
    18  //     constitutes an illegal input.
    19  //   - `stakingSigners` must be a subset of `canonicalIdentifiers`
    20  //   - `beaconSigners` must be a subset of `canonicalIdentifiers`
    21  //
    22  // RETURN VALUES:
    23  //
    24  //   - `signerIndices` is a bit vector. Let signerIndices[i] denote the ith bit of `signerIndices`.
    25  //
    26  //     .                            ┌ 1 if and only if canonicalIdentifiers[i] is in `stakingSigners` or `beaconSigners`
    27  //     .         signerIndices[i] = └ 0 otherwise
    28  //
    29  //     Let `n` be the length of `canonicalIdentifiers`. `signerIndices` contains at least `n` bits, though, we
    30  //     right-pad it with tailing zeros to full bytes.
    31  //
    32  //   - `sigTypes` is a bit vector. Let sigTypes[i] denote the ith bit of `sigTypes`
    33  //     .                       ┌ 1 if and only if the ith signer is in `beaconSigners`
    34  //     .         sigTypes[i] = └ 0 if and only if the ith signer is in `stakingSigners`
    35  //     (Per prerequisite, we require that no signer is listed in both `beaconSigners` and `stakingSigners`)
    36  //
    37  // Example:
    38  // As an example consider the case where we have a committee C of 10 nodes in canonical oder
    39  //
    40  //	C = [A,B,C,D,E,F,G,H,I,J]
    41  //
    42  // where nodes [B,F] are stakingSigners and beaconSigners are [C,E,G,I,J].
    43  //  1. First return parameter: `signerIndices`
    44  //     - We start with a bit vector v that has |C| number of bits
    45  //     - If a node contributed either as staking signer or beacon signer,
    46  //     we set the respective bit to 1:
    47  //     .         [A,B,C,D,E,F,G,H,I,J]
    48  //     .            ↓ ↓   ↓ ↓ ↓   ↓ ↓
    49  //     .          0,1,1,0,1,1,1,0,1,1
    50  //     - Lastly, right-pad the resulting bit vector with 0 to full bytes. We have 10 committee members,
    51  //     so we pad to 2 bytes:
    52  //     .          01101110 11000000
    53  //  2. second return parameter: `sigTypes`
    54  //     - Here, we restrict our focus on the signers, which we encoded in the previous step.
    55  //     In our example, nodes [B,C,E,F,G,I,J] signed in canonical order. This is exactly the same order,
    56  //     as we have represented the signer in the last step.
    57  //     - For these 5 nodes in their canonical order, we encode each node's signature type as
    58  //     .        bit-value 1: node was in beaconSigners
    59  //     .        bit-value 0: node was in stakingSigners
    60  //     This results in the bit vector
    61  //     .            [B,C,E,F,G,I,J]
    62  //     .             ↓ ↓ ↓ ↓ ↓ ↓ ↓
    63  //     .             0,1,0,1,1,1,1
    64  //     - Again, we right-pad with zeros to full bytes, As we only had 7 signers, the sigType slice is 1byte long
    65  //     .            01011110
    66  //
    67  // the signer indices is prefixed with a checksum of the canonicalIdentifiers, which can be used by the decoder
    68  // to verify if the decoder is using the same canonicalIdentifiers as the encoder to decode the signer indices.
    69  //
    70  // ERROR RETURNS
    71  // During normal operations, no error returns are expected. This is because encoding signer sets is generally
    72  // part of the node's internal work to generate messages. Hence, the inputs to this method come from other
    73  // trusted components within the node. Therefore, any illegal input is treated as a symptom of an internal bug.
    74  func EncodeSignerToIndicesAndSigType(
    75  	canonicalIdentifiers flow.IdentifierList,
    76  	stakingSigners flow.IdentifierList,
    77  	beaconSigners flow.IdentifierList,
    78  ) (signerIndices []byte, sigTypes []byte, err error) {
    79  	stakingSignersLookup := stakingSigners.Lookup()
    80  	if len(stakingSignersLookup) != len(stakingSigners) {
    81  		return nil, nil, fmt.Errorf("duplicated entries in staking signers %v", stakingSignersLookup)
    82  	}
    83  	beaconSignersLookup := beaconSigners.Lookup()
    84  	if len(beaconSignersLookup) != len(beaconSigners) {
    85  		return nil, nil, fmt.Errorf("duplicated entries in beacon signers %v", stakingSignersLookup)
    86  	}
    87  
    88  	// encode Identifiers to `signerIndices`; and for each signer, encode the signature type in `sigTypes`
    89  	signerIndices = bitutils.MakeBitVector(len(canonicalIdentifiers))
    90  	sigTypes = bitutils.MakeBitVector(len(stakingSigners) + len(beaconSigners))
    91  	signerCounter := 0
    92  	for canonicalIdx, member := range canonicalIdentifiers {
    93  		if _, ok := stakingSignersLookup[member]; ok {
    94  			bitutils.SetBit(signerIndices, canonicalIdx)
    95  			// The default value for sigTypes is bit zero, which corresponds to a staking sig.
    96  			// Hence, we don't have to change anything here.
    97  			delete(stakingSignersLookup, member)
    98  			signerCounter++
    99  			continue
   100  		}
   101  		if _, ok := beaconSignersLookup[member]; ok {
   102  			bitutils.SetBit(signerIndices, canonicalIdx)
   103  			bitutils.SetBit(sigTypes, signerCounter)
   104  			delete(beaconSignersLookup, member)
   105  			signerCounter++
   106  			continue
   107  		}
   108  	}
   109  
   110  	if len(stakingSignersLookup) > 0 {
   111  		return nil, nil, fmt.Errorf("unknown staking signers %v", stakingSignersLookup)
   112  	}
   113  	if len(beaconSignersLookup) > 0 {
   114  		return nil, nil, fmt.Errorf("unknown or duplicated beacon signers %v", beaconSignersLookup)
   115  	}
   116  
   117  	prefixed := PrefixCheckSum(canonicalIdentifiers, signerIndices)
   118  
   119  	return prefixed, sigTypes, nil
   120  }
   121  
   122  // DecodeSigTypeToStakingAndBeaconSigners decodes the bit-vector `sigType` to the set of
   123  // staking signer identities (`stakingSigners`) and the set of beacon signer identities (`beaconSigners`).
   124  // Prerequisite:
   125  //   - The input `signers` must be the set of signers in their canonical order.
   126  //
   127  // Expected Error returns during normal operations:
   128  //   - signature.IsInvalidSigTypesError if the given `sigType` does not encode a valid sequence of signature types
   129  func DecodeSigTypeToStakingAndBeaconSigners(
   130  	signers flow.IdentityList,
   131  	sigType []byte,
   132  ) (flow.IdentityList, flow.IdentityList, error) {
   133  	numberSigners := len(signers)
   134  	if err := validPadding(sigType, numberSigners); err != nil {
   135  		if errors.Is(err, ErrIncompatibleBitVectorLength) || errors.Is(err, ErrIllegallyPaddedBitVector) {
   136  			return nil, nil, NewInvalidSigTypesErrorf("invalid padding of sigTypes: %w", err)
   137  		}
   138  		return nil, nil, fmt.Errorf("unexpected exception while checking padding of sigTypes: %w", err)
   139  	}
   140  
   141  	// decode bits to Identities
   142  	stakingSigners := make(flow.IdentityList, 0, numberSigners)
   143  	beaconSigners := make(flow.IdentityList, 0, numberSigners)
   144  	for i, signer := range signers {
   145  		if bitutils.ReadBit(sigType, i) == 0 {
   146  			stakingSigners = append(stakingSigners, signer)
   147  		} else {
   148  			beaconSigners = append(beaconSigners, signer)
   149  		}
   150  	}
   151  	return stakingSigners, beaconSigners, nil
   152  }
   153  
   154  // EncodeSignersToIndices encodes the given signerIDs into compacted bit vector.
   155  // PREREQUISITES:
   156  //   - The input `canonicalIdentifiers` must exhaustively list the set of authorized signers in their canonical order.
   157  //   - The input `signerIDs` represents a set, i.e. it should not contain any duplicates.
   158  //   - `signerIDs` must be a subset of `canonicalIdentifiers`
   159  //
   160  // RETURN VALUE:
   161  //   - `signerIndices` is a bit vector. Let signerIndices[i] denote the ith bit of `signerIndices`.
   162  //     .                             ┌ 1 if and only if canonicalIdentifiers[i] is in `signerIDs`
   163  //     .          signerIndices[i] = └ 0 otherwise
   164  //     Let `n` be the length of `canonicalIdentifiers`. `signerIndices` contains at least `n` bits, though, we
   165  //     right-pad it with tailing zeros to full bytes.
   166  //
   167  // Example:
   168  // As an example consider the case where we have a committee C of 10 nodes in canonical oder
   169  //
   170  //	C = [A,B,C,D,E,F,G,H,I,J]
   171  //
   172  // where nodes [B,F] are stakingSigners, and beaconSigners are [C,E,G,I,J].
   173  //  1. First return parameter: QC.signerIndices
   174  //     - We start with a bit vector v that has |C| number of bits
   175  //     - If a node contributed either as staking signer or beacon signer,
   176  //     we set the respective bit to 1:
   177  //     .          [A,B,C,D,E,F,G,H,I,J]
   178  //     .             ↓ ↓   ↓ ↓ ↓   ↓ ↓
   179  //     .           0,1,1,0,1,1,1,0,1,1
   180  //     - Lastly, right-pad the resulting bit vector with 0 to full bytes. We have 10 committee members,
   181  //     so we pad to 2 bytes:
   182  //     .           01101110 11000000
   183  //
   184  // ERROR RETURNS
   185  // During normal operations, no error returns are expected. This is because encoding signer sets is generally
   186  // part of the node's internal work to generate messages. Hence, the inputs to this method come from other
   187  // trusted components within the node. Therefore, any illegal input is treated as a symptom of an internal bug.
   188  // canonicalIdentifiers represents all identities who are eligible to sign the given resource. It excludes
   189  // identities who are ineligible to sign the given resource. For example, canonicalIdentifiers in the context
   190  // of a cluster consensus quorum certificate would include authorized members of the cluster and
   191  // exclude ejected members of the cluster, or unejected collection nodes from a different cluster.
   192  // the signer indices is prefixed with a checksum of the canonicalIdentifiers, which can be used by the decoder
   193  // to verify if the decoder is using the same canonicalIdentifiers as the encoder to decode the signer indices.
   194  func EncodeSignersToIndices(
   195  	canonicalIdentifiers flow.IdentifierList,
   196  	signerIDs flow.IdentifierList,
   197  ) (signerIndices []byte, err error) {
   198  	signersLookup := signerIDs.Lookup()
   199  	if len(signersLookup) != len(signerIDs) {
   200  		return nil, fmt.Errorf("duplicated entries in signerIDs %v", signerIDs)
   201  	}
   202  
   203  	// encode Identifiers to bits
   204  	signerIndices = bitutils.MakeBitVector(len(canonicalIdentifiers))
   205  	for canonicalIdx, member := range canonicalIdentifiers {
   206  		if _, ok := signersLookup[member]; ok {
   207  			bitutils.SetBit(signerIndices, canonicalIdx)
   208  			delete(signersLookup, member)
   209  		}
   210  	}
   211  	if len(signersLookup) > 0 {
   212  		return nil, fmt.Errorf("unknown signers IDs in the keys of %v", signersLookup)
   213  	}
   214  
   215  	prefixed := PrefixCheckSum(canonicalIdentifiers, signerIndices)
   216  
   217  	return prefixed, nil
   218  }
   219  
   220  // DecodeSignerIndicesToIdentifiers decodes the given compacted bit vector into signerIDs
   221  // Prerequisite:
   222  //   - The input `canonicalIdentifiers` must exhaustively list the set of authorized signers in their canonical order.
   223  //
   224  // Expected Error returns during normal operations:
   225  // * signature.InvalidSignerIndicesError if the given index vector `prefixed` does not encode a valid set of signers
   226  func DecodeSignerIndicesToIdentifiers(
   227  	canonicalIdentifiers flow.IdentifierList,
   228  	prefixed []byte,
   229  ) (flow.IdentifierList, error) {
   230  	indices, err := decodeSignerIndices(canonicalIdentifiers, prefixed)
   231  	if err != nil {
   232  		return nil, err
   233  	}
   234  
   235  	signerIDs := make(flow.IdentifierList, 0, len(indices))
   236  	for _, index := range indices {
   237  		signerIDs = append(signerIDs, canonicalIdentifiers[index])
   238  	}
   239  	return signerIDs, nil
   240  }
   241  
   242  func decodeSignerIndices(
   243  	canonicalIdentifiers flow.IdentifierList,
   244  	prefixed []byte,
   245  ) ([]int, error) {
   246  	// the prefixed contains the checksum of the canonicalIdentifiers that the signerIndices
   247  	// creator saw.
   248  	// extract the checksum and compare with the canonicalIdentifiers to see if both
   249  	// the signerIndices creator and validator see the same list.
   250  	signerIndices, err := CompareAndExtract(canonicalIdentifiers, prefixed)
   251  	if err != nil {
   252  		if errors.Is(err, ErrInvalidChecksum) {
   253  			return nil, NewInvalidSignerIndicesErrorf("signer indices' checkum is invalid: %w", err)
   254  		}
   255  		return nil, fmt.Errorf("unexpected exception while checking signer indices: %w", err)
   256  	}
   257  
   258  	numberCanonicalNodes := len(canonicalIdentifiers)
   259  	err = validPadding(signerIndices, numberCanonicalNodes)
   260  	if err != nil {
   261  		if errors.Is(err, ErrIncompatibleBitVectorLength) || errors.Is(err, ErrIllegallyPaddedBitVector) {
   262  			return nil, NewInvalidSignerIndicesErrorf("invalid padding of signerIndices: %w", err)
   263  		}
   264  		return nil, fmt.Errorf("unexpected exception while checking padding of signer indices: %w", err)
   265  	}
   266  
   267  	// decode bits to Identifiers
   268  	indices := make([]int, 0, numberCanonicalNodes)
   269  	for i := 0; i < numberCanonicalNodes; i++ {
   270  		if bitutils.ReadBit(signerIndices, i) == 1 {
   271  			indices = append(indices, i)
   272  		}
   273  	}
   274  	return indices, nil
   275  }
   276  
   277  // DecodeSignerIndicesToIdentities decodes the given compacted bit vector into node Identities.
   278  // Prerequisite:
   279  //   - The input `canonicalIdentifiers` must exhaustively list the set of authorized signers in their canonical order.
   280  //
   281  // Expected Error returns during normal operations:
   282  // * signature.InvalidSignerIndicesError if the given index vector `prefixed` does not encode a valid set of signers
   283  func DecodeSignerIndicesToIdentities(
   284  	canonicalIdentities flow.IdentityList,
   285  	prefixed []byte,
   286  ) (flow.IdentityList, error) {
   287  	indices, err := decodeSignerIndices(canonicalIdentities.NodeIDs(), prefixed)
   288  	if err != nil {
   289  		return nil, err
   290  	}
   291  
   292  	signers := make(flow.IdentityList, 0, len(indices))
   293  	for _, index := range indices {
   294  		signers = append(signers, canonicalIdentities[index])
   295  	}
   296  	return signers, nil
   297  }
   298  
   299  // validPadding verifies that `bitVector` satisfies the following criteria
   300  //  1. The `bitVector`'s length [in bytes], must be the _minimal_ possible length such that it can hold
   301  //     `numUsedBits` number of bits. Otherwise, we return an `ErrIncompatibleBitVectorLength`.
   302  //  2. If `numUsedBits` is _not_ an integer-multiple of 8, `bitVector` is padded with tailing bits. Per
   303  //     convention, these bits must be zero. Otherwise, we return an `ErrIllegallyPaddedBitVector`.
   304  //
   305  // Expected Error returns during normal operations:
   306  //   - ErrIncompatibleBitVectorLength if the vector has the wrong length
   307  //   - ErrIllegallyPaddedBitVector if the vector is padded with bits other than 0
   308  func validPadding(bitVector []byte, numUsedBits int) error {
   309  	// Verify condition 1:
   310  	l := len(bitVector)
   311  	if l != bitutils.MinimalByteSliceLength(numUsedBits) {
   312  		return fmt.Errorf("the bit vector contains a payload of %d used bits, so it should have %d bytes but has %d bytes: %w",
   313  			numUsedBits, bitutils.MinimalByteSliceLength(numUsedBits), l, ErrIncompatibleBitVectorLength)
   314  	}
   315  	// Condition 1 implies that the number of padded bits must be strictly smaller than 8. Otherwise, the vector
   316  	// could have fewer bytes and still have enough room to store `numUsedBits`.
   317  
   318  	// Verify condition 2, i.e. that all padded bits are all 0:
   319  	// * As `bitVector` passed check 1, all padded bits are located in `bitVector`s _last byte_.
   320  	// * Let `lastByte` be the last byte of `bitVector`. The leading bits, specifically `numUsedBits & 7`,
   321  	//   belong to the used payload, which could have non-zero values. We remove these using left-bit-shifts.
   322  	//   The result contains exactly all padded bits (plus some auxiliary 0-bits included by the bit-shift
   323  	//   operator). Hence, condition 2 is satisfied if and only if the result is identical to zero.
   324  	// Note that this implementation is much more efficient than individually checking the padded bits, as we check all
   325  	// padded bits at once; furthermore, we only use multiplication, subtraction, shift, which are fast.
   326  	if numUsedBits&7 == 0 { // if numUsedBits is multiple of 8, then there are no padding bits to check
   327  		return nil
   328  	}
   329  	// the above check has ensured that lastByte does exist (l==0 is excluded)
   330  	lastByte := bitVector[l-1]
   331  	if (lastByte << (numUsedBits & 7)) != 0 { // shift by numUsedBits % 8
   332  		return fmt.Errorf("some padded bits are not zero with %d used bits (bitVector: %x): %w", numUsedBits, bitVector, ErrIllegallyPaddedBitVector)
   333  	}
   334  
   335  	return nil
   336  }