Skip to content

Commit

Permalink
add scroll repo version check
Browse files Browse the repository at this point in the history
  • Loading branch information
colinlyguo committed Mar 1, 2024
1 parent 48a9326 commit 77b92e1
Show file tree
Hide file tree
Showing 8 changed files with 185 additions and 10 deletions.
54 changes: 54 additions & 0 deletions common/version/prover_version.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package version

import (
"strconv"
"strings"

"github.com/scroll-tech/go-ethereum/log"
)

// CheckScrollProverVersion check the "scroll-prover" version, if it's different from the local one, return false
Expand All @@ -19,3 +22,54 @@ func CheckScrollProverVersion(proverVersion string) bool {
// compare the `scroll_prover` version
return remote[2] == local[2]
}

// parseVersion takes a version string and returns its major, minor, and patch numbers.
func parseVersion(version string) (major, minor, patch int) {
trimVersion := strings.TrimPrefix(version, "v")
if trimVersion == version {
log.Error("version does not start with v", "vesion", version)
return 0, 0, 0
}

versionPart := strings.SplitN(trimVersion, "-", 2)[0]
parts := strings.Split(versionPart, ".")
if len(parts) != 3 {
log.Error("invalid version format", "expected format", "v<major>.<minor>.<patch>", "got", version)
return 0, 0, 0
}

var err error
major, err = strconv.Atoi(parts[0])
if err != nil {
log.Error("invalid major version", "value", parts[0], "error", err)
return 0, 0, 0
}

minor, err = strconv.Atoi(parts[1])
if err != nil {
log.Error("invalid minor version", "value", parts[1], "error", err)
return 0, 0, 0
}

patch, err = strconv.Atoi(parts[2])
if err != nil {
log.Error("invalid patch version", "value", parts[2], "error", err)
return 0, 0, 0
}

return major, minor, patch
}

// CheckScrollRepoVersion checks if the proverVersion is at least the minimum required version.
func CheckScrollRepoVersion(proverVersion, minVersion string) bool {
major1, minor1, patch1 := parseVersion(proverVersion)
major2, minor2, patch2 := parseVersion(minVersion)

if major1 != major2 {
return major1 > major2
}
if minor1 != minor2 {
return minor1 > minor2
}
return patch1 >= patch2
}
80 changes: 80 additions & 0 deletions common/version/prover_version_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package version

import (
"os"
"testing"

"github.com/scroll-tech/go-ethereum/log"
)

func TestMain(m *testing.M) {
glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.LogfmtFormat()))
glogger.Verbosity(log.LvlInfo)
log.Root().SetHandler(glogger)

m.Run()
}

func TestCheckScrollProverVersion(t *testing.T) {
tests := []struct {
proverVersion string
want bool
}{
{Version, true},
{"tag-commit-111111-000000", false},
{"incorrect-format", false},
{"tag-commit-222222-111111", false},
}

for _, tt := range tests {
if got := CheckScrollProverVersion(tt.proverVersion); got != tt.want {
t.Errorf("CheckScrollProverVersion(%q) = %v, want %v", tt.proverVersion, got, tt.want)
}
}
}

func TestParseVersion(t *testing.T) {
tests := []struct {
version string
wantMajor int
wantMinor int
wantPatch int
}{
{"v1.2.3-commit-111111-000000", 1, 2, 3},
{"v0.10.0-patch-commit-111111-000000", 0, 10, 0},
{"v2.0.1-alpha", 2, 0, 1},
{"v10.0.0", 10, 0, 0},
{"v1.0", 0, 0, 0}, // Invalid format
{"v..", 0, 0, 0}, // Invalid format
}

for _, tt := range tests {
gotMajor, gotMinor, gotPatch := parseVersion(tt.version)
if gotMajor != tt.wantMajor || gotMinor != tt.wantMinor || gotPatch != tt.wantPatch {
t.Errorf("parseVersion(%q) = %v, %v, %v, want %v, %v, %v", tt.version, gotMajor, gotMinor, gotPatch, tt.wantMajor, tt.wantMinor, tt.wantPatch)
}
}
}

