Skip to content

Commit

Permalink
Merge pull request #3360 from oasisprotocol/tjanez/change-protocol-ve…
Browse files Browse the repository at this point in the history
…rsion-compare

Compare protocol versions according to SemVer 2.0.0
  • Loading branch information
tjanez authored Oct 7, 2020
2 parents 24c3a61 + fb701bd commit f580ad1
Show file tree
Hide file tree
Showing 17 changed files with 64 additions and 49 deletions.
14 changes: 14 additions & 0 deletions .changelog/3360.breaking.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Compare protocol versions according to SemVer 2.0.0

As described in our [Versioning] document, we bumped the protocol versions to
version 1.0.0 with the release of [Oasis Core 20.10].

Hence, we also need to modify how we compare and detect backward-incompatible
changes to follow SemVer 2.0.0 rules.

From now onwards, only a change in a protocol's major version signifies
a backward-incompatible change.

[Versioning]: docs/versioning.md#version-100
[Oasis Core 20.10]:
https://github.com/oasisprotocol/oasis-core/blob/v20.10/CHANGELOG.md
1 change: 1 addition & 0 deletions .changelog/3360.breaking.2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
go/common/version: Remove `MajorMinor()` method from `Version` type
1 change: 1 addition & 0 deletions .changelog/3360.doc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Rename Versioning scheme document to Versioning and include it in the index
1 change: 1 addition & 0 deletions .changelog/3360.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
go/common/version: Add `MaskNonMajor()` method to `Version` type
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,4 @@ implementations.

* [Architectural Decision Records](adr/index.md)
* [Release Process](release-process.md)
* [Versioning](versioning.md)
1 change: 1 addition & 0 deletions docs/toc.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,4 @@

* [Architectural Decision Records](adr/index.md)
* [Release Process](release-process.md)
* [Versioning](versioning.md)
22 changes: 7 additions & 15 deletions docs/versioning.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Versioning scheme
# Versioning

## Oasis Core

Expand Down Expand Up @@ -67,21 +67,13 @@ the `MINOR` version must be bumped.
When only backwards compatible bug fixes are made to a protocol, the `PATCH`
version should be bumped.

### Pre-Mainnet protocol versioning
### Version 1.0.0

Until Oasis Network has reached the Mainnet phase, the `MAJOR` version of all
protocols version is set to 0. This indicates that this is not yet a production
version of the protocols and backwards incompatible changes may happen
frequently.

For this reason, Oasis Core currently considers a change in protocol’s minor
version, a breaking change.

### Mainnet and version 1.0.0

