Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EFM] Updated type conversion of EpochCommit #6494

Merged
merged 7 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 56 additions & 51 deletions model/convert/service_event.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ func convertServiceEventEpochCommit(event flow.Event) (*flow.ServiceEvent, error

fields := cadence.FieldsMappedByName(cdcEvent)

const expectedFieldCount = 3
const expectedFieldCount = 5
if len(fields) < expectedFieldCount {
return nil, fmt.Errorf(
"insufficient fields in EpochCommit event (%d < %d)",
Expand All @@ -252,6 +252,16 @@ func convertServiceEventEpochCommit(event flow.Event) (*flow.ServiceEvent, error
return nil, fmt.Errorf("failed to decode EpochCommit event: %w", err)
}

cdcDKGGroupKey, err := getField[cadence.String](fields, "dkgGroupKey")
if err != nil {
return nil, fmt.Errorf("failed to decode EpochCommit event: %w", err)
}

cdcDKGIndexMap, err := getField[cadence.Dictionary](fields, "dkgIdMapping")
if err != nil {
return nil, fmt.Errorf("failed to decode EpochCommit event: %w", err)
}

commit := &flow.EpochCommit{
Counter: uint64(counter),
}
Expand All @@ -263,16 +273,24 @@ func convertServiceEventEpochCommit(event flow.Event) (*flow.ServiceEvent, error
}

// parse DKG group key and participants
// Note: this is read in the same order as `DKGClient.SubmitResult` ie. with the group public key first followed by individual keys
// https://github.com/onflow/flow-go/blob/feature/dkg/module/dkg/client.go#L182-L183
dkgGroupKey, dkgParticipantKeys, err := convertDKGKeys(cdcDKGKeys.Values)
commit.DKGParticipantKeys, err = convertDKGKeys(cdcDKGKeys.Values)
if err != nil {
return nil, fmt.Errorf("could not convert DKG keys: %w", err)
}
commit.DKGGroupKey = dkgGroupKey
commit.DKGParticipantKeys = dkgParticipantKeys
// TODO(EFM, #6214): parse index map from service event
commit.DKGIndexMap = nil
commit.DKGGroupKey, err = convertDKGKey(cdcDKGGroupKey)
if err != nil {
return nil, fmt.Errorf("could not convert DKG group key: %w", err)
}

commit.DKGIndexMap = make(flow.DKGIndexMap, len(cdcDKGIndexMap.Pairs))
for _, pair := range cdcDKGIndexMap.Pairs {
nodeID, err := flow.HexStringToIdentifier(string(pair.Key.(cadence.String)))
if err != nil {
return nil, fmt.Errorf("could not convert hex string to flow.Identifer: %w", err)
}
index := pair.Value.(cadence.Int).Int()
commit.DKGIndexMap[nodeID] = index
}

// create the service event
serviceEvent := &flow.ServiceEvent{
Expand Down Expand Up @@ -438,11 +456,17 @@ func convertServiceEventEpochRecover(event flow.Event) (*flow.ServiceEvent, erro
// parse DKG group key and participants
// Note: this is read in the same order as `DKGClient.SubmitResult` ie. with the group public key first followed by individual keys
// https://github.com/onflow/flow-go/blob/feature/dkg/module/dkg/client.go#L182-L183
commit.DKGGroupKey, commit.DKGParticipantKeys, err = convertDKGKeys(cdcDKGKeys.Values)
parsedKeys, err := convertDKGKeys(cdcDKGKeys.Values)
if err != nil {
return nil, fmt.Errorf("could not convert DKG keys: %w", err)
}

// TODO(EFM, #6214): sync changes for EFM recovery for smart contracts to update EpochRecover event to have the
// same structure as EpochCommit. Add parsing of IndexMap when available.
commit.DKGGroupKey = parsedKeys[0]
commit.DKGParticipantKeys = parsedKeys[1:]
commit.DKGIndexMap = nil

// create the service event
serviceEvent := &flow.ServiceEvent{
Type: flow.ServiceEventRecover,
Expand Down Expand Up @@ -943,57 +967,38 @@ func convertClusterQCVotes(cdcClusterQCs []cadence.Value) (
// convertDKGKeys converts hex-encoded DKG public keys as received by the DKG
// smart contract into crypto.PublicKey representations suitable for inclusion
// in the protocol state.
func convertDKGKeys(cdcDKGKeys []cadence.Value) (
groupKey crypto.PublicKey,
participantKeys []crypto.PublicKey,
err error,
) {

hexDKGKeys := make([]string, 0, len(cdcDKGKeys))
func convertDKGKeys(cdcDKGKeys []cadence.Value) ([]crypto.PublicKey, error) {
convertedKeys := make([]crypto.PublicKey, 0, len(cdcDKGKeys))
for _, value := range cdcDKGKeys {
keyHex, ok := value.(cadence.String)
if !ok {
return nil, nil, invalidCadenceTypeError("dkgKey", value, cadence.String(""))
pubKey, err := convertDKGKey(value)
if err != nil {
return nil, fmt.Errorf("could not decode dkg public key: %w", err)
}
hexDKGKeys = append(hexDKGKeys, string(keyHex))
convertedKeys = append(convertedKeys, pubKey)
}
return convertedKeys, nil
}

// pop first element - group public key hex string
groupPubKeyHex := hexDKGKeys[0]
hexDKGKeys = hexDKGKeys[1:]
// convertDKGKey converts a single hex-encoded DKG public key as received by the DKG
// smart contract into crypto.PublicKey representations suitable for inclusion
// in the protocol state.
func convertDKGKey(cdcDKGKeys cadence.Value) (crypto.PublicKey, error) {
// extract string representation from Cadence Value
keyHex, ok := cdcDKGKeys.(cadence.String)
if !ok {
return nil, invalidCadenceTypeError("dkgKey", cdcDKGKeys, cadence.String(""))
}

// decode group public key
groupKeyBytes, err := hex.DecodeString(groupPubKeyHex)
// decode individual public keys
pubKeyBytes, err := hex.DecodeString(string(keyHex))
if err != nil {
return nil, nil, fmt.Errorf(
"could not decode group public key into bytes: %w",
err,
)
return nil, fmt.Errorf("could not decode individual public key into bytes: %w", err)
}
groupKey, err = crypto.DecodePublicKey(crypto.BLSBLS12381, groupKeyBytes)
pubKey, err := crypto.DecodePublicKey(crypto.BLSBLS12381, pubKeyBytes)
if err != nil {
return nil, nil, fmt.Errorf("could not decode group public key: %w", err)
return nil, fmt.Errorf("could not decode dkg public key: %w", err)
}

// decode individual public keys
dkgParticipantKeys := make([]crypto.PublicKey, 0, len(hexDKGKeys))
for _, pubKeyString := range hexDKGKeys {

pubKeyBytes, err := hex.DecodeString(pubKeyString)
if err != nil {
return nil, nil, fmt.Errorf(
"could not decode individual public key into bytes: %w",
err,
)
}
pubKey, err := crypto.DecodePublicKey(crypto.BLSBLS12381, pubKeyBytes)
if err != nil {
return nil, nil, fmt.Errorf("could not decode dkg public key: %w", err)
}
dkgParticipantKeys = append(dkgParticipantKeys, pubKey)
}

return groupKey, dkgParticipantKeys, nil
return pubKey, nil
}

func invalidCadenceTypeError(
Expand Down
31 changes: 27 additions & 4 deletions utils/unittest/service_events_fixtures.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,9 @@ func EpochCommitFixtureByChainID(chain flow.ChainID) (flow.Event, *flow.EpochCom
DKGParticipantKeys: []crypto.PublicKey{
MustDecodePublicKeyHex(crypto.BLSBLS12381, "87a339e4e5c74f089da20a33f515d8c8f4464ab53ede5a74aa2432cd1ae66d522da0c122249ee176cd747ddc83ca81090498389384201614caf51eac392c1c0a916dfdcfbbdf7363f9552b6468434add3d3f6dc91a92bbe3ee368b59b7828488"),
},
DKGIndexMap: nil,
DKGIndexMap: flow.DKGIndexMap{
flow.MustHexStringToIdentifier("0000000000000000000000000000000000000000000000000000000000000011"): 0,
},
}

return event, expected
Expand Down Expand Up @@ -271,6 +273,9 @@ func EpochRecoverFixtureByChainID(chain flow.ChainID) (flow.Event, *flow.EpochRe
DKGParticipantKeys: []crypto.PublicKey{
MustDecodePublicKeyHex(crypto.BLSBLS12381, "87a339e4e5c74f089da20a33f515d8c8f4464ab53ede5a74aa2432cd1ae66d522da0c122249ee176cd747ddc83ca81090498389384201614caf51eac392c1c0a916dfdcfbbdf7363f9552b6468434add3d3f6dc91a92bbe3ee368b59b7828488"),
},
//DKGIndexMap: flow.DKGIndexMap{
// flow.MustHexStringToIdentifier("0000000000000000000000000000000000000000000000000000000000000011"): 0,
//},
},
}

Expand Down Expand Up @@ -792,11 +797,21 @@ func createEpochCommitEvent() cadence.Event {
cluster2,
}).WithType(cadence.NewVariableSizedArrayType(clusterQCType)),

// dkgGroupKey
cadence.String("8c588266db5f5cda629e83f8aa04ae9413593fac19e4865d06d291c9d14fbdd9bdb86a7a12f9ef8590c79cb635e3163315d193087e9336092987150d0cd2b14ac6365f7dc93eec573752108b8c12368abb65f0652d9f644e5aed611c37926950"),

// dkgPubKeys
cadence.NewArray([]cadence.Value{
cadence.String("8c588266db5f5cda629e83f8aa04ae9413593fac19e4865d06d291c9d14fbdd9bdb86a7a12f9ef8590c79cb635e3163315d193087e9336092987150d0cd2b14ac6365f7dc93eec573752108b8c12368abb65f0652d9f644e5aed611c37926950"),
cadence.String("87a339e4e5c74f089da20a33f515d8c8f4464ab53ede5a74aa2432cd1ae66d522da0c122249ee176cd747ddc83ca81090498389384201614caf51eac392c1c0a916dfdcfbbdf7363f9552b6468434add3d3f6dc91a92bbe3ee368b59b7828488"),
}).WithType(cadence.NewVariableSizedArrayType(cadence.StringType)),

// dkgIdMapping
cadence.NewDictionary([]cadence.KeyValuePair{
{
Key: cadence.String("0000000000000000000000000000000000000000000000000000000000000011"),
Value: cadence.NewInt(0),
},
}).WithType(cadence.NewDictionaryType(cadence.StringType, cadence.IntType)),
}).WithType(newFlowEpochEpochCommitEventType())
}

Expand Down Expand Up @@ -1103,14 +1118,14 @@ func newFlowEpochEpochSetupEventType() *cadence.EventType {

func newFlowEpochEpochCommitEventType() *cadence.EventType {

// A.01cf0e2f2f715450.FlowEpoch.EpochCommitted
// A.01cf0e2f2f715450.FlowEpoch.EpochCommit

address, _ := common.HexToAddress("01cf0e2f2f715450")
location := common.NewAddressLocation(nil, address, "FlowEpoch")

return cadence.NewEventType(
location,
"FlowEpoch.EpochCommitted",
"FlowEpoch.EpochCommit",
[]cadence.Field{
{
Identifier: "counter",
Expand All @@ -1120,10 +1135,18 @@ func newFlowEpochEpochCommitEventType() *cadence.EventType {
Identifier: "clusterQCs",
Type: cadence.NewVariableSizedArrayType(newFlowClusterQCClusterQCStructType()),
},
{
Identifier: "dkgGroupKey",
Type: cadence.StringType,
},
{
Identifier: "dkgPubKeys",
Type: cadence.NewVariableSizedArrayType(cadence.StringType),
},
{
Identifier: "dkgIdMapping",
Type: cadence.NewDictionaryType(cadence.StringType, cadence.IntType),
},
},
nil,
)
Expand Down
Loading