diff --git a/arbcompress/native.go b/arbcompress/native.go index 4624d6222e..8244010979 100644 --- a/arbcompress/native.go +++ b/arbcompress/native.go @@ -12,7 +12,10 @@ package arbcompress #include "arbitrator.h" */ import "C" -import "fmt" +import ( + "errors" + "fmt" +) type u8 = C.uint8_t type u32 = C.uint32_t @@ -44,6 +47,8 @@ func Compress(input []byte, level uint32, dictionary Dictionary) ([]byte, error) return output, nil } +var ErrOutputWontFit = errors.New("output won't fit in maxsize") + func Decompress(input []byte, maxSize int) ([]byte, error) { return DecompressWithDictionary(input, maxSize, EmptyDictionary) } @@ -54,6 +59,9 @@ func DecompressWithDictionary(input []byte, maxSize int, dictionary Dictionary) inbuf := sliceToBuffer(input) status := C.brotli_decompress(inbuf, outbuf, C.Dictionary(dictionary)) + if status == C.BrotliStatus_NeedsMoreOutput { + return nil, ErrOutputWontFit + } if status != C.BrotliStatus_Success { return nil, fmt.Errorf("failed decompression: %d", status) } diff --git a/staker/block_validator.go b/staker/block_validator.go index bfb7c24ac6..03367a50b0 100644 --- a/staker/block_validator.go +++ b/staker/block_validator.go @@ -34,6 +34,11 @@ var ( validatorPendingValidationsGauge = metrics.NewRegisteredGauge("arb/validator/validations/pending", nil) validatorValidValidationsCounter = metrics.NewRegisteredCounter("arb/validator/validations/valid", nil) validatorFailedValidationsCounter = metrics.NewRegisteredCounter("arb/validator/validations/failed", nil) + validatorProfileWaitToRecordHist = metrics.NewRegisteredHistogram("arb/validator/profile/wait_to_record", nil, metrics.NewBoundedHistogramSample()) + validatorProfileRecordingHist = metrics.NewRegisteredHistogram("arb/validator/profile/recording", nil, metrics.NewBoundedHistogramSample()) + validatorProfileWaitToLaunchHist = metrics.NewRegisteredHistogram("arb/validator/profile/wait_to_launch", nil, metrics.NewBoundedHistogramSample()) + validatorProfileLaunchingHist = metrics.NewRegisteredHistogram("arb/validator/profile/launching", nil, metrics.NewBoundedHistogramSample()) + validatorProfileRunningHist = metrics.NewRegisteredHistogram("arb/validator/profile/running", nil, metrics.NewBoundedHistogramSample()) validatorMsgCountCurrentBatch = metrics.NewRegisteredGauge("arb/validator/msg_count_current_batch", nil) validatorMsgCountCreatedGauge = metrics.NewRegisteredGauge("arb/validator/msg_count_created", nil) validatorMsgCountRecordSentGauge = metrics.NewRegisteredGauge("arb/validator/msg_count_record_sent", nil) @@ -210,10 +215,11 @@ const ( ) type validationStatus struct { - Status atomic.Uint32 // atomic: value is one of validationStatus* - Cancel func() // non-atomic: only read/written to with reorg mutex - Entry *validationEntry // non-atomic: only read if Status >= validationStatusPrepared - Runs []validator.ValidationRun // if status >= ValidationSent + Status atomic.Uint32 // atomic: value is one of validationStatus* + Cancel func() // non-atomic: only read/written to with reorg mutex + Entry *validationEntry // non-atomic: only read if Status >= validationStatusPrepared + Runs []validator.ValidationRun // if status >= ValidationSent + profileTS int64 // time-stamp for profiling } func (s *validationStatus) getStatus() valStatusField { @@ -225,6 +231,13 @@ func (s *validationStatus) replaceStatus(old, new valStatusField) bool { return s.Status.CompareAndSwap(uint32(old), uint32(new)) } +// gets how many miliseconds last step took, and starts measuring a new step +func (s *validationStatus) profileStep() int64 { + start := s.profileTS + s.profileTS = time.Now().UnixMilli() + return s.profileTS - start +} + func NewBlockValidator( statelessBlockValidator *StatelessBlockValidator, inbox InboxTrackerInterface, @@ -447,6 +460,8 @@ func (v *BlockValidator) sendRecord(s *validationStatus) error { if !s.replaceStatus(Created, RecordSent) { return fmt.Errorf("failed status check for send record. Status: %v", s.getStatus()) } + + validatorProfileWaitToRecordHist.Update(s.profileStep()) v.LaunchThread(func(ctx context.Context) { err := v.ValidationEntryRecord(ctx, s.Entry) if ctx.Err() != nil { @@ -457,6 +472,7 @@ func (v *BlockValidator) sendRecord(s *validationStatus) error { log.Error("Error while recording", "err", err, "status", s.getStatus()) return } + validatorProfileRecordingHist.Update(s.profileStep()) if !s.replaceStatus(RecordSent, Prepared) { log.Error("Fault trying to update validation with recording", "entry", s.Entry, "status", s.getStatus()) return @@ -468,7 +484,7 @@ func (v *BlockValidator) sendRecord(s *validationStatus) error { //nolint:gosec func (v *BlockValidator) writeToFile(validationEntry *validationEntry, moduleRoot common.Hash) error { - input, err := validationEntry.ToInput() + input, err := validationEntry.ToInput([]string{"wavm"}) if err != nil { return err } @@ -585,7 +601,8 @@ func (v *BlockValidator) createNextValidationEntry(ctx context.Context) (bool, e return false, err } status := &validationStatus{ - Entry: entry, + Entry: entry, + profileTS: time.Now().UnixMilli(), } status.Status.Store(uint32(Created)) v.validations.Store(pos, status) @@ -792,12 +809,13 @@ validationsLoop: continue } for _, moduleRoot := range wasmRoots { - if v.chosenValidator[moduleRoot] == nil { + spawner := v.chosenValidator[moduleRoot] + if spawner == nil { notFoundErr := fmt.Errorf("did not find spawner for moduleRoot :%v", moduleRoot) v.possiblyFatal(notFoundErr) return nil, notFoundErr } - if v.chosenValidator[moduleRoot].Room() == 0 { + if spawner.Room() == 0 { log.Trace("advanceValidations: no more room", "moduleRoot", moduleRoot) return nil, nil } @@ -807,28 +825,35 @@ validationsLoop: return nil, nil } if currentStatus == Prepared { - input, err := validationStatus.Entry.ToInput() - if err != nil && ctx.Err() == nil { - v.possiblyFatal(fmt.Errorf("%w: error preparing validation", err)) - continue - } replaced := validationStatus.replaceStatus(Prepared, SendingValidation) if !replaced { v.possiblyFatal(errors.New("failed to set SendingValidation status")) } + validatorProfileWaitToLaunchHist.Update(validationStatus.profileStep()) validatorPendingValidationsGauge.Inc(1) var runs []validator.ValidationRun for _, moduleRoot := range wasmRoots { - run := v.chosenValidator[moduleRoot].Launch(input, moduleRoot) + spawner := v.chosenValidator[moduleRoot] + input, err := validationStatus.Entry.ToInput(spawner.StylusArchs()) + if err != nil && ctx.Err() == nil { + v.possiblyFatal(fmt.Errorf("%w: error preparing validation", err)) + continue + } + if ctx.Err() != nil { + return nil, ctx.Err() + } + run := spawner.Launch(input, moduleRoot) log.Trace("advanceValidations: launched", "pos", validationStatus.Entry.Pos, "moduleRoot", moduleRoot) runs = append(runs, run) } + validatorProfileLaunchingHist.Update(validationStatus.profileStep()) validationCtx, cancel := context.WithCancel(ctx) validationStatus.Runs = runs validationStatus.Cancel = cancel v.LaunchUntrackedThread(func() { defer validatorPendingValidationsGauge.Dec(1) defer cancel() + startTsMilli := validationStatus.profileTS replaced = validationStatus.replaceStatus(SendingValidation, ValidationSent) if !replaced { v.possiblyFatal(errors.New("failed to set status to ValidationSent")) @@ -842,6 +867,7 @@ validationsLoop: return } } + validatorProfileRunningHist.Update(time.Now().UnixMilli() - startTsMilli) nonBlockingTrigger(v.progressValidationsChan) }) } diff --git a/staker/challenge_manager.go b/staker/challenge_manager.go index 22897e3c1d..80cafccced 100644 --- a/staker/challenge_manager.go +++ b/staker/challenge_manager.go @@ -467,7 +467,7 @@ func (m *ChallengeManager) createExecutionBackend(ctx context.Context, step uint if err != nil { return fmt.Errorf("error creating validation entry for challenge %v msg %v for execution challenge: %w", m.challengeIndex, initialCount, err) } - input, err := entry.ToInput() + input, err := entry.ToInput([]string{"wavm"}) if err != nil { return fmt.Errorf("error getting validation entry input of challenge %v msg %v: %w", m.challengeIndex, initialCount, err) } diff --git a/staker/stateless_block_validator.go b/staker/stateless_block_validator.go index ec235c4bf5..65f5787e03 100644 --- a/staker/stateless_block_validator.go +++ b/staker/stateless_block_validator.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "net/url" + "runtime" "testing" "github.com/offchainlabs/nitro/arbstate/daprovider" @@ -134,21 +135,36 @@ type validationEntry struct { DelayedMsg []byte } -func (e *validationEntry) ToInput() (*validator.ValidationInput, error) { +func (e *validationEntry) ToInput(stylusArchs []string) (*validator.ValidationInput, error) { if e.Stage != Ready { return nil, errors.New("cannot create input from non-ready entry") } - return &validator.ValidationInput{ + res := validator.ValidationInput{ Id: uint64(e.Pos), HasDelayedMsg: e.HasDelayedMsg, DelayedMsgNr: e.DelayedMsgNr, Preimages: e.Preimages, - UserWasms: e.UserWasms, + UserWasms: make(map[string]map[common.Hash][]byte, len(e.UserWasms)), BatchInfo: e.BatchInfo, DelayedMsg: e.DelayedMsg, StartState: e.Start, DebugChain: e.ChainConfig.DebugMode(), - }, nil + } + for _, stylusArch := range stylusArchs { + res.UserWasms[stylusArch] = make(map[common.Hash][]byte) + } + for hash, info := range e.UserWasms { + for _, stylusArch := range stylusArchs { + if stylusArch == "wavm" { + res.UserWasms[stylusArch][hash] = info.Module + } else if stylusArch == runtime.GOARCH { + res.UserWasms[stylusArch][hash] = info.Asm + } else { + return nil, fmt.Errorf("stylusArch not supported by block validator: %v", stylusArch) + } + } + } + return &res, nil } func newValidationEntry( @@ -373,14 +389,14 @@ func (v *StatelessBlockValidator) ValidateResult( if err != nil { return false, nil, err } - input, err := entry.ToInput() - if err != nil { - return false, nil, err - } var run validator.ValidationRun if !useExec { if v.redisValidator != nil { if validator.SpawnerSupportsModule(v.redisValidator, moduleRoot) { + input, err := entry.ToInput(v.redisValidator.StylusArchs()) + if err != nil { + return false, nil, err + } run = v.redisValidator.Launch(input, moduleRoot) } } @@ -388,6 +404,10 @@ func (v *StatelessBlockValidator) ValidateResult( if run == nil { for _, spawner := range v.execSpawners { if validator.SpawnerSupportsModule(spawner, moduleRoot) { + input, err := entry.ToInput(spawner.StylusArchs()) + if err != nil { + return false, nil, err + } run = spawner.Launch(input, moduleRoot) break } diff --git a/system_tests/validation_mock_test.go b/system_tests/validation_mock_test.go index 1330f24882..2c6321d009 100644 --- a/system_tests/validation_mock_test.go +++ b/system_tests/validation_mock_test.go @@ -60,6 +60,10 @@ func (s *mockSpawner) WasmModuleRoots() ([]common.Hash, error) { return mockWasmModuleRoots, nil } +func (s *mockSpawner) StylusArchs() []string { + return []string{"mock"} +} + func (s *mockSpawner) Launch(entry *validator.ValidationInput, moduleRoot common.Hash) validator.ValidationRun { run := &mockValRun{ Promise: containers.NewPromise[validator.GoGlobalState](nil), diff --git a/validator/client/redis/producer.go b/validator/client/redis/producer.go index 0adedc6784..b3ad0f8839 100644 --- a/validator/client/redis/producer.go +++ b/validator/client/redis/producer.go @@ -23,6 +23,7 @@ type ValidationClientConfig struct { StreamPrefix string `koanf:"stream-prefix"` Room int32 `koanf:"room"` RedisURL string `koanf:"redis-url"` + StylusArchs []string `koanf:"stylus-archs"` ProducerConfig pubsub.ProducerConfig `koanf:"producer-config"` CreateStreams bool `koanf:"create-streams"` } @@ -35,6 +36,7 @@ var DefaultValidationClientConfig = ValidationClientConfig{ Name: "redis validation client", Room: 2, RedisURL: "", + StylusArchs: []string{"wavm"}, ProducerConfig: pubsub.DefaultProducerConfig, CreateStreams: true, } @@ -44,6 +46,7 @@ var TestValidationClientConfig = ValidationClientConfig{ Room: 2, RedisURL: "", StreamPrefix: "test-", + StylusArchs: []string{"wavm"}, ProducerConfig: pubsub.TestProducerConfig, CreateStreams: false, } @@ -53,6 +56,7 @@ func ValidationClientConfigAddOptions(prefix string, f *pflag.FlagSet) { f.Int32(prefix+".room", DefaultValidationClientConfig.Room, "validation client room") f.String(prefix+".redis-url", DefaultValidationClientConfig.RedisURL, "redis url") f.String(prefix+".stream-prefix", DefaultValidationClientConfig.StreamPrefix, "prefix for stream name") + f.StringSlice(prefix+".stylus-archs", DefaultValidationClientConfig.StylusArchs, "archs required for stylus workers") pubsub.ProducerAddConfigAddOptions(prefix+".producer-config", f) f.Bool(prefix+".create-streams", DefaultValidationClientConfig.CreateStreams, "create redis streams if it does not exist") } @@ -148,6 +152,10 @@ func (c *ValidationClient) Name() string { return c.config.Name } +func (c *ValidationClient) StylusArchs() []string { + return c.config.StylusArchs +} + func (c *ValidationClient) Room() int { return int(c.room.Load()) } diff --git a/validator/client/validation_client.go b/validator/client/validation_client.go index 79ecc6bdf4..d6743b109e 100644 --- a/validator/client/validation_client.go +++ b/validator/client/validation_client.go @@ -8,6 +8,7 @@ import ( "encoding/base64" "errors" "fmt" + "runtime" "sync/atomic" "time" @@ -29,13 +30,16 @@ type ValidationClient struct { stopwaiter.StopWaiter client *rpcclient.RpcClient name string + stylusArchs []string room atomic.Int32 wasmModuleRoots []common.Hash } func NewValidationClient(config rpcclient.ClientConfigFetcher, stack *node.Node) *ValidationClient { return &ValidationClient{ - client: rpcclient.NewRpcClient(config, stack), + client: rpcclient.NewRpcClient(config, stack), + name: "not started", + stylusArchs: []string{"not started"}, } } @@ -51,9 +55,7 @@ func (c *ValidationClient) Launch(entry *validator.ValidationInput, moduleRoot c return server_common.NewValRun(promise, moduleRoot) } -func (c *ValidationClient) Start(ctx_in context.Context) error { - c.StopWaiter.Start(ctx_in, c) - ctx := c.GetContext() +func (c *ValidationClient) Start(ctx context.Context) error { if err := c.client.Start(ctx); err != nil { return err } @@ -64,15 +66,27 @@ func (c *ValidationClient) Start(ctx_in context.Context) error { if len(name) == 0 { return errors.New("couldn't read name from server") } + var stylusArchs []string + if err := c.client.CallContext(ctx, &stylusArchs, server_api.Namespace+"_stylusArchs"); err != nil { + return err + } + if len(stylusArchs) == 0 { + return fmt.Errorf("could not read stylus archs from validation server") + } + for _, stylusArch := range stylusArchs { + if stylusArch != "wavm" && stylusArch != runtime.GOARCH && stylusArch != "mock" { + return fmt.Errorf("unsupported stylus architecture: %v", stylusArch) + } + } var moduleRoots []common.Hash - if err := c.client.CallContext(c.GetContext(), &moduleRoots, server_api.Namespace+"_wasmModuleRoots"); err != nil { + if err := c.client.CallContext(ctx, &moduleRoots, server_api.Namespace+"_wasmModuleRoots"); err != nil { return err } if len(moduleRoots) == 0 { return fmt.Errorf("server reported no wasmModuleRoots") } var room int - if err := c.client.CallContext(c.GetContext(), &room, server_api.Namespace+"_room"); err != nil { + if err := c.client.CallContext(ctx, &room, server_api.Namespace+"_room"); err != nil { return err } if room < 2 { @@ -84,6 +98,8 @@ func (c *ValidationClient) Start(ctx_in context.Context) error { c.room.Store(int32(room)) c.wasmModuleRoots = moduleRoots c.name = name + c.stylusArchs = stylusArchs + c.StopWaiter.Start(ctx, c) return nil } @@ -94,6 +110,13 @@ func (c *ValidationClient) WasmModuleRoots() ([]common.Hash, error) { return nil, errors.New("not started") } +func (c *ValidationClient) StylusArchs() []string { + if c.Started() { + return c.stylusArchs + } + return []string{"not started"} +} + func (c *ValidationClient) Stop() { c.StopWaiter.StopOnly() if c.client != nil { diff --git a/validator/interface.go b/validator/interface.go index 91668a3771..80aa2c1fcc 100644 --- a/validator/interface.go +++ b/validator/interface.go @@ -13,6 +13,7 @@ type ValidationSpawner interface { Start(context.Context) error Stop() Name() string + StylusArchs() []string Room() int } diff --git a/validator/server_api/json.go b/validator/server_api/json.go index dd646e1aa1..90746e4c57 100644 --- a/validator/server_api/json.go +++ b/validator/server_api/json.go @@ -6,11 +6,12 @@ package server_api import ( "encoding/base64" "encoding/json" + "errors" "fmt" "os" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/state" + "github.com/offchainlabs/nitro/arbcompress" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/util/jsonapi" @@ -62,7 +63,7 @@ type InputJSON struct { BatchInfo []BatchInfoJson DelayedMsgB64 string StartState validator.GoGlobalState - UserWasms map[common.Hash]UserWasmJson + UserWasms map[string]map[common.Hash]string DebugChain bool } @@ -77,11 +78,6 @@ func (i *InputJSON) WriteToFile() error { return nil } -type UserWasmJson struct { - Module string - Asm string -} - type BatchInfoJson struct { Number uint64 DataB64 string @@ -99,19 +95,23 @@ func ValidationInputToJson(entry *validator.ValidationInput) *InputJSON { DelayedMsgB64: base64.StdEncoding.EncodeToString(entry.DelayedMsg), StartState: entry.StartState, PreimagesB64: jsonPreimagesMap, - UserWasms: make(map[common.Hash]UserWasmJson), + UserWasms: make(map[string]map[common.Hash]string), DebugChain: entry.DebugChain, } for _, binfo := range entry.BatchInfo { encData := base64.StdEncoding.EncodeToString(binfo.Data) res.BatchInfo = append(res.BatchInfo, BatchInfoJson{Number: binfo.Number, DataB64: encData}) } - for moduleHash, info := range entry.UserWasms { - encWasm := UserWasmJson{ - Asm: base64.StdEncoding.EncodeToString(info.Asm), - Module: base64.StdEncoding.EncodeToString(info.Module), + for arch, wasms := range entry.UserWasms { + archWasms := make(map[common.Hash]string) + for moduleHash, data := range wasms { + compressed, err := arbcompress.CompressLevel(data, 1) + if err != nil { + continue + } + archWasms[moduleHash] = base64.StdEncoding.EncodeToString(compressed) } - res.UserWasms[moduleHash] = encWasm + res.UserWasms[arch] = archWasms } return res } @@ -127,7 +127,7 @@ func ValidationInputFromJson(entry *InputJSON) (*validator.ValidationInput, erro DelayedMsgNr: entry.DelayedMsgNr, StartState: entry.StartState, Preimages: preimages, - UserWasms: make(state.UserWasms), + UserWasms: make(map[string]map[common.Hash][]byte), DebugChain: entry.DebugChain, } delayed, err := base64.StdEncoding.DecodeString(entry.DelayedMsgB64) @@ -146,20 +146,32 @@ func ValidationInputFromJson(entry *InputJSON) (*validator.ValidationInput, erro } valInput.BatchInfo = append(valInput.BatchInfo, decInfo) } - for moduleHash, info := range entry.UserWasms { - asm, err := base64.StdEncoding.DecodeString(info.Asm) - if err != nil { - return nil, err - } - module, err := base64.StdEncoding.DecodeString(info.Module) - if err != nil { - return nil, err - } - decInfo := state.ActivatedWasm{ - Asm: asm, - Module: module, + for arch, wasms := range entry.UserWasms { + archWasms := make(map[common.Hash][]byte) + for moduleHash, encoded := range wasms { + decoded, err := base64.StdEncoding.DecodeString(encoded) + if err != nil { + return nil, err + } + maxSize := 2_000_000 + var uncompressed []byte + for { + uncompressed, err = arbcompress.Decompress(decoded, maxSize) + if errors.Is(err, arbcompress.ErrOutputWontFit) { + if maxSize >= 512_000_000 { + return nil, errors.New("failed decompression: too large") + } + maxSize = maxSize * 4 + continue + } + if err != nil { + return nil, err + } + break + } + archWasms[moduleHash] = uncompressed } - valInput.UserWasms[moduleHash] = decInfo + valInput.UserWasms[arch] = archWasms } return valInput, nil } diff --git a/validator/server_arb/validator_spawner.go b/validator/server_arb/validator_spawner.go index 7b9293f7bd..1d4126dc7c 100644 --- a/validator/server_arb/validator_spawner.go +++ b/validator/server_arb/validator_spawner.go @@ -88,6 +88,10 @@ func (s *ArbitratorSpawner) WasmModuleRoots() ([]common.Hash, error) { return s.locator.ModuleRoots(), nil } +func (s *ArbitratorSpawner) StylusArchs() []string { + return []string{"wavm"} +} + func (s *ArbitratorSpawner) Name() string { return "arbitrator" } @@ -118,8 +122,15 @@ func (v *ArbitratorSpawner) loadEntryToMachine(ctx context.Context, entry *valid return fmt.Errorf("error while trying to add sequencer msg for proving: %w", err) } } - for moduleHash, info := range entry.UserWasms { - err = mach.AddUserWasm(moduleHash, info.Module) + if len(entry.UserWasms["wavm"]) == 0 { + for stylusArch, wasms := range entry.UserWasms { + if len(wasms) > 0 { + return fmt.Errorf("bad stylus arch loaded to machine. Expected wavm. Got: %s", stylusArch) + } + } + } + for moduleHash, module := range entry.UserWasms["wavm"] { + err = mach.AddUserWasm(moduleHash, module) if err != nil { log.Error( "error adding user wasm for proving", diff --git a/validator/server_jit/jit_machine.go b/validator/server_jit/jit_machine.go index 1a3ccfa340..e4fb840cbb 100644 --- a/validator/server_jit/jit_machine.go +++ b/validator/server_jit/jit_machine.go @@ -12,6 +12,7 @@ import ( "net" "os" "os/exec" + "runtime" "time" "github.com/ethereum/go-ethereum/common" @@ -211,16 +212,25 @@ func (machine *JitMachine) prove( } } - // send user wasms - userWasms := entry.UserWasms + userWasms := entry.UserWasms[runtime.GOARCH] + + // if there are user wasms, but only for wrong architecture - error + if len(userWasms) == 0 { + for arch, userWasms := range entry.UserWasms { + if len(userWasms) != 0 { + return state, fmt.Errorf("bad stylus arch for validation input. got: %v, expected: %v", arch, runtime.GOARCH) + } + } + } + if err := writeUint32(uint32(len(userWasms))); err != nil { return state, err } - for moduleHash, info := range userWasms { + for moduleHash, program := range userWasms { if err := writeExact(moduleHash[:]); err != nil { return state, err } - if err := writeBytes(info.Asm); err != nil { + if err := writeBytes(program); err != nil { return state, err } } diff --git a/validator/server_jit/spawner.go b/validator/server_jit/spawner.go index eda74b2911..5ba3664109 100644 --- a/validator/server_jit/spawner.go +++ b/validator/server_jit/spawner.go @@ -71,6 +71,10 @@ func (v *JitSpawner) WasmModuleRoots() ([]common.Hash, error) { return v.locator.ModuleRoots(), nil } +func (v *JitSpawner) StylusArchs() []string { + return []string{runtime.GOARCH} +} + func (v *JitSpawner) execute( ctx context.Context, entry *validator.ValidationInput, moduleRoot common.Hash, ) (validator.GoGlobalState, error) { diff --git a/validator/validation_entry.go b/validator/validation_entry.go index 446f84ca62..133a67a8a8 100644 --- a/validator/validation_entry.go +++ b/validator/validation_entry.go @@ -2,7 +2,6 @@ package validator import ( "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/state" "github.com/offchainlabs/nitro/arbutil" ) @@ -17,7 +16,7 @@ type ValidationInput struct { HasDelayedMsg bool DelayedMsgNr uint64 Preimages map[arbutil.PreimageType]map[common.Hash][]byte - UserWasms state.UserWasms + UserWasms map[string]map[common.Hash][]byte BatchInfo []BatchInfo DelayedMsg []byte StartState GoGlobalState diff --git a/validator/valnode/validation_api.go b/validator/valnode/validation_api.go index 3299366821..6245ffc5e3 100644 --- a/validator/valnode/validation_api.go +++ b/validator/valnode/validation_api.go @@ -44,6 +44,10 @@ func (a *ValidationServerAPI) WasmModuleRoots() ([]common.Hash, error) { return a.spawner.WasmModuleRoots() } +func (a *ValidationServerAPI) StylusArchs() ([]string, error) { + return a.spawner.StylusArchs(), nil +} + func NewValidationServerAPI(spawner validator.ValidationSpawner) *ValidationServerAPI { return &ValidationServerAPI{spawner} }