diff --git a/access/api.go b/access/api.go index 8ccb91c4bcb..adeb7284c10 100644 --- a/access/api.go +++ b/access/api.go @@ -264,6 +264,14 @@ type NetworkParameters struct { ChainID flow.ChainID } +// CompatibleRange contains the first and the last height that the version supports. +type CompatibleRange struct { + // The first block that the version supports. + StartHeight uint64 + // The last block that the version supports. + EndHeight uint64 +} + // NodeVersionInfo contains information about node, such as semver, commit, sporkID, protocolVersion, etc type NodeVersionInfo struct { Semver string @@ -272,4 +280,17 @@ type NodeVersionInfo struct { ProtocolVersion uint64 SporkRootBlockHeight uint64 NodeRootBlockHeight uint64 + CompatibleRange *CompatibleRange +} + +// CompatibleRangeToMessage converts a flow.CompatibleRange to a protobuf message +func CompatibleRangeToMessage(c *CompatibleRange) *entities.CompatibleRange { + if c != nil { + return &entities.CompatibleRange{ + StartHeight: c.StartHeight, + EndHeight: c.EndHeight, + } + } + + return nil } diff --git a/access/handler.go b/access/handler.go index 340fb4e5ef1..3007fc6f691 100644 --- a/access/handler.go +++ b/access/handler.go @@ -100,6 +100,7 @@ func (h *Handler) GetNodeVersionInfo( ProtocolVersion: nodeVersionInfo.ProtocolVersion, SporkRootBlockHeight: nodeVersionInfo.SporkRootBlockHeight, NodeRootBlockHeight: nodeVersionInfo.NodeRootBlockHeight, + CompatibleRange: CompatibleRangeToMessage(nodeVersionInfo.CompatibleRange), }, }, nil } diff --git a/cmd/access/node_builder/access_node_builder.go b/cmd/access/node_builder/access_node_builder.go index b31ea749060..6f381a867fb 100644 --- a/cmd/access/node_builder/access_node_builder.go +++ b/cmd/access/node_builder/access_node_builder.go @@ -323,7 +323,7 @@ type FlowAccessNodeBuilder struct { ExecutionDataPruner *pruner.Pruner ExecutionDatastoreManager edstorage.DatastoreManager ExecutionDataTracker tracker.Storage - versionControl *version.VersionControl + VersionControl *version.VersionControl // The sync engine participants provider is the libp2p peer store for the access node // which is not available until after the network has started. @@ -978,7 +978,7 @@ func (builder *FlowAccessNodeBuilder) BuildExecutionSyncComponents() *FlowAccess builder.programCacheSize > 0, ) - err = builder.ScriptExecutor.Initialize(builder.ExecutionIndexer, scripts, builder.versionControl) + err = builder.ScriptExecutor.Initialize(builder.ExecutionIndexer, scripts, builder.VersionControl) if err != nil { return nil, err } @@ -1813,8 +1813,8 @@ func (builder *FlowAccessNodeBuilder) Build() (cmd.Node, error) { // VersionControl needs to consume BlockFinalized events. node.ProtocolEvents.AddConsumer(versionControl) - builder.versionControl = versionControl - versionControlDependable.Init(builder.versionControl) + builder.VersionControl = versionControl + versionControlDependable.Init(builder.VersionControl) return versionControl, nil }). @@ -1921,6 +1921,7 @@ func (builder *FlowAccessNodeBuilder) Build() (cmd.Node, error) { TxResultQueryMode: txResultQueryMode, TxResultsIndex: builder.TxResultsIndex, LastFullBlockHeight: lastFullBlockHeight, + VersionControl: builder.VersionControl, }) if err != nil { return nil, fmt.Errorf("could not initialize backend: %w", err) diff --git a/cmd/observer/node_builder/observer_builder.go b/cmd/observer/node_builder/observer_builder.go index 80c702f2967..6a75ded5de7 100644 --- a/cmd/observer/node_builder/observer_builder.go +++ b/cmd/observer/node_builder/observer_builder.go @@ -279,7 +279,7 @@ type ObserverServiceBuilder struct { ExecutionIndexerCore *indexer.IndexerCore TxResultsIndex *index.TransactionResultsIndex IndexerDependencies *cmd.DependencyList - versionControl *version.VersionControl + VersionControl *version.VersionControl ExecutionDataDownloader execution_data.Downloader ExecutionDataRequester state_synchronization.ExecutionDataRequester @@ -1513,7 +1513,7 @@ func (builder *ObserverServiceBuilder) BuildExecutionSyncComponents() *ObserverS builder.programCacheSize > 0, ) - err = builder.ScriptExecutor.Initialize(builder.ExecutionIndexer, scripts, builder.versionControl) + err = builder.ScriptExecutor.Initialize(builder.ExecutionIndexer, scripts, builder.VersionControl) if err != nil { return nil, err } @@ -1854,8 +1854,8 @@ func (builder *ObserverServiceBuilder) enqueueRPCServer() { // VersionControl needs to consume BlockFinalized events. node.ProtocolEvents.AddConsumer(versionControl) - builder.versionControl = versionControl - versionControlDependable.Init(builder.versionControl) + builder.VersionControl = versionControl + versionControlDependable.Init(builder.VersionControl) return versionControl, nil }) @@ -1930,6 +1930,7 @@ func (builder *ObserverServiceBuilder) enqueueRPCServer() { builder.stateStreamConf.ResponseLimit, builder.stateStreamConf.ClientSendBufferSize, ), + VersionControl: builder.VersionControl, } if builder.localServiceAPIEnabled { diff --git a/engine/access/handle_irrecoverable_state_test.go b/engine/access/handle_irrecoverable_state_test.go index 74d848a02b1..911ba5c2a53 100644 --- a/engine/access/handle_irrecoverable_state_test.go +++ b/engine/access/handle_irrecoverable_state_test.go @@ -75,12 +75,7 @@ func (suite *IrrecoverableStateTestSuite) SetupTest() { suite.state = protocol.NewState(suite.T()) suite.snapshot = protocol.NewSnapshot(suite.T()) - rootHeader := unittest.BlockHeaderFixture() params := protocol.NewParams(suite.T()) - params.On("SporkID").Return(unittest.IdentifierFixture(), nil) - params.On("ProtocolVersion").Return(uint(unittest.Uint64InRange(10, 30)), nil) - params.On("SporkRootBlockHeight").Return(rootHeader.Height, nil) - params.On("SealedRoot").Return(rootHeader, nil) suite.epochQuery = protocol.NewEpochQuery(suite.T()) suite.state.On("Sealed").Return(suite.snapshot, nil).Maybe() diff --git a/engine/access/rest/models/model_compatible_range.go b/engine/access/rest/models/model_compatible_range.go new file mode 100644 index 00000000000..1937299f7dd --- /dev/null +++ b/engine/access/rest/models/model_compatible_range.go @@ -0,0 +1,15 @@ +/* + * Access API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 1.0.0 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ +package models + +// A compatible version range. +type CompatibleRange struct { + StartHeight string `json:"start_height"` + EndHeight string `json:"end_height"` +} diff --git a/engine/access/rest/models/model_node_version_info.go b/engine/access/rest/models/model_node_version_info.go index 5a53e468996..a6c7a4d915b 100644 --- a/engine/access/rest/models/model_node_version_info.go +++ b/engine/access/rest/models/model_node_version_info.go @@ -9,10 +9,11 @@ package models type NodeVersionInfo struct { - Semver string `json:"semver"` - Commit string `json:"commit"` - SporkId string `json:"spork_id"` - ProtocolVersion string `json:"protocol_version"` - SporkRootBlockHeight string `json:"spork_root_block_height"` - NodeRootBlockHeight string `json:"node_root_block_height"` + Semver string `json:"semver"` + Commit string `json:"commit"` + SporkId string `json:"spork_id"` + ProtocolVersion string `json:"protocol_version"` + SporkRootBlockHeight string `json:"spork_root_block_height"` + NodeRootBlockHeight string `json:"node_root_block_height"` + CompatibleRange *CompatibleRange `json:"compatible_range,omitempty"` } diff --git a/engine/access/rest/models/node_version_info.go b/engine/access/rest/models/node_version_info.go index dc9af010922..5be5bb7086c 100644 --- a/engine/access/rest/models/node_version_info.go +++ b/engine/access/rest/models/node_version_info.go @@ -12,4 +12,11 @@ func (t *NodeVersionInfo) Build(params *access.NodeVersionInfo) { t.ProtocolVersion = util.FromUint(params.ProtocolVersion) t.SporkRootBlockHeight = util.FromUint(params.SporkRootBlockHeight) t.NodeRootBlockHeight = util.FromUint(params.NodeRootBlockHeight) + + if params.CompatibleRange != nil { + t.CompatibleRange = &CompatibleRange{ + StartHeight: util.FromUint(params.CompatibleRange.StartHeight), + EndHeight: util.FromUint(params.CompatibleRange.EndHeight), + } + } } diff --git a/engine/access/rest/routes/node_version_info_test.go b/engine/access/rest/routes/node_version_info_test.go index 0bce5c83c13..f08ada0289a 100644 --- a/engine/access/rest/routes/node_version_info_test.go +++ b/engine/access/rest/routes/node_version_info_test.go @@ -28,13 +28,19 @@ func TestGetNodeVersionInfo(t *testing.T) { t.Run("get node version info", func(t *testing.T) { req := getNodeVersionInfoRequest(t) + nodeRootBlockHeight := unittest.Uint64InRange(10_000, 100_000) + params := &access.NodeVersionInfo{ Semver: build.Version(), Commit: build.Commit(), SporkId: unittest.IdentifierFixture(), ProtocolVersion: unittest.Uint64InRange(10, 30), SporkRootBlockHeight: unittest.Uint64InRange(1000, 10_000), - NodeRootBlockHeight: unittest.Uint64InRange(10_000, 100_000), + NodeRootBlockHeight: nodeRootBlockHeight, + CompatibleRange: &access.CompatibleRange{ + StartHeight: nodeRootBlockHeight, + EndHeight: uint64(0), + }, } backend.Mock. @@ -49,13 +55,22 @@ func TestGetNodeVersionInfo(t *testing.T) { } func nodeVersionInfoExpectedStr(nodeVersionInfo *access.NodeVersionInfo) string { + compatibleRange := fmt.Sprintf(`"compatible_range": { + "start_height": "%d", + "end_height": "%d" + }`, + nodeVersionInfo.CompatibleRange.StartHeight, + nodeVersionInfo.CompatibleRange.EndHeight, + ) + return fmt.Sprintf(`{ "semver": "%s", "commit": "%s", "spork_id": "%s", "protocol_version": "%d", "spork_root_block_height": "%d", - "node_root_block_height": "%d" + "node_root_block_height": "%d", + %s }`, nodeVersionInfo.Semver, nodeVersionInfo.Commit, @@ -63,6 +78,7 @@ func nodeVersionInfoExpectedStr(nodeVersionInfo *access.NodeVersionInfo) string nodeVersionInfo.ProtocolVersion, nodeVersionInfo.SporkRootBlockHeight, nodeVersionInfo.NodeRootBlockHeight, + compatibleRange, ) } diff --git a/engine/access/rpc/backend/backend.go b/engine/access/rpc/backend/backend.go index 3af46045697..184c37e0bcd 100644 --- a/engine/access/rpc/backend/backend.go +++ b/engine/access/rpc/backend/backend.go @@ -16,6 +16,7 @@ import ( "github.com/onflow/flow-go/engine/access/rpc/connection" "github.com/onflow/flow-go/engine/access/subscription" "github.com/onflow/flow-go/engine/common/rpc" + "github.com/onflow/flow-go/engine/common/version" "github.com/onflow/flow-go/fvm/blueprints" "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/model/flow/filter" @@ -81,9 +82,9 @@ type Backend struct { executionReceipts storage.ExecutionReceipts connFactory connection.ConnectionFactory - // cache the response to GetNodeVersionInfo since it doesn't change - nodeInfo *access.NodeVersionInfo - BlockTracker subscription.BlockTracker + BlockTracker subscription.BlockTracker + stateParams protocol.Params + versionControl *version.VersionControl } type Params struct { @@ -119,6 +120,7 @@ type Params struct { TxResultQueryMode IndexQueryMode TxResultsIndex *index.TransactionResultsIndex LastFullBlockHeight *counters.PersistentStrictMonotonicCounter + VersionControl *version.VersionControl } var _ TransactionErrorMessage = (*Backend)(nil) @@ -162,9 +164,6 @@ func New(params Params) (*Backend, error) { } systemTxID := systemTx.ID() - // initialize node version info - nodeInfo := getNodeVersionInfo(params.State.Params()) - transactionsLocalDataProvider := &TransactionsLocalDataProvider{ state: params.State, collections: params.Collections, @@ -243,7 +242,8 @@ func New(params Params) (*Backend, error) { executionReceipts: params.ExecutionReceipts, connFactory: params.ConnFactory, chainID: params.ChainID, - nodeInfo: nodeInfo, + stateParams: params.State.Params(), + versionControl: params.VersionControl, } txValidator, err := configureTransactionValidator(params.State, params.ChainID, params.ScriptExecutor, params.CheckPayerBalance) @@ -344,17 +344,21 @@ func (b *Backend) Ping(ctx context.Context) error { // GetNodeVersionInfo returns node version information such as semver, commit, sporkID, protocolVersion, etc func (b *Backend) GetNodeVersionInfo(_ context.Context) (*access.NodeVersionInfo, error) { - return b.nodeInfo, nil -} + sporkID := b.stateParams.SporkID() + protocolVersion := b.stateParams.ProtocolVersion() + sporkRootBlockHeight := b.stateParams.SporkRootBlockHeight() + + nodeRootBlockHeader := b.stateParams.SealedRoot() -// getNodeVersionInfo returns the NodeVersionInfo for the node. -// Since these values are static while the node is running, it is safe to cache. -func getNodeVersionInfo(stateParams protocol.Params) *access.NodeVersionInfo { - sporkID := stateParams.SporkID() - protocolVersion := stateParams.ProtocolVersion() - sporkRootBlockHeight := stateParams.SporkRootBlockHeight() + var compatibleRange *access.CompatibleRange - nodeRootBlockHeader := stateParams.SealedRoot() + // Version control feature could be disabled + if b.versionControl != nil { + compatibleRange = &access.CompatibleRange{ + StartHeight: b.versionControl.StartHeight(), + EndHeight: b.versionControl.EndHeight(), + } + } nodeInfo := &access.NodeVersionInfo{ Semver: build.Version(), @@ -363,9 +367,10 @@ func getNodeVersionInfo(stateParams protocol.Params) *access.NodeVersionInfo { ProtocolVersion: uint64(protocolVersion), SporkRootBlockHeight: sporkRootBlockHeight, NodeRootBlockHeight: nodeRootBlockHeader.Height, + CompatibleRange: compatibleRange, } - return nodeInfo + return nodeInfo, nil } func (b *Backend) GetCollectionByID(_ context.Context, colID flow.Identifier) (*flow.LightCollection, error) { diff --git a/engine/access/rpc/backend/backend_network.go b/engine/access/rpc/backend/backend_network.go index 56903ae2a1e..97d914d9323 100644 --- a/engine/access/rpc/backend/backend_network.go +++ b/engine/access/rpc/backend/backend_network.go @@ -10,7 +10,6 @@ import ( "google.golang.org/grpc/status" "github.com/onflow/flow-go/access" - "github.com/onflow/flow-go/cmd/build" "github.com/onflow/flow-go/engine/common/rpc/convert" "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/state/protocol" @@ -51,19 +50,6 @@ func (b *backendNetwork) GetNetworkParameters(_ context.Context) access.NetworkP } } -func (b *backendNetwork) GetNodeVersionInfo(_ context.Context) (*access.NodeVersionInfo, error) { - stateParams := b.state.Params() - sporkId := stateParams.SporkID() - protocolVersion := stateParams.ProtocolVersion() - - return &access.NodeVersionInfo{ - Semver: build.Version(), - Commit: build.Commit(), - SporkId: sporkId, - ProtocolVersion: uint64(protocolVersion), - }, nil -} - // GetLatestProtocolStateSnapshot returns the latest finalized snapshot. func (b *backendNetwork) GetLatestProtocolStateSnapshot(_ context.Context) ([]byte, error) { snapshot := b.state.Final() diff --git a/engine/access/rpc/backend/backend_stream_transactions_test.go b/engine/access/rpc/backend/backend_stream_transactions_test.go index 78e7b1e676d..ec8ff353bf3 100644 --- a/engine/access/rpc/backend/backend_stream_transactions_test.go +++ b/engine/access/rpc/backend/backend_stream_transactions_test.go @@ -98,13 +98,7 @@ func (s *TransactionStatusSuite) SetupTest() { s.tempSnapshot = &protocol.Snapshot{} s.db, s.dbDir = unittest.TempBadgerDB(s.T()) - header := unittest.BlockHeaderFixture() - params := protocol.NewParams(s.T()) - params.On("SporkID").Return(unittest.IdentifierFixture(), nil) - params.On("ProtocolVersion").Return(uint(unittest.Uint64InRange(10, 30)), nil) - params.On("SporkRootBlockHeight").Return(header.Height, nil) - params.On("SealedRoot").Return(header, nil) s.state.On("Params").Return(params) s.blocks = storagemock.NewBlocks(s.T()) diff --git a/engine/access/rpc/backend/backend_test.go b/engine/access/rpc/backend/backend_test.go index 63bf2637e3e..4974cbe6ce7 100644 --- a/engine/access/rpc/backend/backend_test.go +++ b/engine/access/rpc/backend/backend_test.go @@ -5,8 +5,11 @@ import ( "errors" "fmt" "os" + "sort" "testing" + "time" + "github.com/coreos/go-semver/semver" "github.com/dgraph-io/badger/v2" accessproto "github.com/onflow/flow/protobuf/go/flow/access" "github.com/onflow/flow/protobuf/go/flow/entities" @@ -21,13 +24,14 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - accessflow "github.com/onflow/flow-go/access" + "github.com/onflow/flow-go/access" "github.com/onflow/flow-go/cmd/build" - access "github.com/onflow/flow-go/engine/access/mock" + accessmock "github.com/onflow/flow-go/engine/access/mock" backendmock "github.com/onflow/flow-go/engine/access/rpc/backend/mock" "github.com/onflow/flow-go/engine/access/rpc/connection" connectionmock "github.com/onflow/flow-go/engine/access/rpc/connection/mock" "github.com/onflow/flow-go/engine/common/rpc/convert" + "github.com/onflow/flow-go/engine/common/version" "github.com/onflow/flow-go/fvm/blueprints" "github.com/onflow/flow-go/model/flow" "github.com/onflow/flow-go/module" @@ -73,10 +77,11 @@ type Suite struct { db *badger.DB dbDir string lastFullBlockHeight *counters.PersistentStrictMonotonicCounter + versionControl *version.VersionControl - colClient *access.AccessAPIClient - execClient *access.ExecutionAPIClient - historicalAccessClient *access.AccessAPIClient + colClient *accessmock.AccessAPIClient + execClient *accessmock.ExecutionAPIClient + historicalAccessClient *accessmock.AccessAPIClient connectionFactory *connectionmock.ConnectionFactory communicator *backendmock.Communicator @@ -108,12 +113,12 @@ func (suite *Suite) SetupTest() { suite.collections = new(storagemock.Collections) suite.receipts = new(storagemock.ExecutionReceipts) suite.results = new(storagemock.ExecutionResults) - suite.colClient = new(access.AccessAPIClient) - suite.execClient = new(access.ExecutionAPIClient) + suite.colClient = new(accessmock.AccessAPIClient) + suite.execClient = new(accessmock.ExecutionAPIClient) suite.transactionResults = storagemock.NewLightTransactionResults(suite.T()) suite.events = storagemock.NewEvents(suite.T()) suite.chainID = flow.Testnet - suite.historicalAccessClient = new(access.AccessAPIClient) + suite.historicalAccessClient = new(accessmock.AccessAPIClient) suite.connectionFactory = connectionmock.NewConnectionFactory(suite.T()) suite.communicator = new(backendmock.Communicator) @@ -1589,13 +1594,14 @@ func (suite *Suite) TestGetNodeVersionInfo() { state := protocol.NewState(suite.T()) state.On("Params").Return(stateParams, nil).Maybe() - expected := &accessflow.NodeVersionInfo{ + expected := &access.NodeVersionInfo{ Semver: build.Version(), Commit: build.Commit(), SporkId: sporkID, ProtocolVersion: uint64(protocolVersion), SporkRootBlockHeight: sporkRootBlock.Height, NodeRootBlockHeight: nodeRootBlock.Height, + CompatibleRange: nil, } params := suite.defaultBackendParams() @@ -1609,6 +1615,104 @@ func (suite *Suite) TestGetNodeVersionInfo() { suite.Require().Equal(expected, actual) }) + + suite.Run("start and end version set", func() { + latestBlockHeight := nodeRootBlock.Height + 100 + versionBeacons := storagemock.NewVersionBeacons(suite.T()) + + events := []*flow.SealedVersionBeacon{ + { + VersionBeacon: unittest.VersionBeaconFixture( + unittest.WithBoundaries(flow.VersionBoundary{BlockHeight: nodeRootBlock.Height + 4, Version: "0.0.1"}), + ), + SealHeight: nodeRootBlock.Height + 2, + }, + { + VersionBeacon: unittest.VersionBeaconFixture( + unittest.WithBoundaries(flow.VersionBoundary{BlockHeight: nodeRootBlock.Height + 12, Version: "0.0.2"}), + ), + SealHeight: nodeRootBlock.Height + 10, + }, + { + VersionBeacon: unittest.VersionBeaconFixture( + unittest.WithBoundaries(flow.VersionBoundary{BlockHeight: latestBlockHeight - 8, Version: "0.0.3"}), + ), + SealHeight: latestBlockHeight - 10, + }, + } + + eventMap := make(map[uint64]*flow.SealedVersionBeacon, len(events)) + for _, event := range events { + eventMap[event.SealHeight] = event + } + + // make sure events are sorted descending by seal height + sort.Slice(events, func(i, j int) bool { + return events[i].SealHeight > events[j].SealHeight + }) + + versionBeacons. + On("Highest", mock.AnythingOfType("uint64")). + Return(func(height uint64) (*flow.SealedVersionBeacon, error) { + // iterating through events sorted descending by seal height + // return the first event that was sealed in a height less than or equal to height + for _, event := range events { + if event.SealHeight <= height { + return event, nil + } + } + return nil, storage.ErrNotFound + }) + + var err error + suite.versionControl, err = version.NewVersionControl( + unittest.Logger(), + versionBeacons, + semver.New("0.0.2"), + nodeRootBlock.Height, + latestBlockHeight, + ) + require.NoError(suite.T(), err) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + // Start the VersionControl component. + suite.versionControl.Start(irrecoverable.NewMockSignalerContext(suite.T(), ctx)) + unittest.RequireComponentsReadyBefore(suite.T(), 2*time.Second, suite.versionControl) + + stateParams := protocol.NewParams(suite.T()) + stateParams.On("SporkID").Return(sporkID, nil) + stateParams.On("ProtocolVersion").Return(protocolVersion, nil) + stateParams.On("SporkRootBlockHeight").Return(sporkRootBlock.Height, nil) + stateParams.On("SealedRoot").Return(nodeRootBlock, nil) + + state := protocol.NewState(suite.T()) + state.On("Params").Return(stateParams, nil).Maybe() + + expected := &access.NodeVersionInfo{ + Semver: build.Version(), + Commit: build.Commit(), + SporkId: sporkID, + ProtocolVersion: uint64(protocolVersion), + SporkRootBlockHeight: sporkRootBlock.Height, + NodeRootBlockHeight: nodeRootBlock.Height, + CompatibleRange: &access.CompatibleRange{ + StartHeight: nodeRootBlock.Height + 12, + EndHeight: latestBlockHeight - 9, + }, + } + + params := suite.defaultBackendParams() + params.State = state + + backend, err := New(params) + suite.Require().NoError(err) + + actual, err := backend.GetNodeVersionInfo(ctx) + suite.Require().NoError(err) + + suite.Require().Equal(expected, actual) + }) } func (suite *Suite) TestGetNetworkParameters() { @@ -2134,5 +2238,6 @@ func (suite *Suite) defaultBackendParams() Params { BlockTracker: nil, TxResultQueryMode: IndexQueryModeExecutionNodesOnly, LastFullBlockHeight: suite.lastFullBlockHeight, + VersionControl: suite.versionControl, } } diff --git a/engine/common/rpc/convert/compatible_range_test.go b/engine/common/rpc/convert/compatible_range_test.go new file mode 100644 index 00000000000..8424e7256d9 --- /dev/null +++ b/engine/common/rpc/convert/compatible_range_test.go @@ -0,0 +1,31 @@ +package convert_test + +import ( + "math/rand" + "testing" + + "github.com/onflow/flow/protobuf/go/flow/entities" + "github.com/stretchr/testify/assert" + + "github.com/onflow/flow-go/access" +) + +// TestConvertCompatibleRange tests that converting a compatible range to a protobuf message +func TestConvertCompatibleRange(t *testing.T) { + t.Parallel() + + startHeight := uint64(rand.Uint32()) + endHeight := uint64(rand.Uint32()) + + comparableRange := &access.CompatibleRange{ + StartHeight: startHeight, + EndHeight: endHeight, + } + expected := &entities.CompatibleRange{ + StartHeight: startHeight, + EndHeight: endHeight, + } + + msg := access.CompatibleRangeToMessage(comparableRange) + assert.Equal(t, msg, expected) +} diff --git a/engine/common/version/version_control.go b/engine/common/version/version_control.go index 79fa0287733..5bd45901114 100644 --- a/engine/common/version/version_control.go +++ b/engine/common/version/version_control.go @@ -359,3 +359,29 @@ func (v *VersionControl) blockFinalized( } } } + +// StartHeight return the first block that the version supports. +// Start height is the sealed root block if there is no start boundary in the current spork. +func (v *VersionControl) StartHeight() uint64 { + startHeight := v.startHeight.Load() + + // in case no start boundary in the current spork + if startHeight == NoHeight { + startHeight = v.sealedRootBlockHeight.Load() + } + + return startHeight +} + +// EndHeight return the last block that the version supports. +// End height is the last processed height if there is no end boundary in the current spork. +func (v *VersionControl) EndHeight() uint64 { + endHeight := v.endHeight.Load() + + // in case no end boundary in the current spork + if endHeight == NoHeight { + endHeight = v.lastProcessedHeight.Load() + } + + return endHeight +} diff --git a/go.mod b/go.mod index 54c7f970c47..6fc6dc77172 100644 --- a/go.mod +++ b/go.mod @@ -54,7 +54,7 @@ require ( github.com/onflow/flow-core-contracts/lib/go/contracts v1.3.1 github.com/onflow/flow-core-contracts/lib/go/templates v1.3.1 github.com/onflow/flow-go-sdk v1.0.0-preview.53 - github.com/onflow/flow/protobuf/go/flow v0.4.5 + github.com/onflow/flow/protobuf/go/flow v0.4.6 github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 github.com/pierrec/lz4 v2.6.1+incompatible github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index 1463899bfe0..d750ce109b2 100644 --- a/go.sum +++ b/go.sum @@ -2193,8 +2193,8 @@ github.com/onflow/flow-nft/lib/go/contracts v1.2.1/go.mod h1:2gpbza+uzs1k7x31hkp github.com/onflow/flow-nft/lib/go/templates v1.2.0 h1:JSQyh9rg0RC+D1930BiRXN8lrtMs+ubVMK6aQPon6Yc= github.com/onflow/flow-nft/lib/go/templates v1.2.0/go.mod h1:p+2hRvtjLUR3MW1NsoJe5Gqgr2eeH49QB6+s6ze00w0= github.com/onflow/flow/protobuf/go/flow v0.3.2-0.20231121210617-52ee94b830c2/go.mod h1:NA2pX2nw8zuaxfKphhKsk00kWLwfd+tv8mS23YXO4Sk= -github.com/onflow/flow/protobuf/go/flow v0.4.5 h1:6o+pgYGqwXdEhqSJxu2BdnDXkOQVOkfGAb6IiXB+NPM= -github.com/onflow/flow/protobuf/go/flow v0.4.5/go.mod h1:NA2pX2nw8zuaxfKphhKsk00kWLwfd+tv8mS23YXO4Sk= +github.com/onflow/flow/protobuf/go/flow v0.4.6 h1:KE/CsRVfyG5lGBtm1aNcjojMciQyS5GfPF3ixOWRfi0= +github.com/onflow/flow/protobuf/go/flow v0.4.6/go.mod h1:NA2pX2nw8zuaxfKphhKsk00kWLwfd+tv8mS23YXO4Sk= github.com/onflow/go-ethereum v1.14.7 h1:gg3awYqI02e3AypRdpJKEvNTJ6kz/OhAqRti0h54Wlc= github.com/onflow/go-ethereum v1.14.7/go.mod h1:zV14QLrXyYu5ucvcwHUA0r6UaqveqbXaehAVQJlSW+I= github.com/onflow/nft-storefront/lib/go/contracts v1.0.0 h1:sxyWLqGm/p4EKT6DUlQESDG1ZNMN9GjPCm1gTq7NGfc= diff --git a/insecure/go.mod b/insecure/go.mod index cb75a3ad34e..2c31ae9c8cd 100644 --- a/insecure/go.mod +++ b/insecure/go.mod @@ -210,7 +210,7 @@ require ( github.com/onflow/flow-go-sdk v1.0.0-preview.53 // indirect github.com/onflow/flow-nft/lib/go/contracts v1.2.1 // indirect github.com/onflow/flow-nft/lib/go/templates v1.2.0 // indirect - github.com/onflow/flow/protobuf/go/flow v0.4.5 // indirect + github.com/onflow/flow/protobuf/go/flow v0.4.6 // indirect github.com/onflow/go-ethereum v1.14.7 // indirect github.com/onflow/sdks v0.6.0-preview.1 // indirect github.com/onflow/wal v1.0.2 // indirect diff --git a/insecure/go.sum b/insecure/go.sum index 067f5159e23..616e2155cd0 100644 --- a/insecure/go.sum +++ b/insecure/go.sum @@ -2181,8 +2181,8 @@ github.com/onflow/flow-nft/lib/go/contracts v1.2.1/go.mod h1:2gpbza+uzs1k7x31hkp github.com/onflow/flow-nft/lib/go/templates v1.2.0 h1:JSQyh9rg0RC+D1930BiRXN8lrtMs+ubVMK6aQPon6Yc= github.com/onflow/flow-nft/lib/go/templates v1.2.0/go.mod h1:p+2hRvtjLUR3MW1NsoJe5Gqgr2eeH49QB6+s6ze00w0= github.com/onflow/flow/protobuf/go/flow v0.3.2-0.20231121210617-52ee94b830c2/go.mod h1:NA2pX2nw8zuaxfKphhKsk00kWLwfd+tv8mS23YXO4Sk= -github.com/onflow/flow/protobuf/go/flow v0.4.5 h1:6o+pgYGqwXdEhqSJxu2BdnDXkOQVOkfGAb6IiXB+NPM= -github.com/onflow/flow/protobuf/go/flow v0.4.5/go.mod h1:NA2pX2nw8zuaxfKphhKsk00kWLwfd+tv8mS23YXO4Sk= +github.com/onflow/flow/protobuf/go/flow v0.4.6 h1:KE/CsRVfyG5lGBtm1aNcjojMciQyS5GfPF3ixOWRfi0= +github.com/onflow/flow/protobuf/go/flow v0.4.6/go.mod h1:NA2pX2nw8zuaxfKphhKsk00kWLwfd+tv8mS23YXO4Sk= github.com/onflow/go-ethereum v1.14.7 h1:gg3awYqI02e3AypRdpJKEvNTJ6kz/OhAqRti0h54Wlc= github.com/onflow/go-ethereum v1.14.7/go.mod h1:zV14QLrXyYu5ucvcwHUA0r6UaqveqbXaehAVQJlSW+I= github.com/onflow/sdks v0.5.1-0.20230912225508-b35402f12bba/go.mod h1:F0dj0EyHC55kknLkeD10js4mo14yTdMotnWMslPirrU= diff --git a/integration/Makefile b/integration/Makefile index df840bebc8b..4893e0cc9ff 100644 --- a/integration/Makefile +++ b/integration/Makefile @@ -97,3 +97,10 @@ bft-gossipsub-tests: .PHONY: bft-tests bft-tests: bft-framework-tests bft-protocol-tests bft-gossipsub-tests +.PHONY: lint +lint: + golangci-lint run -v ./... + +.PHONY: fix-lint +fix-lint: + golangci-lint run -v --fix ./... diff --git a/integration/go.mod b/integration/go.mod index df4c093b150..dbc4a985f47 100644 --- a/integration/go.mod +++ b/integration/go.mod @@ -25,10 +25,10 @@ require ( github.com/onflow/flow-core-contracts/lib/go/contracts v1.3.1 github.com/onflow/flow-core-contracts/lib/go/templates v1.3.1 github.com/onflow/flow-emulator v1.0.0-preview.36.0.20240729195722-d4eb1c30eb9f - github.com/onflow/flow-go v0.36.8-0.20240729193633-433a32eeb0cd + github.com/onflow/flow-go v0.37.7-0.20240826193109-e211841b59f5 github.com/onflow/flow-go-sdk v1.0.0-preview.53 github.com/onflow/flow-go/insecure v0.0.0-00010101000000-000000000000 - github.com/onflow/flow/protobuf/go/flow v0.4.5 + github.com/onflow/flow/protobuf/go/flow v0.4.6 github.com/onflow/go-ethereum v1.14.7 github.com/prometheus/client_golang v1.18.0 github.com/prometheus/client_model v0.5.0 diff --git a/integration/go.sum b/integration/go.sum index 9ffd52257c9..5200631813b 100644 --- a/integration/go.sum +++ b/integration/go.sum @@ -2167,8 +2167,8 @@ github.com/onflow/flow-nft/lib/go/contracts v1.2.1/go.mod h1:2gpbza+uzs1k7x31hkp github.com/onflow/flow-nft/lib/go/templates v1.2.0 h1:JSQyh9rg0RC+D1930BiRXN8lrtMs+ubVMK6aQPon6Yc= github.com/onflow/flow-nft/lib/go/templates v1.2.0/go.mod h1:p+2hRvtjLUR3MW1NsoJe5Gqgr2eeH49QB6+s6ze00w0= github.com/onflow/flow/protobuf/go/flow v0.3.2-0.20231121210617-52ee94b830c2/go.mod h1:NA2pX2nw8zuaxfKphhKsk00kWLwfd+tv8mS23YXO4Sk= -github.com/onflow/flow/protobuf/go/flow v0.4.5 h1:6o+pgYGqwXdEhqSJxu2BdnDXkOQVOkfGAb6IiXB+NPM= -github.com/onflow/flow/protobuf/go/flow v0.4.5/go.mod h1:NA2pX2nw8zuaxfKphhKsk00kWLwfd+tv8mS23YXO4Sk= +github.com/onflow/flow/protobuf/go/flow v0.4.6 h1:KE/CsRVfyG5lGBtm1aNcjojMciQyS5GfPF3ixOWRfi0= +github.com/onflow/flow/protobuf/go/flow v0.4.6/go.mod h1:NA2pX2nw8zuaxfKphhKsk00kWLwfd+tv8mS23YXO4Sk= github.com/onflow/go-ethereum v1.14.7 h1:gg3awYqI02e3AypRdpJKEvNTJ6kz/OhAqRti0h54Wlc= github.com/onflow/go-ethereum v1.14.7/go.mod h1:zV14QLrXyYu5ucvcwHUA0r6UaqveqbXaehAVQJlSW+I= github.com/onflow/sdks v0.5.1-0.20230912225508-b35402f12bba/go.mod h1:F0dj0EyHC55kknLkeD10js4mo14yTdMotnWMslPirrU=