github.com/onflow/flow-go@v0.33.17/model/convert/service_event.go (about)

     1  package convert
     2  
     3  import (
     4  	"encoding/hex"
     5  	"fmt"
     6  
     7  	"github.com/coreos/go-semver/semver"
     8  	"github.com/onflow/cadence"
     9  	"github.com/onflow/cadence/encoding/ccf"
    10  
    11  	"github.com/onflow/flow-go/crypto"
    12  	"github.com/onflow/flow-go/fvm/systemcontracts"
    13  	"github.com/onflow/flow-go/model/flow"
    14  	"github.com/onflow/flow-go/model/flow/assignment"
    15  )
    16  
    17  // ServiceEvent converts a service event encoded as the generic flow.Event
    18  // type to a flow.ServiceEvent type for use within protocol software and protocol
    19  // state. This acts as the conversion from the Cadence type to the flow-go type.
    20  func ServiceEvent(chainID flow.ChainID, event flow.Event) (*flow.ServiceEvent, error) {
    21  
    22  	events := systemcontracts.ServiceEventsForChain(chainID)
    23  
    24  	// depending on type of service event construct Go type
    25  	switch event.Type {
    26  	case events.EpochSetup.EventType():
    27  		return convertServiceEventEpochSetup(event)
    28  	case events.EpochCommit.EventType():
    29  		return convertServiceEventEpochCommit(event)
    30  	case events.VersionBeacon.EventType():
    31  		return convertServiceEventVersionBeacon(event)
    32  	default:
    33  		return nil, fmt.Errorf("invalid event type: %s", event.Type)
    34  	}
    35  }
    36  
    37  // convertServiceEventEpochSetup converts a service event encoded as the generic
    38  // flow.Event type to a ServiceEvent type for an EpochSetup event
    39  func convertServiceEventEpochSetup(event flow.Event) (*flow.ServiceEvent, error) {
    40  
    41  	// decode bytes using ccf
    42  	payload, err := ccf.Decode(nil, event.Payload)
    43  	if err != nil {
    44  		return nil, fmt.Errorf("could not unmarshal event payload: %w", err)
    45  	}
    46  
    47  	// NOTE: variable names prefixed with cdc represent cadence types
    48  	cdcEvent, ok := payload.(cadence.Event)
    49  	if !ok {
    50  		return nil, invalidCadenceTypeError("payload", payload, cadence.Event{})
    51  	}
    52  
    53  	const expectedFieldCount = 9
    54  	if len(cdcEvent.Fields) < expectedFieldCount {
    55  		return nil, fmt.Errorf(
    56  			"insufficient fields in EpochSetup event (%d < %d)",
    57  			len(cdcEvent.Fields),
    58  			expectedFieldCount,
    59  		)
    60  	}
    61  
    62  	if cdcEvent.Type() == nil {
    63  		return nil, fmt.Errorf("EpochSetup event doesn't have type")
    64  	}
    65  
    66  	// parse EpochSetup event
    67  
    68  	var counter cadence.UInt64
    69  	var firstView cadence.UInt64
    70  	var finalView cadence.UInt64
    71  	var randomSrcHex cadence.String
    72  	var dkgPhase1FinalView cadence.UInt64
    73  	var dkgPhase2FinalView cadence.UInt64
    74  	var dkgPhase3FinalView cadence.UInt64
    75  	var cdcClusters cadence.Array
    76  	var cdcParticipants cadence.Array
    77  	var foundFieldCount int
    78  
    79  	evt := cdcEvent.Type().(*cadence.EventType)
    80  
    81  	for i, f := range evt.Fields {
    82  		switch f.Identifier {
    83  		case "counter":
    84  			foundFieldCount++
    85  			counter, ok = cdcEvent.Fields[i].(cadence.UInt64)
    86  			if !ok {
    87  				return nil, invalidCadenceTypeError(
    88  					"counter",
    89  					cdcEvent.Fields[i],
    90  					cadence.UInt64(0),
    91  				)
    92  			}
    93  
    94  		case "nodeInfo":
    95  			foundFieldCount++
    96  			cdcParticipants, ok = cdcEvent.Fields[i].(cadence.Array)
    97  			if !ok {
    98  				return nil, invalidCadenceTypeError(
    99  					"participants",
   100  					cdcEvent.Fields[i],
   101  					cadence.Array{},
   102  				)
   103  			}
   104  
   105  		case "firstView":
   106  			foundFieldCount++
   107  			firstView, ok = cdcEvent.Fields[i].(cadence.UInt64)
   108  			if !ok {
   109  				return nil, invalidCadenceTypeError(
   110  					"firstView",
   111  					cdcEvent.Fields[i],
   112  					cadence.UInt64(0),
   113  				)
   114  			}
   115  
   116  		case "finalView":
   117  			foundFieldCount++
   118  			finalView, ok = cdcEvent.Fields[i].(cadence.UInt64)
   119  			if !ok {
   120  				return nil, invalidCadenceTypeError(
   121  					"finalView",
   122  					cdcEvent.Fields[i],
   123  					cadence.UInt64(0),
   124  				)
   125  			}
   126  
   127  		case "collectorClusters":
   128  			foundFieldCount++
   129  			cdcClusters, ok = cdcEvent.Fields[i].(cadence.Array)
   130  			if !ok {
   131  				return nil, invalidCadenceTypeError(
   132  					"clusters",
   133  					cdcEvent.Fields[i],
   134  					cadence.Array{},
   135  				)
   136  			}
   137  
   138  		case "randomSource":
   139  			foundFieldCount++
   140  			randomSrcHex, ok = cdcEvent.Fields[i].(cadence.String)
   141  			if !ok {
   142  				return nil, invalidCadenceTypeError(
   143  					"randomSource",
   144  					cdcEvent.Fields[i],
   145  					cadence.String(""),
   146  				)
   147  			}
   148  
   149  		case "DKGPhase1FinalView":
   150  			foundFieldCount++
   151  			dkgPhase1FinalView, ok = cdcEvent.Fields[i].(cadence.UInt64)
   152  			if !ok {
   153  				return nil, invalidCadenceTypeError(
   154  					"dkgPhase1FinalView",
   155  					cdcEvent.Fields[i],
   156  					cadence.UInt64(0),
   157  				)
   158  			}
   159  
   160  		case "DKGPhase2FinalView":
   161  			foundFieldCount++
   162  			dkgPhase2FinalView, ok = cdcEvent.Fields[i].(cadence.UInt64)
   163  			if !ok {
   164  				return nil, invalidCadenceTypeError(
   165  					"dkgPhase2FinalView",
   166  					cdcEvent.Fields[i],
   167  					cadence.UInt64(0),
   168  				)
   169  			}
   170  
   171  		case "DKGPhase3FinalView":
   172  			foundFieldCount++
   173  			dkgPhase3FinalView, ok = cdcEvent.Fields[i].(cadence.UInt64)
   174  			if !ok {
   175  				return nil, invalidCadenceTypeError(
   176  					"dkgPhase3FinalView",
   177  					cdcEvent.Fields[i],
   178  					cadence.UInt64(0),
   179  				)
   180  			}
   181  		}
   182  	}
   183  
   184  	if foundFieldCount != expectedFieldCount {
   185  		return nil, fmt.Errorf(
   186  			"EpochSetup event required fields not found (%d != %d)",
   187  			foundFieldCount,
   188  			expectedFieldCount,
   189  		)
   190  	}
   191  
   192  	setup := &flow.EpochSetup{
   193  		Counter:            uint64(counter),
   194  		FirstView:          uint64(firstView),
   195  		FinalView:          uint64(finalView),
   196  		DKGPhase1FinalView: uint64(dkgPhase1FinalView),
   197  		DKGPhase2FinalView: uint64(dkgPhase2FinalView),
   198  		DKGPhase3FinalView: uint64(dkgPhase3FinalView),
   199  	}
   200  
   201  	// random source from the event must be a hex string
   202  	// containing exactly 128 bits (equivalent to 16 bytes or 32 hex characters)
   203  	setup.RandomSource, err = hex.DecodeString(string(randomSrcHex))
   204  	if err != nil {
   205  		return nil, fmt.Errorf(
   206  			"could not decode random source hex (%v): %w",
   207  			randomSrcHex,
   208  			err,
   209  		)
   210  	}
   211  
   212  	if len(setup.RandomSource) != flow.EpochSetupRandomSourceLength {
   213  		return nil, fmt.Errorf(
   214  			"random source in epoch setup event must be of (%d) bytes, got (%d)",
   215  			flow.EpochSetupRandomSourceLength,
   216  			len(setup.RandomSource),
   217  		)
   218  	}
   219  
   220  	// parse cluster assignments
   221  	setup.Assignments, err = convertClusterAssignments(cdcClusters.Values)
   222  	if err != nil {
   223  		return nil, fmt.Errorf("could not convert cluster assignments: %w", err)
   224  	}
   225  
   226  	// parse epoch participants
   227  	setup.Participants, err = convertParticipants(cdcParticipants.Values)
   228  	if err != nil {
   229  		return nil, fmt.Errorf("could not convert participants: %w", err)
   230  	}
   231  
   232  	// construct the service event
   233  	serviceEvent := &flow.ServiceEvent{
   234  		Type:  flow.ServiceEventSetup,
   235  		Event: setup,
   236  	}
   237  
   238  	return serviceEvent, nil
   239  }
   240  
   241  // convertServiceEventEpochCommit converts a service event encoded as the generic
   242  // flow.Event type to a ServiceEvent type for an EpochCommit event
   243  func convertServiceEventEpochCommit(event flow.Event) (*flow.ServiceEvent, error) {
   244  
   245  	// decode bytes using ccf
   246  	payload, err := ccf.Decode(nil, event.Payload)
   247  	if err != nil {
   248  		return nil, fmt.Errorf("could not unmarshal event payload: %w", err)
   249  	}
   250  
   251  	cdcEvent, ok := payload.(cadence.Event)
   252  	if !ok {
   253  		return nil, invalidCadenceTypeError("payload", payload, cadence.Event{})
   254  	}
   255  
   256  	const expectedFieldCount = 3
   257  	if len(cdcEvent.Fields) < expectedFieldCount {
   258  		return nil, fmt.Errorf(
   259  			"insufficient fields in EpochCommit event (%d < %d)",
   260  			len(cdcEvent.Fields),
   261  			expectedFieldCount,
   262  		)
   263  	}
   264  
   265  	if cdcEvent.Type() == nil {
   266  		return nil, fmt.Errorf("EpochCommit event doesn't have type")
   267  	}
   268  
   269  	// Extract EpochCommit event fields
   270  	var counter cadence.UInt64
   271  	var cdcClusterQCVotes cadence.Array
   272  	var cdcDKGKeys cadence.Array
   273  	var foundFieldCount int
   274  
   275  	evt := cdcEvent.Type().(*cadence.EventType)
   276  
   277  	for i, f := range evt.Fields {
   278  		switch f.Identifier {
   279  		case "counter":
   280  			foundFieldCount++
   281  			counter, ok = cdcEvent.Fields[i].(cadence.UInt64)
   282  			if !ok {
   283  				return nil, invalidCadenceTypeError(
   284  					"counter",
   285  					cdcEvent.Fields[i],
   286  					cadence.UInt64(0),
   287  				)
   288  			}
   289  
   290  		case "clusterQCs":
   291  			foundFieldCount++
   292  			cdcClusterQCVotes, ok = cdcEvent.Fields[i].(cadence.Array)
   293  			if !ok {
   294  				return nil, invalidCadenceTypeError(
   295  					"clusterQCs",
   296  					cdcEvent.Fields[i],
   297  					cadence.Array{},
   298  				)
   299  			}
   300  
   301  		case "dkgPubKeys":
   302  			foundFieldCount++
   303  			cdcDKGKeys, ok = cdcEvent.Fields[i].(cadence.Array)
   304  			if !ok {
   305  				return nil, invalidCadenceTypeError(
   306  					"dkgPubKeys",
   307  					cdcEvent.Fields[i],
   308  					cadence.Array{},
   309  				)
   310  			}
   311  		}
   312  	}
   313  
   314  	if foundFieldCount != expectedFieldCount {
   315  		return nil, fmt.Errorf(
   316  			"EpochCommit event required fields not found (%d != %d)",
   317  			foundFieldCount,
   318  			expectedFieldCount,
   319  		)
   320  	}
   321  
   322  	commit := &flow.EpochCommit{
   323  		Counter: uint64(counter),
   324  	}
   325  
   326  	// parse cluster qc votes
   327  	commit.ClusterQCs, err = convertClusterQCVotes(cdcClusterQCVotes.Values)
   328  	if err != nil {
   329  		return nil, fmt.Errorf("could not convert cluster qc votes: %w", err)
   330  	}
   331  
   332  	// parse DKG group key and participants
   333  	// Note: this is read in the same order as `DKGClient.SubmitResult` ie. with the group public key first followed by individual keys
   334  	// https://github.com/onflow/flow-go/blob/feature/dkg/module/dkg/client.go#L182-L183
   335  	dkgGroupKey, dkgParticipantKeys, err := convertDKGKeys(cdcDKGKeys.Values)
   336  	if err != nil {
   337  		return nil, fmt.Errorf("could not convert DKG keys: %w", err)
   338  	}
   339  	commit.DKGGroupKey = dkgGroupKey
   340  	commit.DKGParticipantKeys = dkgParticipantKeys
   341  
   342  	// create the service event
   343  	serviceEvent := &flow.ServiceEvent{
   344  		Type:  flow.ServiceEventCommit,
   345  		Event: commit,
   346  	}
   347  
   348  	return serviceEvent, nil
   349  }
   350  
   351  // convertClusterAssignments converts the Cadence representation of cluster
   352  // assignments included in the EpochSetup into the protocol AssignmentList
   353  // representation.
   354  func convertClusterAssignments(cdcClusters []cadence.Value) (flow.AssignmentList, error) {
   355  
   356  	// ensure we don't have duplicate cluster indices
   357  	indices := make(map[uint]struct{})
   358  
   359  	// parse cluster assignments to Go types
   360  	identifierLists := make([]flow.IdentifierList, len(cdcClusters))
   361  	for _, value := range cdcClusters {
   362  
   363  		cdcCluster, ok := value.(cadence.Struct)
   364  		if !ok {
   365  			return nil, invalidCadenceTypeError("cluster", cdcCluster, cadence.Struct{})
   366  		}
   367  
   368  		const expectedFieldCount = 2
   369  		if len(cdcCluster.Fields) < expectedFieldCount {
   370  			return nil, fmt.Errorf(
   371  				"insufficient fields (%d < %d)",
   372  				len(cdcCluster.Fields),
   373  				expectedFieldCount,
   374  			)
   375  		}
   376  
   377  		if cdcCluster.Type() == nil {
   378  			return nil, fmt.Errorf("cluster struct doesn't have type")
   379  		}
   380  
   381  		// Extract cluster fields
   382  		var clusterIndex cadence.UInt16
   383  		var weightsByNodeID cadence.Dictionary
   384  		var foundFieldCount int
   385  
   386  		cdcClusterType := cdcCluster.Type().(*cadence.StructType)
   387  
   388  		for i, f := range cdcClusterType.Fields {
   389  			switch f.Identifier {
   390  			case "index":
   391  				foundFieldCount++
   392  				clusterIndex, ok = cdcCluster.Fields[i].(cadence.UInt16)
   393  				if !ok {
   394  					return nil, invalidCadenceTypeError(
   395  						"index",
   396  						cdcCluster.Fields[i],
   397  						cadence.UInt16(0),
   398  					)
   399  				}
   400  
   401  			case "nodeWeights":
   402  				foundFieldCount++
   403  				weightsByNodeID, ok = cdcCluster.Fields[i].(cadence.Dictionary)
   404  				if !ok {
   405  					return nil, invalidCadenceTypeError(
   406  						"nodeWeights",
   407  						cdcCluster.Fields[i],
   408  						cadence.Dictionary{},
   409  					)
   410  				}
   411  			}
   412  		}
   413  
   414  		if foundFieldCount != expectedFieldCount {
   415  			return nil, fmt.Errorf(
   416  				"cluster struct required fields not found (%d != %d)",
   417  				foundFieldCount,
   418  				expectedFieldCount,
   419  			)
   420  		}
   421  
   422  		// ensure cluster index is valid
   423  		if int(clusterIndex) >= len(cdcClusters) {
   424  			return nil, fmt.Errorf(
   425  				"invalid cdcCluster index (%d) outside range [0,%d]",
   426  				clusterIndex,
   427  				len(cdcClusters)-1,
   428  			)
   429  		}
   430  		_, dup := indices[uint(clusterIndex)]
   431  		if dup {
   432  			return nil, fmt.Errorf("duplicate cdcCluster index (%d)", clusterIndex)
   433  		}
   434  
   435  		// read weights to retrieve node IDs of cdcCluster members
   436  		for _, pair := range weightsByNodeID.Pairs {
   437  
   438  			nodeIDString, ok := pair.Key.(cadence.String)
   439  			if !ok {
   440  				return nil, invalidCadenceTypeError(
   441  					"clusterWeights.nodeID",
   442  					pair.Key,
   443  					cadence.String(""),
   444  				)
   445  			}
   446  			nodeID, err := flow.HexStringToIdentifier(string(nodeIDString))
   447  			if err != nil {
   448  				return nil, fmt.Errorf(
   449  					"could not convert hex string to identifer: %w",
   450  					err,
   451  				)
   452  			}
   453  
   454  			identifierLists[clusterIndex] = append(identifierLists[clusterIndex], nodeID)
   455  		}
   456  	}
   457  
   458  	// sort identifier lists in Canonical order
   459  	assignments := assignment.FromIdentifierLists(identifierLists)
   460  
   461  	return assignments, nil
   462  }
   463  
   464  // convertParticipants converts the network participants specified in the
   465  // EpochSetup event into an IdentityList.
   466  func convertParticipants(cdcParticipants []cadence.Value) (flow.IdentityList, error) {
   467  
   468  	participants := make(flow.IdentityList, 0, len(cdcParticipants))
   469  	var err error
   470  
   471  	for _, value := range cdcParticipants {
   472  
   473  		cdcNodeInfoStruct, ok := value.(cadence.Struct)
   474  		if !ok {
   475  			return nil, invalidCadenceTypeError(
   476  				"cdcNodeInfoFields",
   477  				value,
   478  				cadence.Struct{},
   479  			)
   480  		}
   481  
   482  		const expectedFieldCount = 14
   483  		if len(cdcNodeInfoStruct.Fields) < expectedFieldCount {
   484  			return nil, fmt.Errorf(
   485  				"insufficient fields (%d < %d)",
   486  				len(cdcNodeInfoStruct.Fields),
   487  				expectedFieldCount,
   488  			)
   489  		}
   490  
   491  		if cdcNodeInfoStruct.Type() == nil {
   492  			return nil, fmt.Errorf("nodeInfo struct doesn't have type")
   493  		}
   494  
   495  		cdcNodeInfoStructType := cdcNodeInfoStruct.Type().(*cadence.StructType)
   496  
   497  		const requiredFieldCount = 6
   498  		var foundFieldCount int
   499  
   500  		var nodeIDHex cadence.String
   501  		var role cadence.UInt8
   502  		var address cadence.String
   503  		var networkKeyHex cadence.String
   504  		var stakingKeyHex cadence.String
   505  		var initialWeight cadence.UInt64
   506  
   507  		for i, f := range cdcNodeInfoStructType.Fields {
   508  			switch f.Identifier {
   509  			case "id":
   510  				foundFieldCount++
   511  				nodeIDHex, ok = cdcNodeInfoStruct.Fields[i].(cadence.String)
   512  				if !ok {
   513  					return nil, invalidCadenceTypeError(
   514  						"nodeInfo.id",
   515  						cdcNodeInfoStruct.Fields[i],
   516  						cadence.String(""),
   517  					)
   518  				}
   519  
   520  			case "role":
   521  				foundFieldCount++
   522  				role, ok = cdcNodeInfoStruct.Fields[i].(cadence.UInt8)
   523  				if !ok {
   524  					return nil, invalidCadenceTypeError(
   525  						"nodeInfo.role",
   526  						cdcNodeInfoStruct.Fields[i],
   527  						cadence.UInt8(0),
   528  					)
   529  				}
   530  
   531  			case "networkingAddress":
   532  				foundFieldCount++
   533  				address, ok = cdcNodeInfoStruct.Fields[i].(cadence.String)
   534  				if !ok {
   535  					return nil, invalidCadenceTypeError(
   536  						"nodeInfo.networkingAddress",
   537  						cdcNodeInfoStruct.Fields[i],
   538  						cadence.String(""),
   539  					)
   540  				}
   541  
   542  			case "networkingKey":
   543  				foundFieldCount++
   544  				networkKeyHex, ok = cdcNodeInfoStruct.Fields[i].(cadence.String)
   545  				if !ok {
   546  					return nil, invalidCadenceTypeError(
   547  						"nodeInfo.networkingKey",
   548  						cdcNodeInfoStruct.Fields[i],
   549  						cadence.String(""),
   550  					)
   551  				}
   552  
   553  			case "stakingKey":
   554  				foundFieldCount++
   555  				stakingKeyHex, ok = cdcNodeInfoStruct.Fields[i].(cadence.String)
   556  				if !ok {
   557  					return nil, invalidCadenceTypeError(
   558  						"nodeInfo.stakingKey",
   559  						cdcNodeInfoStruct.Fields[i],
   560  						cadence.String(""),
   561  					)
   562  				}
   563  
   564  			case "initialWeight":
   565  				foundFieldCount++
   566  				initialWeight, ok = cdcNodeInfoStruct.Fields[i].(cadence.UInt64)
   567  				if !ok {
   568  					return nil, invalidCadenceTypeError(
   569  						"nodeInfo.initialWeight",
   570  						cdcNodeInfoStruct.Fields[i],
   571  						cadence.UInt64(0),
   572  					)
   573  				}
   574  			}
   575  		}
   576  
   577  		if foundFieldCount != requiredFieldCount {
   578  			return nil, fmt.Errorf(
   579  				"NodeInfo struct required fields not found (%d != %d)",
   580  				foundFieldCount,
   581  				requiredFieldCount,
   582  			)
   583  		}
   584  
   585  		if !flow.Role(role).Valid() {
   586  			return nil, fmt.Errorf("invalid role %d", role)
   587  		}
   588  
   589  		identity := &flow.Identity{
   590  			Address: string(address),
   591  			Weight:  uint64(initialWeight),
   592  			Role:    flow.Role(role),
   593  		}
   594  
   595  		// convert nodeID string into identifier
   596  		identity.NodeID, err = flow.HexStringToIdentifier(string(nodeIDHex))
   597  		if err != nil {
   598  			return nil, fmt.Errorf("could not convert hex string to identifer: %w", err)
   599  		}
   600  
   601  		// parse to PublicKey the networking key hex string
   602  		networkKeyBytes, err := hex.DecodeString(string(networkKeyHex))
   603  		if err != nil {
   604  			return nil, fmt.Errorf(
   605  				"could not decode network public key into bytes: %w",
   606  				err,
   607  			)
   608  		}
   609  		identity.NetworkPubKey, err = crypto.DecodePublicKey(
   610  			crypto.ECDSAP256,
   611  			networkKeyBytes,
   612  		)
   613  		if err != nil {
   614  			return nil, fmt.Errorf("could not decode network public key: %w", err)
   615  		}
   616  
   617  		// parse to PublicKey the staking key hex string
   618  		stakingKeyBytes, err := hex.DecodeString(string(stakingKeyHex))
   619  		if err != nil {
   620  			return nil, fmt.Errorf(
   621  				"could not decode staking public key into bytes: %w",
   622  				err,
   623  			)
   624  		}
   625  		identity.StakingPubKey, err = crypto.DecodePublicKey(
   626  			crypto.BLSBLS12381,
   627  			stakingKeyBytes,
   628  		)
   629  		if err != nil {
   630  			return nil, fmt.Errorf("could not decode staking public key: %w", err)
   631  		}
   632  
   633  		participants = append(participants, identity)
   634  	}
   635  
   636  	participants = participants.Sort(flow.Canonical)
   637  	return participants, nil
   638  }
   639  
   640  // convertClusterQCVotes converts raw cluster QC votes from the EpochCommit event
   641  // to a representation suitable for inclusion in the protocol state. Votes are
   642  // aggregated as part of this conversion.
   643  func convertClusterQCVotes(cdcClusterQCs []cadence.Value) (
   644  	[]flow.ClusterQCVoteData,
   645  	error,
   646  ) {
   647  
   648  	// avoid duplicate indices
   649  	indices := make(map[uint]struct{})
   650  	qcVoteDatas := make([]flow.ClusterQCVoteData, len(cdcClusterQCs))
   651  
   652  	// CAUTION: Votes are not validated prior to aggregation. This means a single
   653  	// invalid vote submission will result in a fully invalid QC for that cluster.
   654  	// Votes must be validated by the ClusterQC smart contract.
   655  
   656  	for _, cdcClusterQC := range cdcClusterQCs {
   657  		cdcClusterQCStruct, ok := cdcClusterQC.(cadence.Struct)
   658  		if !ok {
   659  			return nil, invalidCadenceTypeError(
   660  				"clusterQC",
   661  				cdcClusterQC,
   662  				cadence.Struct{},
   663  			)
   664  		}
   665  
   666  		const expectedFieldCount = 4
   667  		if len(cdcClusterQCStruct.Fields) < expectedFieldCount {
   668  			return nil, fmt.Errorf(
   669  				"insufficient fields (%d < %d)",
   670  				len(cdcClusterQCStruct.Fields),
   671  				expectedFieldCount,
   672  			)
   673  		}
   674  
   675  		if cdcClusterQCStruct.Type() == nil {
   676  			return nil, fmt.Errorf("clusterQC struct doesn't have type")
   677  		}
   678  
   679  		cdcClusterQCStructType := cdcClusterQCStruct.Type().(*cadence.StructType)
   680  
   681  		const requiredFieldCount = 3
   682  		var foundFieldCount int
   683  
   684  		var index cadence.UInt16
   685  		var cdcVoterIDs cadence.Array
   686  		var cdcRawVotes cadence.Array
   687  
   688  		for i, f := range cdcClusterQCStructType.Fields {
   689  			switch f.Identifier {
   690  			case "index":
   691  				foundFieldCount++
   692  				index, ok = cdcClusterQCStruct.Fields[i].(cadence.UInt16)
   693  				if !ok {
   694  					return nil, invalidCadenceTypeError(
   695  						"ClusterQC.index",
   696  						cdcClusterQCStruct.Fields[i],
   697  						cadence.UInt16(0),
   698  					)
   699  				}
   700  
   701  			case "voteSignatures":
   702  				foundFieldCount++
   703  				cdcRawVotes, ok = cdcClusterQCStruct.Fields[i].(cadence.Array)
   704  				if !ok {
   705  					return nil, invalidCadenceTypeError(
   706  						"clusterQC.voteSignatures",
   707  						cdcClusterQCStruct.Fields[i],
   708  						cadence.Array{},
   709  					)
   710  				}
   711  
   712  			case "voterIDs":
   713  				foundFieldCount++
   714  				cdcVoterIDs, ok = cdcClusterQCStruct.Fields[i].(cadence.Array)
   715  				if !ok {
   716  					return nil, invalidCadenceTypeError(
   717  						"clusterQC.voterIDs",
   718  						cdcClusterQCStruct.Fields[i],
   719  						cadence.Array{},
   720  					)
   721  				}
   722  			}
   723  		}
   724  
   725  		if foundFieldCount != requiredFieldCount {
   726  			return nil, fmt.Errorf(
   727  				"clusterQC struct required fields not found (%d != %d)",
   728  				foundFieldCount,
   729  				requiredFieldCount,
   730  			)
   731  		}
   732  
   733  		if int(index) >= len(cdcClusterQCs) {
   734  			return nil, fmt.Errorf(
   735  				"invalid index (%d) not in range [0,%d]",
   736  				index,
   737  				len(cdcClusterQCs),
   738  			)
   739  		}
   740  		_, dup := indices[uint(index)]
   741  		if dup {
   742  			return nil, fmt.Errorf("duplicate cluster QC index (%d)", index)
   743  		}
   744  
   745  		voterIDs := make([]flow.Identifier, 0, len(cdcVoterIDs.Values))
   746  		for _, cdcVoterID := range cdcVoterIDs.Values {
   747  			voterIDHex, ok := cdcVoterID.(cadence.String)
   748  			if !ok {
   749  				return nil, invalidCadenceTypeError(
   750  					"clusterQC[i].voterID",
   751  					cdcVoterID,
   752  					cadence.String(""),
   753  				)
   754  			}
   755  			voterID, err := flow.HexStringToIdentifier(string(voterIDHex))
   756  			if err != nil {
   757  				return nil, fmt.Errorf("could not convert voter ID from hex: %w", err)
   758  			}
   759  			voterIDs = append(voterIDs, voterID)
   760  		}
   761  
   762  		// gather all the vote signatures
   763  		signatures := make([]crypto.Signature, 0, len(cdcRawVotes.Values))
   764  		for _, cdcRawVote := range cdcRawVotes.Values {
   765  			rawVoteHex, ok := cdcRawVote.(cadence.String)
   766  			if !ok {
   767  				return nil, invalidCadenceTypeError(
   768  					"clusterQC[i].vote",
   769  					cdcRawVote,
   770  					cadence.String(""),
   771  				)
   772  			}
   773  			rawVoteBytes, err := hex.DecodeString(string(rawVoteHex))
   774  			if err != nil {
   775  				return nil, fmt.Errorf("could not convert raw vote from hex: %w", err)
   776  			}
   777  			signatures = append(signatures, rawVoteBytes)
   778  		}
   779  		// Aggregate BLS signatures
   780  		aggregatedSignature, err := crypto.AggregateBLSSignatures(signatures)
   781  		if err != nil {
   782  			// expected errors of the function are:
   783  			//  - empty list of signatures
   784  			//  - an input signature does not deserialize to a valid point
   785  			// Both are not expected at this stage because list is guaranteed not to be
   786  			// empty and individual signatures have been validated.
   787  			return nil, fmt.Errorf("cluster qc vote aggregation failed: %w", err)
   788  		}
   789  
   790  		// check that aggregated signature is not identity, because an identity signature
   791  		// is invalid if verified under an identity public key. This can happen in two cases:
   792  		//  - If the quorum has at least one honest signer, and given all staking key proofs of possession
   793  		//    are valid, it's extremely unlikely for the aggregated public key (and the corresponding
   794  		//    aggregated signature) to be identity.
   795  		//  - If all quorum is malicious and intentionally forge an identity aggregate. As of the previous point,
   796  		//    this is only possible if there is no honest collector involved in constructing the cluster QC.
   797  		//    Hence, the cluster would need to contain a supermajority of malicious collectors.
   798  		//    As we are assuming that the fraction of malicious collectors overall does not exceed 1/3  (measured
   799  		//    by stake), the probability for randomly assigning 2/3 or more byzantine collectors to a single cluster
   800  		//    vanishes (provided a sufficiently high collector count in total).
   801  		//
   802  		//  Note that at this level, all individual signatures are guaranteed to be valid
   803  		//  w.r.t their corresponding staking public key. It is therefore enough to check
   804  		//  the aggregated signature to conclude whether the aggregated public key is identity.
   805  		//  This check is therefore a sanity check to catch a potential issue early.
   806  		if crypto.IsBLSSignatureIdentity(aggregatedSignature) {
   807  			return nil, fmt.Errorf("cluster qc vote aggregation failed because resulting BLS signature is identity")
   808  		}
   809  
   810  		// set the fields on the QC vote data object
   811  		qcVoteDatas[int(index)] = flow.ClusterQCVoteData{
   812  			SigData:  aggregatedSignature,
   813  			VoterIDs: voterIDs,
   814  		}
   815  	}
   816  
   817  	return qcVoteDatas, nil
   818  }
   819  
   820  // convertDKGKeys converts hex-encoded DKG public keys as received by the DKG
   821  // smart contract into crypto.PublicKey representations suitable for inclusion
   822  // in the protocol state.
   823  func convertDKGKeys(cdcDKGKeys []cadence.Value) (
   824  	groupKey crypto.PublicKey,
   825  	participantKeys []crypto.PublicKey,
   826  	err error,
   827  ) {
   828  
   829  	hexDKGKeys := make([]string, 0, len(cdcDKGKeys))
   830  	for _, value := range cdcDKGKeys {
   831  		keyHex, ok := value.(cadence.String)
   832  		if !ok {
   833  			return nil, nil, invalidCadenceTypeError("dkgKey", value, cadence.String(""))
   834  		}
   835  		hexDKGKeys = append(hexDKGKeys, string(keyHex))
   836  	}
   837  
   838  	// pop first element - group public key hex string
   839  	groupPubKeyHex := hexDKGKeys[0]
   840  	hexDKGKeys = hexDKGKeys[1:]
   841  
   842  	// decode group public key
   843  	groupKeyBytes, err := hex.DecodeString(groupPubKeyHex)
   844  	if err != nil {
   845  		return nil, nil, fmt.Errorf(
   846  			"could not decode group public key into bytes: %w",
   847  			err,
   848  		)
   849  	}
   850  	groupKey, err = crypto.DecodePublicKey(crypto.BLSBLS12381, groupKeyBytes)
   851  	if err != nil {
   852  		return nil, nil, fmt.Errorf("could not decode group public key: %w", err)
   853  	}
   854  
   855  	// decode individual public keys
   856  	dkgParticipantKeys := make([]crypto.PublicKey, 0, len(hexDKGKeys))
   857  	for _, pubKeyString := range hexDKGKeys {
   858  
   859  		pubKeyBytes, err := hex.DecodeString(pubKeyString)
   860  		if err != nil {
   861  			return nil, nil, fmt.Errorf(
   862  				"could not decode individual public key into bytes: %w",
   863  				err,
   864  			)
   865  		}
   866  		pubKey, err := crypto.DecodePublicKey(crypto.BLSBLS12381, pubKeyBytes)
   867  		if err != nil {
   868  			return nil, nil, fmt.Errorf("could not decode dkg public key: %w", err)
   869  		}
   870  		dkgParticipantKeys = append(dkgParticipantKeys, pubKey)
   871  	}
   872  
   873  	return groupKey, dkgParticipantKeys, nil
   874  }
   875  
   876  func invalidCadenceTypeError(
   877  	fieldName string,
   878  	actualType, expectedType cadence.Value,
   879  ) error {
   880  	return fmt.Errorf(
   881  		"invalid Cadence type for field %s (got=%s, expected=%s)",
   882  		fieldName,
   883  		actualType.Type().ID(),
   884  		expectedType.Type().ID(),
   885  	)
   886  }
   887  
   888  func convertServiceEventVersionBeacon(event flow.Event) (*flow.ServiceEvent, error) {
   889  	payload, err := ccf.Decode(nil, event.Payload)
   890  	if err != nil {
   891  		return nil, fmt.Errorf("could not unmarshal event payload: %w", err)
   892  	}
   893  
   894  	versionBeacon, err := DecodeCadenceValue(
   895  		"VersionBeacon payload", payload, func(cdcEvent cadence.Event) (
   896  			flow.VersionBeacon,
   897  			error,
   898  		) {
   899  			const expectedFieldCount = 2
   900  			if len(cdcEvent.Fields) != expectedFieldCount {
   901  				return flow.VersionBeacon{}, fmt.Errorf(
   902  					"unexpected number of fields in VersionBeacon event (%d != %d)",
   903  					len(cdcEvent.Fields),
   904  					expectedFieldCount,
   905  				)
   906  			}
   907  
   908  			if cdcEvent.Type() == nil {
   909  				return flow.VersionBeacon{}, fmt.Errorf("VersionBeacon event doesn't have type")
   910  			}
   911  
   912  			var versionBoundariesValue, sequenceValue cadence.Value
   913  			var foundFieldCount int
   914  
   915  			evt := cdcEvent.Type().(*cadence.EventType)
   916  
   917  			for i, f := range evt.Fields {
   918  				switch f.Identifier {
   919  				case "versionBoundaries":
   920  					foundFieldCount++
   921  					versionBoundariesValue = cdcEvent.Fields[i]
   922  
   923  				case "sequence":
   924  					foundFieldCount++
   925  					sequenceValue = cdcEvent.Fields[i]
   926  				}
   927  			}
   928  
   929  			if foundFieldCount != expectedFieldCount {
   930  				return flow.VersionBeacon{}, fmt.Errorf(
   931  					"VersionBeacon event required fields not found (%d != %d)",
   932  					foundFieldCount,
   933  					expectedFieldCount,
   934  				)
   935  			}
   936  
   937  			versionBoundaries, err := DecodeCadenceValue(
   938  				".versionBoundaries", versionBoundariesValue, convertVersionBoundaries,
   939  			)
   940  			if err != nil {
   941  				return flow.VersionBeacon{}, err
   942  			}
   943  
   944  			sequence, err := DecodeCadenceValue(
   945  				".sequence", sequenceValue, func(cadenceVal cadence.UInt64) (
   946  					uint64,
   947  					error,
   948  				) {
   949  					return uint64(cadenceVal), nil
   950  				},
   951  			)
   952  			if err != nil {
   953  				return flow.VersionBeacon{}, err
   954  			}
   955  
   956  			return flow.VersionBeacon{
   957  				VersionBoundaries: versionBoundaries,
   958  				Sequence:          sequence,
   959  			}, err
   960  		},
   961  	)
   962  	if err != nil {
   963  		return nil, err
   964  	}
   965  
   966  	// a converted version beacon event should also be valid
   967  	if err := versionBeacon.Validate(); err != nil {
   968  		return nil, fmt.Errorf("invalid VersionBeacon event: %w", err)
   969  	}
   970  
   971  	// create the service event
   972  	serviceEvent := &flow.ServiceEvent{
   973  		Type:  flow.ServiceEventVersionBeacon,
   974  		Event: &versionBeacon,
   975  	}
   976  
   977  	return serviceEvent, nil
   978  }
   979  
   980  func convertVersionBoundaries(array cadence.Array) (
   981  	[]flow.VersionBoundary,
   982  	error,
   983  ) {
   984  	boundaries := make([]flow.VersionBoundary, len(array.Values))
   985  
   986  	for i, cadenceVal := range array.Values {
   987  		boundary, err := DecodeCadenceValue(
   988  			fmt.Sprintf(".Values[%d]", i),
   989  			cadenceVal,
   990  			func(structVal cadence.Struct) (
   991  				flow.VersionBoundary,
   992  				error,
   993  			) {
   994  				const expectedFieldCount = 2
   995  				if len(structVal.Fields) < expectedFieldCount {
   996  					return flow.VersionBoundary{}, fmt.Errorf(
   997  						"incorrect number of fields (%d != %d)",
   998  						len(structVal.Fields),
   999  						expectedFieldCount,
  1000  					)
  1001  				}
  1002  
  1003  				if structVal.Type() == nil {
  1004  					return flow.VersionBoundary{}, fmt.Errorf("VersionBoundary struct doesn't have type")
  1005  				}
  1006  
  1007  				var blockHeightValue, versionValue cadence.Value
  1008  				var foundFieldCount int
  1009  
  1010  				structValType := structVal.Type().(*cadence.StructType)
  1011  
  1012  				for i, f := range structValType.Fields {
  1013  					switch f.Identifier {
  1014  					case "blockHeight":
  1015  						foundFieldCount++
  1016  						blockHeightValue = structVal.Fields[i]
  1017  
  1018  					case "version":
  1019  						foundFieldCount++
  1020  						versionValue = structVal.Fields[i]
  1021  					}
  1022  				}
  1023  
  1024  				if foundFieldCount != expectedFieldCount {
  1025  					return flow.VersionBoundary{}, fmt.Errorf(
  1026  						"VersionBoundaries struct required fields not found (%d != %d)",
  1027  						foundFieldCount,
  1028  						expectedFieldCount,
  1029  					)
  1030  				}
  1031  
  1032  				height, err := DecodeCadenceValue(
  1033  					".blockHeight",
  1034  					blockHeightValue,
  1035  					func(cadenceVal cadence.UInt64) (
  1036  						uint64,
  1037  						error,
  1038  					) {
  1039  						return uint64(cadenceVal), nil
  1040  					},
  1041  				)
  1042  				if err != nil {
  1043  					return flow.VersionBoundary{}, err
  1044  				}
  1045  
  1046  				version, err := DecodeCadenceValue(
  1047  					".version",
  1048  					versionValue,
  1049  					convertSemverVersion,
  1050  				)
  1051  				if err != nil {
  1052  					return flow.VersionBoundary{}, err
  1053  				}
  1054  
  1055  				return flow.VersionBoundary{
  1056  					BlockHeight: height,
  1057  					Version:     version,
  1058  				}, nil
  1059  			},
  1060  		)
  1061  		if err != nil {
  1062  			return nil, err
  1063  		}
  1064  		boundaries[i] = boundary
  1065  	}
  1066  
  1067  	return boundaries, nil
  1068  }
  1069  
  1070  func convertSemverVersion(structVal cadence.Struct) (
  1071  	string,
  1072  	error,
  1073  ) {
  1074  	const expectedFieldCount = 4
  1075  	if len(structVal.Fields) < expectedFieldCount {
  1076  		return "", fmt.Errorf(
  1077  			"incorrect number of fields (%d != %d)",
  1078  			len(structVal.Fields),
  1079  			expectedFieldCount,
  1080  		)
  1081  	}
  1082  
  1083  	if structVal.Type() == nil {
  1084  		return "", fmt.Errorf("Semver struct doesn't have type")
  1085  	}
  1086  
  1087  	var majorValue, minorValue, patchValue, preReleaseValue cadence.Value
  1088  	var foundFieldCount int
  1089  
  1090  	structValType := structVal.Type().(*cadence.StructType)
  1091  
  1092  	for i, f := range structValType.Fields {
  1093  		switch f.Identifier {
  1094  		case "major":
  1095  			foundFieldCount++
  1096  			majorValue = structVal.Fields[i]
  1097  
  1098  		case "minor":
  1099  			foundFieldCount++
  1100  			minorValue = structVal.Fields[i]
  1101  
  1102  		case "patch":
  1103  			foundFieldCount++
  1104  			patchValue = structVal.Fields[i]
  1105  
  1106  		case "preRelease":
  1107  			foundFieldCount++
  1108  			preReleaseValue = structVal.Fields[i]
  1109  		}
  1110  	}
  1111  
  1112  	if foundFieldCount != expectedFieldCount {
  1113  		return "", fmt.Errorf(
  1114  			"Semver struct required fields not found (%d != %d)",
  1115  			foundFieldCount,
  1116  			expectedFieldCount,
  1117  		)
  1118  	}
  1119  
  1120  	major, err := DecodeCadenceValue(
  1121  		".major",
  1122  		majorValue,
  1123  		func(cadenceVal cadence.UInt8) (
  1124  			uint64,
  1125  			error,
  1126  		) {
  1127  			return uint64(cadenceVal), nil
  1128  		},
  1129  	)
  1130  	if err != nil {
  1131  		return "", err
  1132  	}
  1133  
  1134  	minor, err := DecodeCadenceValue(
  1135  		".minor",
  1136  		minorValue,
  1137  		func(cadenceVal cadence.UInt8) (
  1138  			uint64,
  1139  			error,
  1140  		) {
  1141  			return uint64(cadenceVal), nil
  1142  		},
  1143  	)
  1144  	if err != nil {
  1145  		return "", err
  1146  	}
  1147  
  1148  	patch, err := DecodeCadenceValue(
  1149  		".patch",
  1150  		patchValue,
  1151  		func(cadenceVal cadence.UInt8) (
  1152  			uint64,
  1153  			error,
  1154  		) {
  1155  			return uint64(cadenceVal), nil
  1156  		},
  1157  	)
  1158  	if err != nil {
  1159  		return "", err
  1160  	}
  1161  
  1162  	preRelease, err := DecodeCadenceValue(
  1163  		".preRelease",
  1164  		preReleaseValue,
  1165  		func(cadenceVal cadence.Optional) (
  1166  			string,
  1167  			error,
  1168  		) {
  1169  			if cadenceVal.Value == nil {
  1170  				return "", nil
  1171  			}
  1172  
  1173  			return DecodeCadenceValue(
  1174  				"!",
  1175  				cadenceVal.Value,
  1176  				func(cadenceVal cadence.String) (
  1177  					string,
  1178  					error,
  1179  				) {
  1180  					return string(cadenceVal), nil
  1181  				},
  1182  			)
  1183  		},
  1184  	)
  1185  	if err != nil {
  1186  		return "", err
  1187  	}
  1188  
  1189  	version := semver.Version{
  1190  		Major:      int64(major),
  1191  		Minor:      int64(minor),
  1192  		Patch:      int64(patch),
  1193  		PreRelease: semver.PreRelease(preRelease),
  1194  	}
  1195  
  1196  	return version.String(), nil
  1197  
  1198  }
  1199  
  1200  type decodeError struct {
  1201  	location string
  1202  	err      error
  1203  }
  1204  
  1205  func (e decodeError) Error() string {
  1206  	if e.err != nil {
  1207  		return fmt.Sprintf("decoding error %s: %s", e.location, e.err.Error())
  1208  	}
  1209  	return fmt.Sprintf("decoding error %s", e.location)
  1210  }
  1211  
  1212  func (e decodeError) Unwrap() error {
  1213  	return e.err
  1214  }
  1215  
  1216  func DecodeCadenceValue[From cadence.Value, Into any](
  1217  	location string,
  1218  	value cadence.Value,
  1219  	decodeInner func(From) (Into, error),
  1220  ) (Into, error) {
  1221  	var defaultInto Into
  1222  	if value == nil {
  1223  		return defaultInto, decodeError{
  1224  			location: location,
  1225  			err:      nil,
  1226  		}
  1227  	}
  1228  
  1229  	convertedValue, is := value.(From)
  1230  	if !is {
  1231  		return defaultInto, decodeError{
  1232  			location: location,
  1233  			err: fmt.Errorf(
  1234  				"invalid Cadence type (got=%T, expected=%T)",
  1235  				value,
  1236  				*new(From),
  1237  			),
  1238  		}
  1239  	}
  1240  
  1241  	inner, err := decodeInner(convertedValue)
  1242  	if err != nil {
  1243  		if err, is := err.(decodeError); is {
  1244  			return defaultInto, decodeError{
  1245  				location: location + err.location,
  1246  				err:      err.err,
  1247  			}
  1248  		}
  1249  		return defaultInto, decodeError{
  1250  			location: location,
  1251  			err:      err,
  1252  		}
  1253  	}
  1254  
  1255  	return inner, nil
  1256  }