Skip to content

Commit

Permalink
merge master and update geth pin
Browse files Browse the repository at this point in the history
  • Loading branch information
ganeshvanahalli committed Jan 10, 2025
1 parent 3b3ebeb commit a1fc664
Show file tree
Hide file tree
Showing 7 changed files with 165 additions and 82 deletions.
150 changes: 102 additions & 48 deletions arbos/programs/native.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,17 @@ func activateProgram(
debug bool,
burner burn.Burner,
) (*activationInfo, error) {
info, asmMap, err := activateProgramInternal(db, program, codehash, wasm, page_limit, stylusVersion, arbosVersionForGas, debug, burner.GasLeft())
targets := db.Database().WasmTargets()
moduleActivationMandatory := true
info, asmMap, err := activateProgramInternal(program, codehash, wasm, page_limit, stylusVersion, arbosVersionForGas, debug, burner.GasLeft(), targets, moduleActivationMandatory)
if err != nil {
return nil, err
}
db.ActivateWasm(info.moduleHash, asmMap)
return info, nil
}

func activateProgramInternal(
db vm.StateDB,
func activateModule(
addressForLogging common.Address,
codehash common.Hash,
wasm []byte,
Expand All @@ -90,7 +91,7 @@ func activateProgramInternal(
arbosVersionForGas uint64,
debug bool,
gasLeft *uint64,
) (*activationInfo, map[ethdb.WasmTarget][]byte, error) {
) (*activationInfo, []byte, error) {
output := &rustBytes{}
moduleHash := &bytes32{}
stylusData := &C.StylusData{}
Expand Down Expand Up @@ -119,69 +120,120 @@ func activateProgramInternal(
}
return nil, nil, err
}
hash := bytes32ToHash(moduleHash)
targets := db.Database().WasmTargets()
info := &activationInfo{
moduleHash: bytes32ToHash(moduleHash),
initGas: uint16(stylusData.init_cost),
cachedInitGas: uint16(stylusData.cached_init_cost),
asmEstimate: uint32(stylusData.asm_estimate),
footprint: uint16(stylusData.footprint),
}
return info, module, nil
}

func compileNative(
wasm []byte,
stylusVersion uint16,
debug bool,
target ethdb.WasmTarget,
) ([]byte, error) {
output := &rustBytes{}
status_asm := C.stylus_compile(
goSlice(wasm),
u16(stylusVersion),
cbool(debug),
goSlice([]byte(target)),
output,
)
asm := rustBytesIntoBytes(output)
if status_asm != 0 {
return nil, fmt.Errorf("%w: %s", ErrProgramActivation, string(asm))
}
return asm, nil
}

func activateProgramInternal(
addressForLogging common.Address,
codehash common.Hash,
wasm []byte,
page_limit uint16,
stylusVersion uint16,
arbosVersionForGas uint64,
debug bool,
gasLeft *uint64,
targets []ethdb.WasmTarget,
moduleActivationMandatory bool,
) (*activationInfo, map[ethdb.WasmTarget][]byte, error) {
var wavmFound bool
var nativeTargets []ethdb.WasmTarget
for _, target := range targets {
if target == rawdb.TargetWavm {
wavmFound = true
} else {
nativeTargets = append(nativeTargets, target)
}
}
type result struct {
target ethdb.WasmTarget
asm []byte
err error
}
results := make(chan result, len(targets))
for _, target := range targets {
target := target
if target == rawdb.TargetWavm {
results <- result{target, module, nil}
} else {
go func() {
output := &rustBytes{}
status_asm := C.stylus_compile(
goSlice(wasm),
u16(stylusVersion),
cbool(debug),
goSlice([]byte(target)),
output,
)
asm := rustBytesIntoBytes(output)
if status_asm != 0 {
results <- result{target, nil, fmt.Errorf("%w: %s", ErrProgramActivation, string(asm))}
return
}
results <- result{target, asm, nil}
}()
results := make(chan result)
// info will be set in separate thread, make sure to wait before reading
var info *activationInfo
asmMap := make(map[ethdb.WasmTarget][]byte, len(nativeTargets)+1)
if moduleActivationMandatory || wavmFound {
go func() {
var err error
var module []byte
info, module, err = activateModule(addressForLogging, codehash, wasm, page_limit, stylusVersion, arbosVersionForGas, debug, gasLeft)
results <- result{rawdb.TargetWavm, module, err}
}()
}
if moduleActivationMandatory {
// wait for the module activation before starting compilation for other targets
res := <-results
if res.err != nil {
return nil, nil, res.err
} else if wavmFound {
asmMap[res.target] = res.asm
}
}
asmMap := make(map[ethdb.WasmTarget][]byte, len(targets))
for range targets {
for _, target := range nativeTargets {
target := target
go func() {
asm, err := compileNative(wasm, stylusVersion, debug, target)
results <- result{target, asm, err}
}()
}
expectedResults := len(nativeTargets)
if !moduleActivationMandatory && wavmFound {
// we didn't wait for module activation result, so wait for it too
expectedResults++
}
var err error
for i := 0; i < expectedResults; i++ {
res := <-results
if res.err != nil {
err = errors.Join(res.err, err)
err = errors.Join(res.err, fmt.Errorf("%s:%w", res.target, err))
} else {
asmMap[res.target] = res.asm
}
}
if err != nil {
if err != nil && moduleActivationMandatory {
log.Error(
"Compilation failed for one or more targets despite activation succeeding",
"address", addressForLogging,
"codeHash", codeHash,
"moduleHash", hash,
"codehash", codehash,
"moduleHash", info.moduleHash,
"targets", targets,
"err", err,
)
panic(fmt.Sprintf("Compilation of %v failed for one or more targets despite activation succeeding: %v", addressForLogging, err))
}

info := &activationInfo{
moduleHash: hash,
initGas: uint16(stylusData.init_cost),
cachedInitGas: uint16(stylusData.cached_init_cost),
asmEstimate: uint32(stylusData.asm_estimate),
footprint: uint16(stylusData.footprint),
}
return info, asmMap, err
}

func getLocalAsm(statedb vm.StateDB, moduleHash common.Hash, addressForLogging common.Address, code []byte, codeHash common.Hash, pagelimit uint16, time uint64, debugMode bool, program Program) ([]byte, error) {
func getLocalAsm(statedb vm.StateDB, moduleHash common.Hash, addressForLogging common.Address, code []byte, codehash common.Hash, pagelimit uint16, time uint64, debugMode bool, program Program) ([]byte, error) {
localTarget := rawdb.LocalTarget()
localAsm, err := statedb.TryGetActivatedAsm(localTarget, moduleHash)
if err == nil && len(localAsm) > 0 {
Expand All @@ -199,14 +251,16 @@ func getLocalAsm(statedb vm.StateDB, moduleHash common.Hash, addressForLogging c
zeroArbosVersion := uint64(0)
zeroGas := uint64(0)

targets := statedb.Database().WasmTargets()
// we know program is activated, so it must be in correct version and not use too much memory
info, asmMap, err := activateProgramInternal(statedb, addressForLogging, codeHash, wasm, pagelimit, program.version, zeroArbosVersion, debugMode, &zeroGas)
moduleActivationMandatory := false
info, asmMap, err := activateProgramInternal(addressForLogging, codehash, wasm, pagelimit, program.version, zeroArbosVersion, debugMode, &zeroGas, targets, moduleActivationMandatory)
if err != nil {
log.Error("failed to reactivate program", "address", addressForLogging, "expected moduleHash", moduleHash, "err", err)
return nil, fmt.Errorf("failed to reactivate program address: %v err: %w", addressForLogging, err)
}

if info.moduleHash != moduleHash {
if info != nil && info.moduleHash != moduleHash {
log.Error("failed to reactivate program", "address", addressForLogging, "expected moduleHash", moduleHash, "got", info.moduleHash)
return nil, fmt.Errorf("failed to reactivate program. address: %v, expected ModuleHash: %v", addressForLogging, moduleHash)
}
Expand All @@ -223,7 +277,7 @@ func getLocalAsm(statedb vm.StateDB, moduleHash common.Hash, addressForLogging c
} else {
// program activated recently, possibly in this eth_call
// store it to statedb. It will be stored to database if statedb is commited
statedb.ActivateWasm(info.moduleHash, asmMap)
statedb.ActivateWasm(moduleHash, asmMap)
}
asm, exists := asmMap[localTarget]
if !exists {
Expand Down Expand Up @@ -302,10 +356,10 @@ func handleReqImpl(apiId usize, req_type u32, data *rustSlice, costPtr *u64, out

// Caches a program in Rust. We write a record so that we can undo on revert.
// For gas estimation and eth_call, we ignore permanent updates and rely on Rust's LRU.
func cacheProgram(db vm.StateDB, module common.Hash, program Program, addressForLogging common.Address, code []byte, codeHash common.Hash, params *StylusParams, debug bool, time uint64, runMode core.MessageRunMode) {
func cacheProgram(db vm.StateDB, module common.Hash, program Program, addressForLogging common.Address, code []byte, codehash common.Hash, params *StylusParams, debug bool, time uint64, runMode core.MessageRunMode) {
if runMode == core.MessageCommitMode {
// address is only used for logging
asm, err := getLocalAsm(db, module, addressForLogging, code, codeHash, params.PageLimit, time, debug, program)
asm, err := getLocalAsm(db, module, addressForLogging, code, codehash, params.PageLimit, time, debug, program)
if err != nil {
panic("unable to recreate wasm")
}
Expand Down
14 changes: 7 additions & 7 deletions arbos/programs/programs.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,8 @@ func (p Programs) ActivateProgram(evm *vm.EVM, address common.Address, arbosVers
return stylusVersion, codeHash, info.moduleHash, dataFee, false, p.setProgram(codeHash, programData)
}

func runModeToString(runmode core.MessageRunMode) string {
switch runmode {
func runModeToString(runMode core.MessageRunMode) string {
switch runMode {
case core.MessageCommitMode:
return "commit_runmode"
case core.MessageGasEstimationMode:
Expand All @@ -187,7 +187,7 @@ func (p Programs) CallProgram(
tracingInfo *util.TracingInfo,
calldata []byte,
reentrant bool,
runmode core.MessageRunMode,
runMode core.MessageRunMode,
) ([]byte, error) {
evm := interpreter.Evm()
contract := scope.Contract
Expand Down Expand Up @@ -262,26 +262,26 @@ func (p Programs) CallProgram(
address = *contract.CodeAddr
}
var arbos_tag uint32
if runmode == core.MessageCommitMode {
if runMode == core.MessageCommitMode {
arbos_tag = statedb.Database().WasmCacheTag()
}

metrics.GetOrRegisterCounter(fmt.Sprintf("arb/arbos/stylus/program_calls/%s", runModeToString(runmode)), nil).Inc(1)
metrics.GetOrRegisterCounter(fmt.Sprintf("arb/arbos/stylus/program_calls/%s", runModeToString(runMode)), nil).Inc(1)
ret, err := callProgram(address, moduleHash, localAsm, scope, interpreter, tracingInfo, calldata, evmData, goParams, model, arbos_tag)
if len(ret) > 0 && arbosVersion >= gethParams.ArbosVersion_StylusFixes {
// Ensure that return data costs as least as much as it would in the EVM.
evmCost := evmMemoryCost(uint64(len(ret)))
if startingGas < evmCost {
contract.Gas = 0
// #nosec G115
metrics.GetOrRegisterCounter(fmt.Sprintf("arb/arbos/stylus/gas_used/%s", runModeToString(runmode)), nil).Inc(int64(startingGas))
metrics.GetOrRegisterCounter(fmt.Sprintf("arb/arbos/stylus/gas_used/%s", runModeToString(runMode)), nil).Inc(int64(startingGas))
return nil, vm.ErrOutOfGas
}
maxGasToReturn := startingGas - evmCost
contract.Gas = am.MinInt(contract.Gas, maxGasToReturn)
}
// #nosec G115
metrics.GetOrRegisterCounter(fmt.Sprintf("arb/arbos/stylus/gas_used/%s", runModeToString(runmode)), nil).Inc(int64(startingGas - contract.Gas))
metrics.GetOrRegisterCounter(fmt.Sprintf("arb/arbos/stylus/gas_used/%s", runModeToString(runMode)), nil).Inc(int64(startingGas - contract.Gas))
return ret, err
}

Expand Down
3 changes: 2 additions & 1 deletion arbos/programs/wasmstorehelper.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ func (p Programs) SaveActiveProgramToWasmStore(statedb *state.StateDB, codeHash

// We know program is activated, so it must be in correct version and not use too much memory
// Empty program address is supplied because we dont have access to this during rebuilding of wasm store
info, asmMap, err := activateProgramInternal(statedb, common.Address{}, codeHash, wasm, progParams.PageLimit, program.version, zeroArbosVersion, debugMode, &zeroGas)
moduleActivationMandatory := false
info, asmMap, err := activateProgramInternal(common.Address{}, codeHash, wasm, progParams.PageLimit, program.version, zeroArbosVersion, debugMode, &zeroGas, targets, moduleActivationMandatory)
if err != nil {
log.Error("failed to reactivate program while rebuilding wasm store", "expected moduleHash", moduleHash, "err", err)
return fmt.Errorf("failed to reactivate program while rebuilding wasm store: %w", err)
Expand Down
3 changes: 0 additions & 3 deletions execution/gethexec/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,6 @@ func (c *StylusTargetConfig) Validate() error {
}
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 {
Expand Down
2 changes: 1 addition & 1 deletion go-ethereum
4 changes: 3 additions & 1 deletion system_tests/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1429,6 +1429,7 @@ func createNonL1BlockChainWithStackConfig(
if execConfig == nil {
execConfig = ExecConfigDefaultTest(t)
}
Require(t, execConfig.Validate())

stack, err := node.New(stackConfig)
Require(t, err)
Expand Down Expand Up @@ -1516,6 +1517,8 @@ func Create2ndNodeWithConfig(
if execConfig == nil {
execConfig = ExecConfigDefaultNonSequencerTest(t)
}
Require(t, execConfig.Validate())

feedErrChan := make(chan error, 10)
parentChainRpcClient := parentChainStack.Attach()
parentChainClient := ethclient.NewClient(parentChainRpcClient)
Expand Down Expand Up @@ -1549,7 +1552,6 @@ func Create2ndNodeWithConfig(

AddValNodeIfNeeded(t, ctx, nodeConfig, true, "", valnodeConfig.Wasm.RootPath)

Require(t, execConfig.Validate())
Require(t, nodeConfig.Validate())
configFetcher := func() *gethexec.Config { return execConfig }
currentExec, err := gethexec.CreateExecutionNode(ctx, chainStack, chainDb, blockchain, parentChainClient, configFetcher)
Expand Down
Loading

0 comments on commit a1fc664

Please sign in to comment.