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  }