github.com/koko1123/flow-go-1@v0.29.6/state/protocol/convert.go (about) 1 package protocol 2 3 import ( 4 "fmt" 5 6 "github.com/koko1123/flow-go-1/module/signature" 7 8 "github.com/koko1123/flow-go-1/model/flow" 9 "github.com/koko1123/flow-go-1/model/flow/filter" 10 "github.com/onflow/flow-go/crypto" 11 ) 12 13 // ToEpochSetup converts an Epoch interface instance to the underlying concrete 14 // epoch setup service event. The input must be a valid, set up epoch. 15 // Error returns: 16 // * protocol.ErrNoPreviousEpoch - if the epoch represents a previous epoch which does not exist. 17 // * protocol.ErrNextEpochNotSetup - if the epoch represents a next epoch which has not been set up. 18 // * state.ErrUnknownSnapshotReference - if the epoch is queried from an unresolvable snapshot. 19 func ToEpochSetup(epoch Epoch) (*flow.EpochSetup, error) { 20 counter, err := epoch.Counter() 21 if err != nil { 22 return nil, fmt.Errorf("could not get epoch counter: %w", err) 23 } 24 firstView, err := epoch.FirstView() 25 if err != nil { 26 return nil, fmt.Errorf("could not get epoch first view: %w", err) 27 } 28 finalView, err := epoch.FinalView() 29 if err != nil { 30 return nil, fmt.Errorf("could not get epoch final view: %w", err) 31 } 32 dkgPhase1FinalView, dkgPhase2FinalView, dkgPhase3FinalView, err := DKGPhaseViews(epoch) 33 if err != nil { 34 return nil, fmt.Errorf("could not get epoch dkg final views: %w", err) 35 } 36 participants, err := epoch.InitialIdentities() 37 if err != nil { 38 return nil, fmt.Errorf("could not get epoch participants: %w", err) 39 } 40 clustering, err := epoch.Clustering() 41 if err != nil { 42 return nil, fmt.Errorf("could not get epoch clustering: %w", err) 43 } 44 assignments := clustering.Assignments() 45 randomSource, err := epoch.RandomSource() 46 if err != nil { 47 return nil, fmt.Errorf("could not get epoch random source: %w", err) 48 } 49 50 setup := &flow.EpochSetup{ 51 Counter: counter, 52 FirstView: firstView, 53 DKGPhase1FinalView: dkgPhase1FinalView, 54 DKGPhase2FinalView: dkgPhase2FinalView, 55 DKGPhase3FinalView: dkgPhase3FinalView, 56 FinalView: finalView, 57 Participants: participants, 58 Assignments: assignments, 59 RandomSource: randomSource, 60 } 61 return setup, nil 62 } 63 64 // ToEpochCommit converts an Epoch interface instance to the underlying 65 // concrete epoch commit service event. The epoch must have been committed. 66 // Error returns: 67 // * protocol.ErrNoPreviousEpoch - if the epoch represents a previous epoch which does not exist. 68 // * protocol.ErrNextEpochNotSetup - if the epoch represents a next epoch which has not been set up. 69 // * protocol.ErrEpochNotCommitted - if the epoch has not been committed. 70 // * state.ErrUnknownSnapshotReference - if the epoch is queried from an unresolvable snapshot. 71 func ToEpochCommit(epoch Epoch) (*flow.EpochCommit, error) { 72 counter, err := epoch.Counter() 73 if err != nil { 74 return nil, fmt.Errorf("could not get epoch counter: %w", err) 75 } 76 clustering, err := epoch.Clustering() 77 if err != nil { 78 return nil, fmt.Errorf("could not get epoch clustering: %w", err) 79 } 80 qcs := make([]*flow.QuorumCertificateWithSignerIDs, 0, len(clustering)) 81 for i := range clustering { 82 cluster, err := epoch.Cluster(uint(i)) 83 if err != nil { 84 return nil, fmt.Errorf("could not get epoch cluster (index=%d): %w", i, err) 85 } 86 qc := cluster.RootQC() 87 // TODO: double check cluster.Members returns canonical order 88 signerIDs, err := signature.DecodeSignerIndicesToIdentifiers(cluster.Members().NodeIDs(), qc.SignerIndices) 89 if err != nil { 90 return nil, fmt.Errorf("could not encode signer indices: %w", err) 91 } 92 qcs = append(qcs, &flow.QuorumCertificateWithSignerIDs{ 93 View: qc.View, 94 BlockID: qc.BlockID, 95 SignerIDs: signerIDs, 96 SigData: qc.SigData, 97 }) 98 } 99 100 participants, err := epoch.InitialIdentities() 101 if err != nil { 102 return nil, fmt.Errorf("could not get epoch participants: %w", err) 103 } 104 dkg, err := epoch.DKG() 105 if err != nil { 106 return nil, fmt.Errorf("could not get epoch dkg: %w", err) 107 } 108 dkgParticipantKeys, err := GetDKGParticipantKeys(dkg, participants.Filter(filter.IsValidDKGParticipant)) 109 if err != nil { 110 return nil, fmt.Errorf("could not get dkg participant keys: %w", err) 111 } 112 113 commit := &flow.EpochCommit{ 114 Counter: counter, 115 ClusterQCs: flow.ClusterQCVoteDatasFromQCs(qcs), 116 DKGGroupKey: dkg.GroupKey(), 117 DKGParticipantKeys: dkgParticipantKeys, 118 } 119 return commit, nil 120 } 121 122 // GetDKGParticipantKeys retrieves the canonically ordered list of DKG 123 // participant keys from the DKG. 124 // All errors indicate inconsistent or invalid inputs. 125 // No errors are expected during normal operation. 126 func GetDKGParticipantKeys(dkg DKG, participants flow.IdentityList) ([]crypto.PublicKey, error) { 127 128 keys := make([]crypto.PublicKey, 0, len(participants)) 129 for i, identity := range participants { 130 131 index, err := dkg.Index(identity.NodeID) 132 if err != nil { 133 return nil, fmt.Errorf("could not get index (node=%x): %w", identity.NodeID, err) 134 } 135 key, err := dkg.KeyShare(identity.NodeID) 136 if err != nil { 137 return nil, fmt.Errorf("could not get key share (node=%x): %w", identity.NodeID, err) 138 } 139 if uint(i) != index { 140 return nil, fmt.Errorf("participant list index (%d) does not match dkg index (%d)", i, index) 141 } 142 143 keys = append(keys, key) 144 } 145 146 return keys, nil 147 } 148 149 // ToDKGParticipantLookup computes the nodeID -> DKGParticipant lookup for a 150 // DKG instance. The participants must exactly match the DKG instance configuration. 151 // All errors indicate inconsistent or invalid inputs. 152 // No errors are expected during normal operation. 153 func ToDKGParticipantLookup(dkg DKG, participants flow.IdentityList) (map[flow.Identifier]flow.DKGParticipant, error) { 154 155 lookup := make(map[flow.Identifier]flow.DKGParticipant) 156 for _, identity := range participants { 157 158 index, err := dkg.Index(identity.NodeID) 159 if err != nil { 160 return nil, fmt.Errorf("could not get index (node=%x): %w", identity.NodeID, err) 161 } 162 key, err := dkg.KeyShare(identity.NodeID) 163 if err != nil { 164 return nil, fmt.Errorf("could not get key share (node=%x): %w", identity.NodeID, err) 165 } 166 167 lookup[identity.NodeID] = flow.DKGParticipant{ 168 Index: index, 169 KeyShare: key, 170 } 171 } 172 173 return lookup, nil 174 } 175 176 // DKGPhaseViews returns the DKG final phase views for an epoch. 177 // Error returns: 178 // * protocol.ErrNoPreviousEpoch - if the epoch represents a previous epoch which does not exist. 179 // * protocol.ErrNextEpochNotSetup - if the epoch represents a next epoch which has not been set up. 180 // * protocol.ErrEpochNotCommitted - if the epoch has not been committed. 181 // * state.ErrUnknownSnapshotReference - if the epoch is queried from an unresolvable snapshot. 182 func DKGPhaseViews(epoch Epoch) (phase1FinalView uint64, phase2FinalView uint64, phase3FinalView uint64, err error) { 183 phase1FinalView, err = epoch.DKGPhase1FinalView() 184 if err != nil { 185 return 186 } 187 phase2FinalView, err = epoch.DKGPhase2FinalView() 188 if err != nil { 189 return 190 } 191 phase3FinalView, err = epoch.DKGPhase3FinalView() 192 if err != nil { 193 return 194 } 195 return 196 }