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 }