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