From 318fdb1fe9e17633fc916743e7da26acbe0fd947 Mon Sep 17 00:00:00 2001 From: Janez Podhostnik Date: Thu, 6 Jul 2023 19:42:51 +0200 Subject: [PATCH 1/2] Fix Version Beacon event conversion --- model/convert/service_event.go | 22 +++++++--------------- utils/unittest/service_events_fixtures.go | 4 ++-- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/model/convert/service_event.go b/model/convert/service_event.go index b3e9902e1e4..7a406ed3e71 100644 --- a/model/convert/service_event.go +++ b/model/convert/service_event.go @@ -1183,22 +1183,14 @@ func convertSemverVersion(structVal cadence.Struct) ( return "", err } - version := fmt.Sprintf( - "%d.%d.%d%s", - major, - minor, - patch, - preRelease, - ) - _, err = semver.NewVersion(version) - if err != nil { - return "", fmt.Errorf( - "invalid semver %s: %w", - version, - err, - ) + version := semver.Version{ + Major: int64(major), + Minor: int64(minor), + Patch: int64(patch), + PreRelease: semver.PreRelease(preRelease), } - return version, nil + + return version.String(), nil } diff --git a/utils/unittest/service_events_fixtures.go b/utils/unittest/service_events_fixtures.go index 8ae5a5b6a62..57d236589c7 100644 --- a/utils/unittest/service_events_fixtures.go +++ b/utils/unittest/service_events_fixtures.go @@ -165,7 +165,7 @@ func VersionBeaconFixtureByChainID(chain flow.ChainID) (flow.Event, *flow.Versio VersionBoundaries: []flow.VersionBoundary{ { BlockHeight: 44, - Version: "2.13.7", + Version: "2.13.7-test", }, }, Sequence: 5, @@ -671,7 +671,7 @@ func createVersionBeaconEvent() cadence.Event { cadence.UInt8(7), // preRelease - cadence.NewOptional(cadence.String("")), + cadence.NewOptional(cadence.String("test")), }).WithType(semverType) versionBoundary := cadence.NewStruct([]cadence.Value{ From f253727fd058ad99e220adb4aed5225b8ad9b8c2 Mon Sep 17 00:00:00 2001 From: Janez Podhostnik Date: Fri, 7 Jul 2023 13:44:33 +0200 Subject: [PATCH 2/2] additional tests for version beacon conversion --- model/convert/service_event.go | 5 + model/convert/service_event_test.go | 175 ++++++++++++++++++++++ utils/unittest/service_events_fixtures.go | 16 +- 3 files changed, 188 insertions(+), 8 deletions(-) diff --git a/model/convert/service_event.go b/model/convert/service_event.go index 7a406ed3e71..81c1d9cb9a4 100644 --- a/model/convert/service_event.go +++ b/model/convert/service_event.go @@ -965,6 +965,11 @@ func convertServiceEventVersionBeacon(event flow.Event) (*flow.ServiceEvent, err return nil, err } + // a converted version beacon event should also be valid + if err := versionBeacon.Validate(); err != nil { + return nil, fmt.Errorf("invalid VersionBeacon event: %w", err) + } + // create the service event serviceEvent := &flow.ServiceEvent{ Type: flow.ServiceEventVersionBeacon, diff --git a/model/convert/service_event_test.go b/model/convert/service_event_test.go index 6652f3e3b8e..88ba8c4d3ca 100644 --- a/model/convert/service_event_test.go +++ b/model/convert/service_event_test.go @@ -8,7 +8,9 @@ import ( "github.com/stretchr/testify/require" "github.com/onflow/cadence" + "github.com/onflow/cadence/encoding/ccf" + "github.com/onflow/flow-go/fvm/systemcontracts" "github.com/onflow/flow-go/model/convert" "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/utils/unittest" @@ -164,3 +166,176 @@ func TestDecodeCadenceValue(t *testing.T) { ) } } + +func TestVersionBeaconEventConversion(t *testing.T) { + versionBoundaryType := unittest.NewNodeVersionBeaconVersionBoundaryStructType() + semverType := unittest.NewNodeVersionBeaconSemverStructType() + eventType := unittest.NewNodeVersionBeaconVersionBeaconEventType() + + type vbTestCase struct { + name string + event cadence.Event + converted *flow.VersionBeacon + expectAndHandleError func(t *testing.T, err error) + } + + runVersionBeaconTestCase := func(t *testing.T, test vbTestCase) { + chainID := flow.Emulator + t.Run(test.name, func(t *testing.T) { + events, err := systemcontracts.ServiceEventsForChain(chainID) + if err != nil { + panic(err) + } + + event := unittest.EventFixture(events.VersionBeacon.EventType(), 1, 1, unittest.IdentifierFixture(), 0) + event.Payload, err = ccf.Encode(test.event) + require.NoError(t, err) + + // convert Cadence types to Go types + serviceEvent, err := convert.ServiceEvent(chainID, event) + + if test.expectAndHandleError != nil { + require.Error(t, err) + test.expectAndHandleError(t, err) + return + } + + require.NoError(t, err) + require.NotNil(t, event) + + // cast event type to version beacon + actual, ok := serviceEvent.Event.(*flow.VersionBeacon) + require.True(t, ok) + + require.Equal(t, test.converted, actual) + }) + } + + runVersionBeaconTestCase(t, + vbTestCase{ + name: "with pre-release", + event: cadence.NewEvent( + []cadence.Value{ + // versionBoundaries + cadence.NewArray( + []cadence.Value{ + cadence.NewStruct( + []cadence.Value{ + // blockHeight + cadence.UInt64(44), + // version + cadence.NewStruct( + []cadence.Value{ + // major + cadence.UInt8(2), + // minor + cadence.UInt8(13), + // patch + cadence.UInt8(7), + // preRelease + cadence.NewOptional(cadence.String("test")), + }, + ).WithType(semverType), + }, + ).WithType(versionBoundaryType), + }, + ).WithType(cadence.NewVariableSizedArrayType(versionBoundaryType)), + // sequence + cadence.UInt64(5), + }, + ).WithType(eventType), + converted: &flow.VersionBeacon{ + VersionBoundaries: []flow.VersionBoundary{ + { + BlockHeight: 44, + Version: "2.13.7-test", + }, + }, + Sequence: 5, + }, + }, + ) + + runVersionBeaconTestCase(t, + vbTestCase{ + name: "without pre-release", + event: cadence.NewEvent( + []cadence.Value{ + // versionBoundaries + cadence.NewArray( + []cadence.Value{ + cadence.NewStruct( + []cadence.Value{ + // blockHeight + cadence.UInt64(44), + // version + cadence.NewStruct( + []cadence.Value{ + // major + cadence.UInt8(2), + // minor + cadence.UInt8(13), + // patch + cadence.UInt8(7), + // preRelease + cadence.NewOptional(nil), + }, + ).WithType(semverType), + }, + ).WithType(versionBoundaryType), + }, + ).WithType(cadence.NewVariableSizedArrayType(versionBoundaryType)), + // sequence + cadence.UInt64(5), + }, + ).WithType(eventType), + converted: &flow.VersionBeacon{ + VersionBoundaries: []flow.VersionBoundary{ + { + BlockHeight: 44, + Version: "2.13.7", + }, + }, + Sequence: 5, + }, + }, + ) + runVersionBeaconTestCase(t, + vbTestCase{ + name: "invalid pre-release", + event: cadence.NewEvent( + []cadence.Value{ + // versionBoundaries + cadence.NewArray( + []cadence.Value{ + cadence.NewStruct( + []cadence.Value{ + // blockHeight + cadence.UInt64(44), + // version + cadence.NewStruct( + []cadence.Value{ + // major + cadence.UInt8(2), + // minor + cadence.UInt8(13), + // patch + cadence.UInt8(7), + // preRelease + cadence.NewOptional(cadence.String("/slashes.not.allowed")), + }, + ).WithType(semverType), + }, + ).WithType(versionBoundaryType), + }, + ).WithType(cadence.NewVariableSizedArrayType(versionBoundaryType)), + // sequence + cadence.UInt64(5), + }, + ).WithType(eventType), + expectAndHandleError: func(t *testing.T, err error) { + require.ErrorContains(t, err, "failed to validate pre-release") + }, + }, + ) +} diff --git a/utils/unittest/service_events_fixtures.go b/utils/unittest/service_events_fixtures.go index 57d236589c7..74e5600c154 100644 --- a/utils/unittest/service_events_fixtures.go +++ b/utils/unittest/service_events_fixtures.go @@ -656,9 +656,9 @@ func createEpochCommittedEvent() cadence.Event { } func createVersionBeaconEvent() cadence.Event { - versionBoundaryType := newNodeVersionBeaconVersionBoundaryStructType() + versionBoundaryType := NewNodeVersionBeaconVersionBoundaryStructType() - semverType := newNodeVersionBeaconSemverStructType() + semverType := NewNodeVersionBeaconSemverStructType() semver := cadence.NewStruct([]cadence.Value{ // major @@ -690,7 +690,7 @@ func createVersionBeaconEvent() cadence.Event { // sequence cadence.UInt64(5), - }).WithType(newNodeVersionBeaconVersionBeaconEventType()) + }).WithType(NewNodeVersionBeaconVersionBeaconEventType()) } func newFlowClusterQCVoteStructType() cadence.Type { @@ -943,7 +943,7 @@ func newFlowClusterQCClusterQCStructType() *cadence.StructType { } } -func newNodeVersionBeaconVersionBeaconEventType() *cadence.EventType { +func NewNodeVersionBeaconVersionBeaconEventType() *cadence.EventType { // A.01cf0e2f2f715450.NodeVersionBeacon.VersionBeacon @@ -956,7 +956,7 @@ func newNodeVersionBeaconVersionBeaconEventType() *cadence.EventType { Fields: []cadence.Field{ { Identifier: "versionBoundaries", - Type: cadence.NewVariableSizedArrayType(newNodeVersionBeaconVersionBoundaryStructType()), + Type: cadence.NewVariableSizedArrayType(NewNodeVersionBeaconVersionBoundaryStructType()), }, { Identifier: "sequence", @@ -966,7 +966,7 @@ func newNodeVersionBeaconVersionBeaconEventType() *cadence.EventType { } } -func newNodeVersionBeaconVersionBoundaryStructType() *cadence.StructType { +func NewNodeVersionBeaconVersionBoundaryStructType() *cadence.StructType { // A.01cf0e2f2f715450.NodeVersionBeacon.VersionBoundary @@ -983,13 +983,13 @@ func newNodeVersionBeaconVersionBoundaryStructType() *cadence.StructType { }, { Identifier: "version", - Type: newNodeVersionBeaconSemverStructType(), + Type: NewNodeVersionBeaconSemverStructType(), }, }, } } -func newNodeVersionBeaconSemverStructType() *cadence.StructType { +func NewNodeVersionBeaconSemverStructType() *cadence.StructType { // A.01cf0e2f2f715450.NodeVersionBeacon.Semver