Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement reading all wasm module roots in machine locator [NIT-2444] #2254

Merged
merged 6 commits into from
Apr 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 61 additions & 21 deletions validator/server_common/machine_locator.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,28 @@ import (
"strings"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
)

type MachineLocator struct {
rootPath string
latest common.Hash
rootPath string
latest common.Hash
moduleRoots []common.Hash
}

var ErrMachineNotFound = errors.New("machine not found")

func NewMachineLocator(rootPath string) (*MachineLocator, error) {
var places []string

if rootPath != "" {
places = append(places, rootPath)
} else {
dirs := []string{rootPath}
if rootPath == "" {
// Check the project dir: <project>/arbnode/node.go => ../../target/machines
_, thisFile, _, ok := runtime.Caller(0)
if !ok {
panic("failed to find root path")
}
projectDir := filepath.Dir(filepath.Dir(filepath.Dir(thisFile)))
projectPath := filepath.Join(filepath.Join(projectDir, "target"), "machines")
places = append(places, projectPath)
dirs = append(dirs, projectPath)

// Check the working directory: ./machines and ./target/machines
workDir, err := os.Getwd()
Expand All @@ -39,31 +38,68 @@ func NewMachineLocator(rootPath string) (*MachineLocator, error) {
}
workPath1 := filepath.Join(workDir, "machines")
workPath2 := filepath.Join(filepath.Join(workDir, "target"), "machines")
places = append(places, workPath1)
places = append(places, workPath2)
dirs = append(dirs, workPath1)
dirs = append(dirs, workPath2)

// Check above the executable: <binary> => ../../machines
execfile, err := os.Executable()
if err != nil {
return nil, err
}
execPath := filepath.Join(filepath.Dir(filepath.Dir(execfile)), "machines")
places = append(places, execPath)
dirs = append(dirs, execPath)
}

for _, place := range places {
if _, err := os.Stat(place); err == nil {
var latestModuleRoot common.Hash
latestModuleRootPath := filepath.Join(place, "latest", "module-root.txt")
fileBytes, err := os.ReadFile(latestModuleRootPath)
if err == nil {
s := strings.TrimSpace(string(fileBytes))
latestModuleRoot = common.HexToHash(s)
var (
moduleRoots = make(map[common.Hash]bool)
latestModuleRoot common.Hash
)

for _, dir := range dirs {
fInfo, err := os.Stat(dir)
if err != nil {
log.Warn("Getting file info", "error", err)
continue
}
if !fInfo.IsDir() {
// Skip files that are not directories.
continue
}
files, err := os.ReadDir(dir)
if err != nil {
log.Warn("Reading directory", "dir", dir, "error", err)
}
for _, file := range files {
mrFile := filepath.Join(dir, file.Name(), "module-root.txt")
if _, err := os.Stat(mrFile); errors.Is(err, os.ErrNotExist) {
// Skip if module-roots file does not exist.
continue
}
mrContent, err := os.ReadFile(mrFile)
if err != nil {
log.Warn("Reading module roots file", "file path", mrFile, "error", err)
continue
}
moduleRoot := common.HexToHash(strings.TrimSpace(string(mrContent)))
if file.Name() != "latest" && file.Name() != moduleRoot.Hex() {
continue
}
moduleRoots[moduleRoot] = true
if file.Name() == "latest" {
latestModuleRoot = moduleRoot
rootPath = dir
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rootpath=dir doesn't belong in the latest "if". machines might not have a "latest" and it'd still be correct

}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only include dirs if their name is either "latest" or the wasmMduleRoot - otherwise locator will not be able to find it
see GetMachinePath.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't that exactly what I'm doing already ? Iterating all folders, checking if there's module-root.txt then reading file content (which is same as directory name if it's not "latest"), then adding to moduleRoots.

Or am I missing something ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you have a file "foobar/module-root.txt" - you cannot use this module-root because the locator won't be able to find "foobar" dir later. We can change that in GetMachinePath.. but easier to just not include it in the list.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, ptal.

return &MachineLocator{place, latestModuleRoot}, nil
}
}
return nil, ErrMachineNotFound
var roots []common.Hash
for k := range moduleRoots {
roots = append(roots, k)
}
return &MachineLocator{
rootPath: rootPath,
latest: latestModuleRoot,
moduleRoots: roots,
}, nil
}

func (l MachineLocator) GetMachinePath(moduleRoot common.Hash) string {
Expand All @@ -81,3 +117,7 @@ func (l MachineLocator) LatestWasmModuleRoot() common.Hash {
func (l MachineLocator) RootPath() string {
return l.rootPath
}

func (l MachineLocator) ModuleRoots() []common.Hash {
return l.moduleRoots
}
36 changes: 36 additions & 0 deletions validator/server_common/machine_locator_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package server_common

import (
"sort"
"testing"

"github.com/google/go-cmp/cmp"
)

var (
wantLatestModuleRoot = "0xf4389b835497a910d7ba3ebfb77aa93da985634f3c052de1290360635be40c4a"
wantModuleRoots = []string{
"0x8b104a2e80ac6165dc58b9048de12f301d70b02a0ab51396c22b4b4b802a16a4",
"0x68e4fe5023f792d4ef584796c84d710303a5e12ea02d6e37e2b5e9c4332507c4",
"0xf4389b835497a910d7ba3ebfb77aa93da985634f3c052de1290360635be40c4a",
}
)

func TestNewMachineLocator(t *testing.T) {
ml, err := NewMachineLocator("testdata")
if err != nil {
t.Fatalf("Error creating new machine locator: %v", err)
}
if ml.latest.Hex() != wantLatestModuleRoot {
t.Errorf("NewMachineLocator() got latestModuleRoot: %v, want: %v", ml.latest, wantLatestModuleRoot)
}
var got []string
for _, s := range ml.ModuleRoots() {
got = append(got, s.Hex())
}
sort.Strings(got)
sort.Strings(wantModuleRoots)
if diff := cmp.Diff(got, wantModuleRoots); diff != "" {
t.Errorf("NewMachineLocator() unexpected diff (-want +got):\n%s", diff)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0x68e4fe5023f792d4ef584796c84d710303a5e12ea02d6e37e2b5e9c4332507c4
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0x8b104a2e80ac6165dc58b9048de12f301d70b02a0ab51396c22b4b4b802a16a4
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0xf4389b835497a910d7ba3ebfb77aa93da985634f3c052de1290360635be40c4a
1 change: 1 addition & 0 deletions validator/server_common/testdata/latest
Loading