When we will prepare an Oasis Core release for the Mainnet, we will bump the
protocol versions to version 1.0.0 which will [signify that they are ready for
production use](https://semver.org/#how-do-i-know-when-to-release-100).
With the release of [Oasis Core 20.10], we bumped the protocol versions to
version 1.0.0 which [signified that they are ready for production use](
https://semver.org/#how-do-i-know-when-to-release-100).

[CalVer]: http://calver.org
[SemVer]: https://semver.org/
[Oasis Core 20.10]:
https://github.com/oasisprotocol/oasis-core/blob/v20.10/CHANGELOG.md
31 changes: 23 additions & 8 deletions go/common/version/version.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
// Package version implements Oasis protocol and runtime versioning.
//
// For a more detailed explanation of Oasis Core's versioning, see:
// https://docs.oasis.dev/oasis-core/processes/versioning.
package version

import (
Expand All @@ -12,7 +15,7 @@ import (

// NOTE: This should be kept in sync with runtime/src/common/version.rs.

// Version is a protocol or a runtime version.
// Version is a protocol version.
type Version struct {
Major uint16 `json:"major,omitempty"`
Minor uint16 `json:"minor,omitempty"`
Expand All @@ -38,14 +41,15 @@ func (v Version) String() string {
return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
}

// MajorMinor extracts major and minor segments of the Version only.
// MaskNonMajor masks all non-major version segments to 0 and returns a new
// protocol version.
//
// This is useful for comparing protocol version since the patch segment can be
// ignored.
func (v Version) MajorMinor() Version {
// This is useful for comparing protocol versions for backward-incompatible
// changes.
func (v Version) MaskNonMajor() Version {
return Version{
Major: v.Major,
Minor: v.Minor,
Minor: 0,
Patch: 0,
}
}
Expand Down Expand Up @@ -74,10 +78,21 @@ var (
// the epochtime, beacon, registry, roothash, etc. modules that are
// backend by consensus.
//
// NOTE: Any change in the major or minor versions are considered
// breaking changes for the protocol.
// NOTE: Consensus protocol version compatibility is currently not directly
// checked in Oasis Core.
// It is converted to TendermintAppVersion whose compatibility is checked
// via Tendermint's version checks.
ConsensusProtocol = Version{Major: 1, Minor: 0, Patch: 0}

// TendermintAppVersion is Tendermint ABCI application's version computed by
// masking non-major consensus protocol version segments to 0 to be
// compatible with Tendermint's version checks.
//
// NOTE: Tendermint's version checks compare the whole version uint64
// directly. For example:
// https://github.com/tendermint/tendermint/blob/1635d1339c73ae6a82e062cd2dc7191b029efa14/state/validation.go#L21-L22.
TendermintAppVersion = ConsensusProtocol.MaskNonMajor().ToU64()

// Tendermint exposes the tendermint core version.
Tendermint = parseSemVerStr(version.TMCoreSemVer)

Expand Down
12 changes: 6 additions & 6 deletions go/common/version/version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ import (
"github.com/stretchr/testify/require"
)

func TestMajorMinor(t *testing.T) {
func TestMaskNonMajor(t *testing.T) {
require := require.New(t)

v1 := Version{1, 1, 0}
v2 := Version{1, 1, 5}
v3 := Version{1, 1, 10}
require.Equal(v1.MajorMinor(), v2.MajorMinor(), "version.MajorMinor() should match")
require.Equal(v2.MajorMinor(), v3.MajorMinor(), "version.MajorMinor() should match")
v4 := Version{1, 2, 0}
require.NotEqual(v1.MajorMinor(), v4.MajorMinor(), "version.MajorMinor() should not match")
v3 := Version{1, 4, 10}
require.Equal(v1.MaskNonMajor(), v2.MaskNonMajor(), "version.MaskNonMajor() should match")
require.Equal(v2.MaskNonMajor(), v3.MaskNonMajor(), "version.MaskNonMajor() should match")
v4 := Version{2, 1, 0}
require.NotEqual(v1.MaskNonMajor(), v4.MaskNonMajor(), "version.MaskNonMajor() should not match")
}

func TestParseSemVer(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions go/consensus/tendermint/abci/mux.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ func (mux *abciMux) registerHaltHook(hook func(context.Context, int64, epochtime

func (mux *abciMux) Info(req types.RequestInfo) types.ResponseInfo {
return types.ResponseInfo{
AppVersion: version.ConsensusProtocol.ToU64(),
AppVersion: version.TendermintAppVersion,
LastBlockHeight: mux.state.BlockHeight(),
LastBlockAppHash: mux.state.BlockHash(),
}
Expand Down Expand Up @@ -767,7 +767,7 @@ func (mux *abciMux) EndBlock(req types.RequestEndBlock) types.ResponseEndBlock {
// Update version to what we are actually running.
resp.ConsensusParamUpdates = &types.ConsensusParams{
Version: &tmproto.VersionParams{
AppVersion: version.ConsensusProtocol.ToU64(),
AppVersion: version.TendermintAppVersion,
},
}

Expand Down
2 changes: 1 addition & 1 deletion go/consensus/tendermint/api/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func genesisToTendermint(d *genesis.Document) (*tmtypes.GenesisDoc, error) {
PubKeyTypes: []string{tmtypes.ABCIPubKeyTypeEd25519},
},
Version: tmproto.VersionParams{
AppVersion: version.ConsensusProtocol.ToU64(),
AppVersion: version.TendermintAppVersion,
},
},
AppState: b,
Expand Down
2 changes: 1 addition & 1 deletion go/consensus/tendermint/full/statesync.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func (sp *stateProvider) State(ctx context.Context, height uint64) (tmstate.Stat
InitialHeight: sp.genesisDocument.InitialHeight,
}
// XXX: This will fail in case an upgrade happened in-between.
state.Version.Consensus.App = version.ConsensusProtocol.ToU64()
state.Version.Consensus.App = version.TendermintAppVersion

// The snapshot height maps onto the state heights as follows:
//
Expand Down
2 changes: 1 addition & 1 deletion go/consensus/tendermint/seed/seed.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ func New(dataDir string, identity *identity.Identity, genesisProvider genesis.Pr
ProtocolVersion: p2p.NewProtocolVersion(
tmversion.P2PProtocol,
tmversion.BlockProtocol,
version.ConsensusProtocol.ToU64(),
version.TendermintAppVersion,
),
DefaultNodeID: nodeKey.ID(),
ListenAddr: viper.GetString(tmcommon.CfgCoreListenAddress),
Expand Down
2 changes: 1 addition & 1 deletion go/consensus/tendermint/tests/genesis/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func NewTestNodeGenesisProvider(identity *identity.Identity) (genesis.Provider,
AppState: b,
}
tmDoc.ConsensusParams.Version = tmproto.VersionParams{
AppVersion: version.ConsensusProtocol.ToU64(),
AppVersion: version.TendermintAppVersion,
}

nodeID := identity.ConsensusSigner.Public()
Expand Down
2 changes: 1 addition & 1 deletion go/runtime/host/protocol/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ func (c *connection) InitHost(ctx context.Context, conn net.Conn) (*version.Vers
}

info := rsp.RuntimeInfoResponse
if ver := version.FromU64(info.ProtocolVersion); ver.MajorMinor() != version.RuntimeHostProtocol.MajorMinor() {
if ver := version.FromU64(info.ProtocolVersion); ver.Major != version.RuntimeHostProtocol.Major {
c.logger.Error("runtime has incompatible protocol version",
"version", ver,
"expected_version", version.RuntimeHostProtocol,
Expand Down
4 changes: 2 additions & 2 deletions go/worker/common/p2p/p2p.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,9 @@ func (p *P2P) handleConnection(conn core.Conn) {
}

func (p *P2P) topicIDForRuntime(runtimeID common.Namespace) string {
return fmt.Sprintf("%s/%s/%s",
return fmt.Sprintf("%s/%d/%s",
p.chainContext,
version.RuntimeCommitteeProtocol.MajorMinor().String(),
version.RuntimeCommitteeProtocol.Major,
runtimeID.String(),
)
}
Expand Down
11 changes: 0 additions & 11 deletions runtime/src/common/version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,6 @@ impl Version {
patch: patch,
}
}

/// Extract major and minor segments of the Version only.
///
/// This is useful for comparing protocol version since the patch segment can be ignored.
pub fn major_minor(&self) -> Version {
Version {
major: self.major,
minor: self.minor,
patch: 0,
}
}
}

// Returns the version as a platform-dependent u64.
Expand Down

0 comments on commit f580ad1

Please sign in to comment.