func TestCheckScrollRepoVersion(t *testing.T) {
tests := []struct {
proverVersion string
minVersion string
want bool
}{
{"v1.2.3-commit-111111-000000", "v1.2.3", true},
{"v1.2.3-patch-commit-111111-000000", "v1.2.2", true},
{"v1.0.0-alpha", "v1.0.0", true},
{"v1.2.2", "v1.2.3", false},
{"v2.0.0", "v1.9.9", true},
{"v0.9.0", "v1.0.0", false},
{"v9.9.9", "v10.0.0", false},
{"v4.1.98-aaa-bbb-ccc", "v999.0.0", false},
}

for _, tt := range tests {
if got := CheckScrollRepoVersion(tt.proverVersion, tt.minVersion); got != tt.want {
t.Errorf("CheckScrollRepoVersion(%q, %q) = %v, want %v", tt.proverVersion, tt.minVersion, got, tt.want)
}
}
}
1 change: 1 addition & 0 deletions coordinator/cmd/api/app/mock_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ func (c *CoordinatorApp) MockConfig(store bool) error {
ChunkCollectionTimeSec: 60,
SessionAttempts: 10,
MaxVerifierWorkers: 4,
MinProverVersion: "v1.0.0",
}
cfg.DB.DSN = base.DBImg.Endpoint()
cfg.L2.ChainID = 111
Expand Down
3 changes: 2 additions & 1 deletion coordinator/conf/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"params_path": "",
"assets_path": ""
},
"max_verifier_workers": 4
"max_verifier_workers": 4,
"min_prover_version": "v1.0.0"
},
"db": {
"driver_name": "postgres",
Expand Down
2 changes: 2 additions & 0 deletions coordinator/internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ type ProverManager struct {
ChunkCollectionTimeSec int `json:"chunk_collection_time_sec"`
// Max number of workers in verifier worker pool
MaxVerifierWorkers int `json:"max_verifier_workers"`
// MinProverVersion is the minimum version of the prover that is required.
MinProverVersion string `json:"min_prover_version"`
}

// L2 loads l2geth configuration items.
Expand Down
3 changes: 2 additions & 1 deletion coordinator/internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ func TestConfig(t *testing.T) {
"params_path": "",
"agg_vk_path": ""
},
"max_verifier_workers": 4
"max_verifier_workers": 4,
"min_prover_version": "v1.0.0"
},
"db": {
"driver_name": "postgres",
Expand Down
4 changes: 4 additions & 0 deletions coordinator/internal/logic/provertask/prover_task.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ func (b *BaseProverTask) checkParameter(ctx *gin.Context, getTaskParameter *coor
}
ptc.ProverVersion = proverVersion.(string)

if !version.CheckScrollRepoVersion(proverVersion.(string), b.cfg.ProverManager.MinProverVersion) {
return nil, fmt.Errorf("incompatible prover version. please upgrade your prover, minimum allowed version: %s, actual version: %s", b.cfg.ProverManager.MinProverVersion, proverVersion.(string))
}

// if the prover has a different vk
if getTaskParameter.VK != b.vk {
// if the prover reports a different prover version
Expand Down
48 changes: 40 additions & 8 deletions coordinator/test/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"time"

"github.com/gin-gonic/gin"
"github.com/scroll-tech/go-ethereum/log"
"github.com/stretchr/testify/assert"
"gorm.io/gorm"

Expand Down Expand Up @@ -53,6 +54,10 @@ var (
)

func TestMain(m *testing.M) {
glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.LogfmtFormat()))
glogger.Verbosity(log.LvlInfo)
log.Root().SetHandler(glogger)

base = docker.NewDockerApp()
m.Run()
base.Free()
Expand All @@ -63,7 +68,7 @@ func randomURL() string {
return fmt.Sprintf("localhost:%d", 10000+2000+id.Int64())
}

func setupCoordinator(t *testing.T, proversPerSession uint8, coordinatorURL string) (*cron.Collector, *http.Server) {
func setupCoordinator(t *testing.T, proversPerSession uint8, coordinatorURL string, proverVersion string) (*cron.Collector, *http.Server) {
var err error
db, err = database.InitDB(dbCfg)
assert.NoError(t, err)
Expand All @@ -83,6 +88,7 @@ func setupCoordinator(t *testing.T, proversPerSession uint8, coordinatorURL stri
ChunkCollectionTimeSec: 10,
MaxVerifierWorkers: 10,
SessionAttempts: 5,
MinProverVersion: proverVersion,
},
Auth: &config.Auth{
ChallengeExpireDurationSec: tokenTimeout,
Expand Down Expand Up @@ -160,6 +166,7 @@ func TestApis(t *testing.T) {
t.Run("TestHandshake", testHandshake)
t.Run("TestFailedHandshake", testFailedHandshake)
t.Run("TestGetTaskBlocked", testGetTaskBlocked)
t.Run("TestOutdatedProverVersion", testOutdatedProverVersion)
t.Run("TestValidProof", testValidProof)
t.Run("TestInvalidProof", testInvalidProof)
t.Run("TestProofGeneratedFailed", testProofGeneratedFailed)
Expand All @@ -174,7 +181,7 @@ func TestApis(t *testing.T) {
func testHandshake(t *testing.T) {
// Setup coordinator and http server.
coordinatorURL := randomURL()
proofCollector, httpHandler := setupCoordinator(t, 1, coordinatorURL)
proofCollector, httpHandler := setupCoordinator(t, 1, coordinatorURL, version.Version)
defer func() {
proofCollector.Stop()
assert.NoError(t, httpHandler.Shutdown(context.Background()))
Expand All @@ -187,7 +194,7 @@ func testHandshake(t *testing.T) {
func testFailedHandshake(t *testing.T) {
// Setup coordinator and http server.
coordinatorURL := randomURL()
proofCollector, httpHandler := setupCoordinator(t, 1, coordinatorURL)
proofCollector, httpHandler := setupCoordinator(t, 1, coordinatorURL, version.Version)
defer func() {
proofCollector.Stop()
}()
Expand All @@ -205,7 +212,7 @@ func testFailedHandshake(t *testing.T) {

func testGetTaskBlocked(t *testing.T) {
coordinatorURL := randomURL()
collector, httpHandler := setupCoordinator(t, 3, coordinatorURL)
collector, httpHandler := setupCoordinator(t, 3, coordinatorURL, version.Version)
defer func() {
collector.Stop()
assert.NoError(t, httpHandler.Shutdown(context.Background()))
Expand Down Expand Up @@ -247,9 +254,34 @@ func testGetTaskBlocked(t *testing.T) {
assert.Equal(t, expectedErr, fmt.Errorf(errMsg))
}

func testOutdatedProverVersion(t *testing.T) {
coordinatorURL := randomURL()
collector, httpHandler := setupCoordinator(t, 3, coordinatorURL, "v999.0.0")
defer func() {
collector.Stop()
assert.NoError(t, httpHandler.Shutdown(context.Background()))
}()

chunkProver := newMockProver(t, "prover_chunk_test", coordinatorURL, message.ProofTypeChunk)
assert.True(t, chunkProver.healthCheckSuccess(t))

batchProver := newMockProver(t, "prover_batch_test", coordinatorURL, message.ProofTypeBatch)
assert.True(t, chunkProver.healthCheckSuccess(t))

expectedErr := fmt.Errorf("return prover task err:check prover task parameter failed, error:incompatible prover version. please upgrade your prover, minimum allowed version: v999.0.0, actual version: %s", chunkProver.proverVersion)
code, errMsg := chunkProver.tryGetProverTask(t, message.ProofTypeChunk)
assert.Equal(t, types.ErrCoordinatorGetTaskFailure, code)
assert.Equal(t, expectedErr, fmt.Errorf(errMsg))

expectedErr = fmt.Errorf("return prover task err:check prover task parameter failed, error:incompatible prover version. please upgrade your prover, minimum allowed version: v999.0.0, actual version: %s", batchProver.proverVersion)
code, errMsg = batchProver.tryGetProverTask(t, message.ProofTypeBatch)
assert.Equal(t, types.ErrCoordinatorGetTaskFailure, code)
assert.Equal(t, expectedErr, fmt.Errorf(errMsg))
}

func testValidProof(t *testing.T) {
coordinatorURL := randomURL()
collector, httpHandler := setupCoordinator(t, 3, coordinatorURL)
collector, httpHandler := setupCoordinator(t, 3, coordinatorURL, version.Version)
defer func() {
collector.Stop()
assert.NoError(t, httpHandler.Shutdown(context.Background()))
Expand Down Expand Up @@ -333,7 +365,7 @@ func testValidProof(t *testing.T) {
func testInvalidProof(t *testing.T) {
// Setup coordinator and ws server.
coordinatorURL := randomURL()
collector, httpHandler := setupCoordinator(t, 3, coordinatorURL)
collector, httpHandler := setupCoordinator(t, 3, coordinatorURL, version.Version)
defer func() {
collector.Stop()
assert.NoError(t, httpHandler.Shutdown(context.Background()))
Expand Down Expand Up @@ -409,7 +441,7 @@ func testInvalidProof(t *testing.T) {
func testProofGeneratedFailed(t *testing.T) {
// Setup coordinator and ws server.
coordinatorURL := randomURL()
collector, httpHandler := setupCoordinator(t, 3, coordinatorURL)
collector, httpHandler := setupCoordinator(t, 3, coordinatorURL, version.Version)
defer func() {
collector.Stop()
assert.NoError(t, httpHandler.Shutdown(context.Background()))
Expand Down Expand Up @@ -496,7 +528,7 @@ func testProofGeneratedFailed(t *testing.T) {
func testTimeoutProof(t *testing.T) {
// Setup coordinator and ws server.
coordinatorURL := randomURL()
collector, httpHandler := setupCoordinator(t, 1, coordinatorURL)
collector, httpHandler := setupCoordinator(t, 1, coordinatorURL, version.Version)
defer func() {
collector.Stop()
assert.NoError(t, httpHandler.Shutdown(context.Background()))
Expand Down

0 comments on commit 77b92e1

Please sign in to comment.