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

support cross-compilation of stylus programs #2605

Merged
merged 27 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b933b74
pass targets to rawdb.WrapDatabaseWithWasm, change rawdb.Target to et…
magicxyyz Aug 22, 2024
eefd729
compile to targets in WasmTargets list
magicxyyz Aug 22, 2024
2832703
use wasm targets list in SaveActiveProgramToWasmStore
magicxyyz Aug 22, 2024
10f9b15
update geth pin
magicxyyz Aug 22, 2024
758d25f
Merge branch 'master' into cross-compile
magicxyyz Aug 23, 2024
17319ad
update geth pin
magicxyyz Aug 23, 2024
cdb43d7
update validation client stylus archs sanity check
magicxyyz Aug 23, 2024
71ab928
change archs list option to extra-archs that must include wavm and is…
magicxyyz Aug 23, 2024
304f2c1
add cross compilation to progam test
magicxyyz Aug 26, 2024
26496b0
Merge branch 'master' into cross-compile
magicxyyz Aug 26, 2024
9004163
Merge branch 'fix-wasm-rebuild-stylus-target' into cross-compile
magicxyyz Aug 26, 2024
3fca01d
Merge branch 'master' into cross-compile
magicxyyz Aug 26, 2024
ea0cbc6
update geth pin
magicxyyz Aug 27, 2024
823464c
Merge branch 'master' into cross-compile
magicxyyz Aug 27, 2024
7b4834f
pass WasmTargets to RecordProgram call
magicxyyz Aug 28, 2024
99b34b3
init test: call Validate on StylusTargetConfig
magicxyyz Aug 28, 2024
bf735f4
don't call programs.SetTarget for TargetWavm
magicxyyz Aug 28, 2024
29327a8
refactor StylusTargetConfig.Validate
magicxyyz Aug 28, 2024
aba9415
error for unsupported stylus target in populateStylusTargetCache
magicxyyz Aug 28, 2024
12fc95d
Merge branch 'master' into cross-compile
magicxyyz Aug 28, 2024
7a4fe00
simplify StylusTargetConfig.Validate
magicxyyz Aug 29, 2024
d87e573
Merge branch 'master' into cross-compile
magicxyyz Aug 29, 2024
10a1004
Merge branch 'master' into cross-compile
magicxyyz Aug 30, 2024
1dcd104
Merge branch 'master' into cross-compile
tsahee Aug 31, 2024
610d6a1
Merge branch 'master' into cross-compile
magicxyyz Sep 3, 2024
7617a3b
Merge branch 'master' into cross-compile
magicxyyz Sep 3, 2024
1c4d7e3
Merge branch 'master' into cross-compile
joshuacolvin0 Sep 4, 2024
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
4 changes: 3 additions & 1 deletion arbnode/inbox_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ func NewTransactionStreamerForTest(t *testing.T, ownerAddress common.Address) (*
if err != nil {
Fail(t, err)
}
if err := execEngine.Initialize(gethexec.DefaultCachingConfig.StylusLRUCache, &gethexec.DefaultStylusTargetConfig); err != nil {
stylusTargetConfig := &gethexec.DefaultStylusTargetConfig
Require(t, stylusTargetConfig.Validate()) // pre-processes config (i.a. parses wasmTargets)
if err := execEngine.Initialize(gethexec.DefaultCachingConfig.StylusLRUCache, stylusTargetConfig); err != nil {
Fail(t, err)
}
execSeq := &execClientWrapper{execEngine, t}
Expand Down
70 changes: 46 additions & 24 deletions arbos/programs/native.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/offchainlabs/nitro/arbos/burn"
"github.com/offchainlabs/nitro/arbos/util"
Expand Down Expand Up @@ -71,7 +72,7 @@ func activateProgramInternal(
version uint16,
debug bool,
gasLeft *uint64,
) (*activationInfo, map[rawdb.Target][]byte, error) {
) (*activationInfo, map[ethdb.WasmTarget][]byte, error) {
output := &rustBytes{}
moduleHash := &bytes32{}
stylusData := &C.StylusData{}
Expand Down Expand Up @@ -99,25 +100,50 @@ func activateProgramInternal(
}
return nil, nil, err
}
target := rawdb.LocalTarget()
status_asm := C.stylus_compile(
goSlice(wasm),
u16(version),
cbool(debug),
goSlice([]byte(target)),
output,
)
asm := output.intoBytes()
if status_asm != 0 {
return nil, nil, fmt.Errorf("%w: %s", ErrProgramActivation, string(asm))
targets := db.Database().WasmTargets()
type result struct {
target ethdb.WasmTarget
asm []byte
err error
}
asmMap := map[rawdb.Target][]byte{
rawdb.TargetWavm: module,
target: asm,
results := make(chan result, len(targets))
for _, target := range targets {
if target == rawdb.TargetWavm {
results <- result{target, module, nil}
Copy link
Contributor

Choose a reason for hiding this comment

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

compile wavm before the loop. If it fails - return just that error without trying other compilation. If it succeeds add wavm to the map and do the loop. Inside the loop - skip wavm compilation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

wavm is compiled before the loop iterating over targets and if wavm compilation fails we return error:

status_mod := userStatus(C.stylus_activate(
goSlice(wasm),
u16(page_limit),
u16(version),
cbool(debug),
output,
&codeHash,
moduleHash,
stylusData,
(*u64)(gasLeft),
))
module, msg, err := status_mod.toResult(output.intoBytes(), debug)
if err != nil {
if debug {
log.Warn("activation failed", "err", err, "msg", msg, "program", addressForLogging)
}
if errors.Is(err, vm.ErrExecutionReverted) {
return nil, nil, fmt.Errorf("%w: %s", ErrProgramActivation, msg)
}
return nil, nil, err
}

I add compiled module to results channel in the loop to add it to asmMap later on only if rawdb.TargetWavm is in the targets list. That way the code is ready for not storing wavm if not needed.
Does it sound right?

I can change it to always include wavm compilation output in the resulting asmMap, but I think that it is enough to require Wavm in WasmTargets list to have it always stored in db in this version.

let me know what you think

} else {
target := target
go func() {
output := &rustBytes{}
status_asm := C.stylus_compile(
goSlice(wasm),
u16(version),
cbool(debug),
goSlice([]byte(target)),
output,
)
asm := output.intoBytes()
if status_asm != 0 {
results <- result{target, nil, fmt.Errorf("%w: %s", ErrProgramActivation, string(asm))}
return
}
results <- result{target, asm, nil}
}()
}
}
asmMap := make(map[ethdb.WasmTarget][]byte, len(targets))
for range targets {
res := <-results
if res.err != nil {
err = errors.Join(res.err, err)
} else {
asmMap[res.target] = res.asm
}
}
if err != nil {
return nil, nil, fmt.Errorf("compilation failed for one or more targets: %w", err)
}

hash := moduleHash.toHash()

info := &activationInfo{
moduleHash: hash,
initGas: uint16(stylusData.init_cost),
Expand Down Expand Up @@ -171,7 +197,7 @@ func getLocalAsm(statedb vm.StateDB, moduleHash common.Hash, addressForLogging c
}
asm, exists := asmMap[localTarget]
if !exists {
var availableTargets []rawdb.Target
var availableTargets []ethdb.WasmTarget
for target := range asmMap {
availableTargets = append(availableTargets, target)
}
Expand Down Expand Up @@ -202,12 +228,8 @@ func callProgram(
panic("missing asm")
}

if db, ok := db.(*state.StateDB); ok {
targets := []rawdb.Target{
rawdb.TargetWavm,
rawdb.LocalTarget(),
}
db.RecordProgram(targets, moduleHash)
if stateDb, ok := db.(*state.StateDB); ok {
stateDb.RecordProgram(db.Database().WasmTargets(), moduleHash)
}

evmApi := newApi(interpreter, tracingInfo, scope, memoryModel)
Expand Down Expand Up @@ -291,7 +313,7 @@ func ResizeWasmLruCache(size uint32) {
const DefaultTargetDescriptionArm = "arm64-linux-unknown+neon"
const DefaultTargetDescriptionX86 = "x86_64-linux-unknown+sse4.2+lzcnt+bmi"

func SetTarget(name rawdb.Target, description string, native bool) error {
func SetTarget(name ethdb.WasmTarget, description string, native bool) error {
output := &rustBytes{}
status := userStatus(C.stylus_target_set(
goSlice([]byte(name)),
Expand Down
3 changes: 2 additions & 1 deletion arbos/programs/wasmstorehelper.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ func (p Programs) SaveActiveProgramToWasmStore(statedb *state.StateDB, codeHash
return err
}

targets := statedb.Database().WasmTargets()
// If already in wasm store then return early
_, err = statedb.TryGetActivatedAsmMap([]rawdb.Target{rawdb.TargetWavm, rawdb.LocalTarget()}, moduleHash)
_, err = statedb.TryGetActivatedAsmMap(targets, moduleHash)
if err == nil {
return nil
}
Expand Down
6 changes: 3 additions & 3 deletions cmd/nitro/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ func rebuildLocalWasm(ctx context.Context, config *gethexec.Config, l2BlockChain
return chainDb, l2BlockChain, nil
}

func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeConfig, chainId *big.Int, cacheConfig *core.CacheConfig, persistentConfig *conf.PersistentConfig, l1Client arbutil.L1Interface, rollupAddrs chaininfo.RollupAddresses) (ethdb.Database, *core.BlockChain, error) {
func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeConfig, chainId *big.Int, cacheConfig *core.CacheConfig, targetConfig *gethexec.StylusTargetConfig, persistentConfig *conf.PersistentConfig, l1Client arbutil.L1Interface, rollupAddrs chaininfo.RollupAddresses) (ethdb.Database, *core.BlockChain, error) {
if !config.Init.Force {
if readOnlyDb, err := stack.OpenDatabaseWithFreezerWithExtraOptions("l2chaindata", 0, 0, config.Persistent.Ancient, "l2chaindata/", true, persistentConfig.Pebble.ExtraOptions("l2chaindata")); err == nil {
if chainConfig := gethexec.TryReadStoredChainConfig(readOnlyDb); chainConfig != nil {
Expand All @@ -585,7 +585,7 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo
if err := dbutil.UnfinishedConversionCheck(wasmDb); err != nil {
return nil, nil, fmt.Errorf("wasm unfinished database conversion check error: %w", err)
}
chainDb := rawdb.WrapDatabaseWithWasm(chainData, wasmDb, 1)
chainDb := rawdb.WrapDatabaseWithWasm(chainData, wasmDb, 1, targetConfig.WasmTargets())
_, err = rawdb.ParseStateScheme(cacheConfig.StateScheme, chainDb)
if err != nil {
return nil, nil, err
Expand Down Expand Up @@ -660,7 +660,7 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo
if err := validateOrUpgradeWasmStoreSchemaVersion(wasmDb); err != nil {
return nil, nil, err
}
chainDb := rawdb.WrapDatabaseWithWasm(chainData, wasmDb, 1)
chainDb := rawdb.WrapDatabaseWithWasm(chainData, wasmDb, 1, targetConfig.WasmTargets())
_, err = rawdb.ParseStateScheme(cacheConfig.StateScheme, chainDb)
if err != nil {
return nil, nil, err
Expand Down
10 changes: 10 additions & 0 deletions cmd/nitro/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,12 @@ func TestEmptyDatabaseDir(t *testing.T) {
}
}

func defaultStylusTargetConfigForTest(t *testing.T) *gethexec.StylusTargetConfig {
targetConfig := gethexec.DefaultStylusTargetConfig
Require(t, targetConfig.Validate())
return &targetConfig
}

func TestOpenInitializeChainDbIncompatibleStateScheme(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -381,6 +387,7 @@ func TestOpenInitializeChainDbIncompatibleStateScheme(t *testing.T) {
&nodeConfig,
new(big.Int).SetUint64(nodeConfig.Chain.ID),
gethexec.DefaultCacheConfigFor(stack, &nodeConfig.Execution.Caching),
defaultStylusTargetConfigForTest(t),
&nodeConfig.Persistent,
l1Client,
chaininfo.RollupAddresses{},
Expand All @@ -397,6 +404,7 @@ func TestOpenInitializeChainDbIncompatibleStateScheme(t *testing.T) {
&nodeConfig,
new(big.Int).SetUint64(nodeConfig.Chain.ID),
gethexec.DefaultCacheConfigFor(stack, &nodeConfig.Execution.Caching),
defaultStylusTargetConfigForTest(t),
&nodeConfig.Persistent,
l1Client,
chaininfo.RollupAddresses{},
Expand All @@ -414,6 +422,7 @@ func TestOpenInitializeChainDbIncompatibleStateScheme(t *testing.T) {
&nodeConfig,
new(big.Int).SetUint64(nodeConfig.Chain.ID),
gethexec.DefaultCacheConfigFor(stack, &nodeConfig.Execution.Caching),
defaultStylusTargetConfigForTest(t),
&nodeConfig.Persistent,
l1Client,
chaininfo.RollupAddresses{},
Expand Down Expand Up @@ -549,6 +558,7 @@ func TestOpenInitializeChainDbEmptyInit(t *testing.T) {
&nodeConfig,
new(big.Int).SetUint64(nodeConfig.Chain.ID),
gethexec.DefaultCacheConfigFor(stack, &nodeConfig.Execution.Caching),
defaultStylusTargetConfigForTest(t),
&nodeConfig.Persistent,
l1Client,
chaininfo.RollupAddresses{},
Expand Down
2 changes: 1 addition & 1 deletion cmd/nitro/nitro.go
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ func mainImpl() int {
}
}

chainDb, l2BlockChain, err := openInitializeChainDb(ctx, stack, nodeConfig, new(big.Int).SetUint64(nodeConfig.Chain.ID), gethexec.DefaultCacheConfigFor(stack, &nodeConfig.Execution.Caching), &nodeConfig.Persistent, l1Client, rollupAddrs)
chainDb, l2BlockChain, err := openInitializeChainDb(ctx, stack, nodeConfig, new(big.Int).SetUint64(nodeConfig.Chain.ID), gethexec.DefaultCacheConfigFor(stack, &nodeConfig.Execution.Caching), &nodeConfig.Execution.StylusTarget, &nodeConfig.Persistent, l1Client, rollupAddrs)
if l2BlockChain != nil {
deferFuncs = append(deferFuncs, func() { l2BlockChain.Stop() })
}
Expand Down
40 changes: 27 additions & 13 deletions execution/gethexec/executionengine.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,19 +151,33 @@ func (s *ExecutionEngine) MarkFeedStart(to arbutil.MessageIndex) {
}

func populateStylusTargetCache(targetConfig *StylusTargetConfig) error {
var effectiveStylusTarget string
target := rawdb.LocalTarget()
switch target {
case rawdb.TargetArm64:
effectiveStylusTarget = targetConfig.Arm64
case rawdb.TargetAmd64:
effectiveStylusTarget = targetConfig.Amd64
case rawdb.TargetHost:
effectiveStylusTarget = targetConfig.Host
}
err := programs.SetTarget(target, effectiveStylusTarget, true)
if err != nil {
return fmt.Errorf("Failed to set stylus target: %w", err)
localTarget := rawdb.LocalTarget()
targets := targetConfig.WasmTargets()
var nativeSet bool
for _, target := range targets {
var effectiveStylusTarget string
magicxyyz marked this conversation as resolved.
Show resolved Hide resolved
switch target {
case rawdb.TargetWavm:
// skip wavm target
continue
case rawdb.TargetArm64:
effectiveStylusTarget = targetConfig.Arm64
case rawdb.TargetAmd64:
effectiveStylusTarget = targetConfig.Amd64
case rawdb.TargetHost:
effectiveStylusTarget = targetConfig.Host
default:
return fmt.Errorf("unsupported stylus target: %v", target)
}
isNative := target == localTarget
err := programs.SetTarget(target, effectiveStylusTarget, isNative)
if err != nil {
return fmt.Errorf("failed to set stylus target: %w", err)
}
nativeSet = nativeSet || isNative
}
if !nativeSet {
return fmt.Errorf("local target %v missing in list of archs %v", localTarget, targets)
}
return nil
}
Expand Down
46 changes: 40 additions & 6 deletions execution/gethexec/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/ethereum/go-ethereum/arbitrum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/filters"
Expand All @@ -29,21 +30,51 @@ import (
)

type StylusTargetConfig struct {
Arm64 string `koanf:"arm64"`
Amd64 string `koanf:"amd64"`
Host string `koanf:"host"`
Arm64 string `koanf:"arm64"`
Amd64 string `koanf:"amd64"`
Host string `koanf:"host"`
ExtraArchs []string `koanf:"extra-archs"`

wasmTargets []ethdb.WasmTarget
}

func (c *StylusTargetConfig) WasmTargets() []ethdb.WasmTarget {
return c.wasmTargets
}

func (c *StylusTargetConfig) Validate() error {
targetsSet := make(map[ethdb.WasmTarget]bool, len(c.ExtraArchs))
for _, arch := range c.ExtraArchs {
magicxyyz marked this conversation as resolved.
Show resolved Hide resolved
target := ethdb.WasmTarget(arch)
if !rawdb.IsSupportedWasmTarget(target) {
return fmt.Errorf("unsupported architecture: %v, possible values: %s, %s, %s, %s", arch, rawdb.TargetWavm, rawdb.TargetArm64, rawdb.TargetAmd64, rawdb.TargetHost)
}
targetsSet[target] = true
}
if !targetsSet[rawdb.TargetWavm] {
return fmt.Errorf("%s target not found in archs list, archs: %v", rawdb.TargetWavm, c.ExtraArchs)
}
targetsSet[rawdb.LocalTarget()] = true
targets := make([]ethdb.WasmTarget, 0, len(c.ExtraArchs)+1)
for target := range targetsSet {
targets = append(targets, target)
}
c.wasmTargets = targets
return nil
}

var DefaultStylusTargetConfig = StylusTargetConfig{
Arm64: programs.DefaultTargetDescriptionArm,
Amd64: programs.DefaultTargetDescriptionX86,
Host: "",
Arm64: programs.DefaultTargetDescriptionArm,
Amd64: programs.DefaultTargetDescriptionX86,
Host: "",
ExtraArchs: []string{string(rawdb.TargetWavm)},
}

func StylusTargetConfigAddOptions(prefix string, f *flag.FlagSet) {
f.String(prefix+".arm64", DefaultStylusTargetConfig.Arm64, "stylus programs compilation target for arm64 linux")
f.String(prefix+".amd64", DefaultStylusTargetConfig.Amd64, "stylus programs compilation target for amd64 linux")
f.String(prefix+".host", DefaultStylusTargetConfig.Host, "stylus programs compilation target for system other than 64-bit ARM or 64-bit x86")
f.StringSlice(prefix+".extra-archs", DefaultStylusTargetConfig.ExtraArchs, fmt.Sprintf("Comma separated list of extra architectures to cross-compile stylus program to and cache in wasm store (additionally to local target). Currently must include at least %s. (supported targets: %s, %s, %s, %s)", rawdb.TargetWavm, rawdb.TargetWavm, rawdb.TargetArm64, rawdb.TargetAmd64, rawdb.TargetHost))
}

type Config struct {
Expand Down Expand Up @@ -82,6 +113,9 @@ func (c *Config) Validate() error {
if c.forwardingTarget != "" && c.Sequencer.Enable {
return errors.New("ForwardingTarget set and sequencer enabled")
}
if err := c.StylusTarget.Validate(); err != nil {
return err
}
return nil
}

Expand Down
2 changes: 1 addition & 1 deletion staker/block_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ func (v *BlockValidator) sendRecord(s *validationStatus) error {

//nolint:gosec
func (v *BlockValidator) writeToFile(validationEntry *validationEntry, moduleRoot common.Hash) error {
input, err := validationEntry.ToInput([]rawdb.Target{rawdb.TargetWavm})
input, err := validationEntry.ToInput([]ethdb.WasmTarget{rawdb.TargetWavm})
if err != nil {
return err
}
Expand Down
3 changes: 2 additions & 1 deletion staker/challenge_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc"
"github.com/offchainlabs/nitro/arbutil"
Expand Down Expand Up @@ -468,7 +469,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([]rawdb.Target{rawdb.TargetWavm})
input, err := entry.ToInput([]ethdb.WasmTarget{rawdb.TargetWavm})
if err != nil {
return fmt.Errorf("error getting validation entry input of challenge %v msg %v: %w", m.challengeIndex, initialCount, err)
}
Expand Down
5 changes: 2 additions & 3 deletions staker/stateless_block_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"github.com/offchainlabs/nitro/arbstate/daprovider"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
Expand Down Expand Up @@ -134,7 +133,7 @@ type validationEntry struct {
DelayedMsg []byte
}

func (e *validationEntry) ToInput(stylusArchs []rawdb.Target) (*validator.ValidationInput, error) {
func (e *validationEntry) ToInput(stylusArchs []ethdb.WasmTarget) (*validator.ValidationInput, error) {
if e.Stage != Ready {
return nil, errors.New("cannot create input from non-ready entry")
}
Expand All @@ -143,7 +142,7 @@ func (e *validationEntry) ToInput(stylusArchs []rawdb.Target) (*validator.Valida
HasDelayedMsg: e.HasDelayedMsg,
DelayedMsgNr: e.DelayedMsgNr,
Preimages: e.Preimages,
UserWasms: make(map[rawdb.Target]map[common.Hash][]byte, len(e.UserWasms)),
UserWasms: make(map[ethdb.WasmTarget]map[common.Hash][]byte, len(e.UserWasms)),
BatchInfo: e.BatchInfo,
DelayedMsg: e.DelayedMsg,
StartState: e.Start,
Expand Down
Loading
Loading