diff --git a/go.mod b/go.mod index 91ce2782224..4c3ccc4d5ce 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,8 @@ module github.com/ava-labs/libevm go 1.20 +retract v1.13.14-0.1.0-rc.1 // bad semver format ("0-rc" grouping) considered > .rc-2 + require ( github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0 github.com/Microsoft/go-winio v0.6.1 diff --git a/params/version.libevm.go b/params/version.libevm.go new file mode 100644 index 00000000000..463e6f7420d --- /dev/null +++ b/params/version.libevm.go @@ -0,0 +1,93 @@ +// Copyright 2024 the libevm authors. +// +// The libevm additions to go-ethereum are free software: you can redistribute +// them and/or modify them under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// The libevm additions are distributed in the hope that they will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser +// General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see +// . + +package params + +import "fmt" + +const ( + LibEVMVersionMajor = 0 + LibEVMVersionMinor = 1 + LibEVMVersionPatch = 0 + + libEVMReleaseType releaseType = betaRelease + libEVMReleaseCandidate uint = 0 // ignored unless [libEVMReleaseType] == [releaseCandidate] +) + +// LibEVMVersion holds the textual version string of `libevm` modifications. +// +// Although compliant with [semver v2], it follows additional rules: +// +// 1. Major, minor, and patch MUST be the respective `geth` values; +// 2. The first three pre-release identifiers MUST be a semver-compliant +// triplet denoting the `libevm` "version"; +// 3. On the `main` (development) branch, the final identifier MUST be "alpha" +// or "beta"; +// 3. If a production version, the final identifier MUST be "release"; and +// 4. If a release candidate, the final two identifiers MUST be "rc" and an +// incrementing numeric value. +// +// The benefits of this pattern are that (a) it captures all relevant +// information; and (b) it follows an intuitive ordering under semver rules. +// Precedence is determined first by the `geth` version then the `libevm` +// version, with release candidates being lower than actual releases. +// +// The primary drawbacks is that it requires an explicit "release" identifier +// because of the use of pre-release identifiers to capture the `libevm` +// triplet. +// +// [semver v2]: https://semver.org/ +var LibEVMVersion = func() string { + v := libEVMSemver{ + geth: semverTriplet{VersionMajor, VersionMinor, VersionPatch}, + libEVM: semverTriplet{LibEVMVersionMajor, LibEVMVersionMinor, LibEVMVersionPatch}, + typ: libEVMReleaseType, + rc: libEVMReleaseCandidate, + } + return v.String() +}() + +type semverTriplet struct { + major, minor, patch uint +} + +func (t semverTriplet) String() string { + return fmt.Sprintf("%d.%d.%d", t.major, t.minor, t.patch) +} + +type releaseType string + +const ( + // betaRelease MUST be used on `main` branch + betaRelease = releaseType("beta") + // Reserved for `release/*` branches + releaseCandidate = releaseType("rc") + productionRelease = releaseType("release") +) + +type libEVMSemver struct { + geth, libEVM semverTriplet + typ releaseType + rc uint +} + +func (v libEVMSemver) String() string { + suffix := v.typ + if suffix == releaseCandidate { + suffix = releaseType(fmt.Sprintf("%s.%d", suffix, v.rc)) + } + return fmt.Sprintf("%s-%s.%s", v.geth, v.libEVM, suffix) +} diff --git a/params/version.libevm_test.go b/params/version.libevm_test.go new file mode 100644 index 00000000000..b8a1d66e241 --- /dev/null +++ b/params/version.libevm_test.go @@ -0,0 +1,86 @@ +// Copyright 2024 the libevm authors. +// +// The libevm additions to go-ethereum are free software: you can redistribute +// them and/or modify them under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// The libevm additions are distributed in the hope that they will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser +// General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see +// . + +package params + +import ( + "testing" + + "golang.org/x/mod/semver" +) + +func TestLibEVMVersioning(t *testing.T) { + // We have an unusual version structure as defined by [LibEVMVersion] that + // is easy to mess up, so it's easier to just automate it and test the + // ordering assumptions. + + // This is a deliberate change-detector test to provide us with a copyable + // string of the current version, useful for git tagging. + const curr = "1.13.14-0.1.0.beta" + if got, want := LibEVMVersion, curr; got != want { + t.Errorf("got LibEVMVersion %q; want %q", got, want) + } + + ordered := []libEVMSemver{ + { + semverTriplet{1, 13, 14}, + semverTriplet{0, 1, 0}, + betaRelease, + 0, // ignored + }, + { + semverTriplet{1, 13, 14}, + semverTriplet{0, 1, 0}, + releaseCandidate, 1, + }, + { + semverTriplet{1, 13, 14}, + semverTriplet{0, 1, 0}, + releaseCandidate, 2, + }, + { + semverTriplet{1, 13, 14}, + semverTriplet{0, 1, 0}, + productionRelease, + 0, // ignored, + }, + { + semverTriplet{1, 13, 14}, + semverTriplet{0, 1, 1}, // bump takes precedence + betaRelease, 0, + }, + { + semverTriplet{1, 13, 14}, + semverTriplet{0, 1, 1}, + productionRelease, 0, + }, + { + semverTriplet{1, 13, 15}, // bump takes precedence + semverTriplet{0, 1, 1}, + betaRelease, 0, + }, + } + + for i, low := range ordered[:len(ordered)-1] { + // The `go mod` semver package requires the "v" prefix, which + // technically isn't valid semver. + lo := "v" + low.String() + hi := "v" + ordered[i+1].String() + if got := semver.Compare(lo, hi); got != -1 { + t.Errorf("Version pattern is not strictly ordered; semver.Compare(%q, %q) = %d", lo, hi, got) + } + } +}