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

add support for wasm compile targets #339

Merged
merged 27 commits into from
Aug 17, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4027003
rawdb: add support for multiple compile targets
magicxyyz Jul 11, 2024
e0ac28c
map from target to asm
magicxyyz Jul 15, 2024
ee41c04
Merge branch 'master' into wasm-store-compile-target
magicxyyz Jul 15, 2024
74bb00e
Merge branch 'master' into wasm-store-compile-target
magicxyyz Jul 22, 2024
b1a40de
improve error handling in TryGetActivatedAsmMap
magicxyyz Jul 22, 2024
c166c0b
Merge branch 'master' into wasm-store-compile-target
magicxyyz Jul 23, 2024
ff2a8bc
export WasmSchemaVersion
magicxyyz Jul 24, 2024
a67b1f8
unify apis for stylus modules (wavm) and native asms
magicxyyz Aug 2, 2024
c700dab
pass targetNames to StateDB.TryGetActivatedAsmMap
magicxyyz Aug 6, 2024
04d7d72
fix StateDB.TryGetActivatedAsmMap
magicxyyz Aug 6, 2024
c4c2994
set wasm schema version to 0
magicxyyz Aug 9, 2024
1086023
return early in RecordProgram if called with empty targetNames slice
magicxyyz Aug 9, 2024
896fca1
rename targets X86 -> amd64 and arm -> arm64 (matching GOARCH)
magicxyyz Aug 9, 2024
bbbcec2
Revert "set wasm schema version to 0"
magicxyyz Aug 9, 2024
7e37376
declare new type for target
magicxyyz Aug 12, 2024
6976d72
use target type
magicxyyz Aug 12, 2024
c359493
add string decoding/encoding for rawdb.Target
magicxyyz Aug 12, 2024
e09c6f8
rename ActivateWasm parameter
magicxyyz Aug 12, 2024
034c335
fix joining errors in TryGetActivatedAsmMap
magicxyyz Aug 12, 2024
a75f682
add rawdb.Target.keyPrefix and rawdb.Target.IsValid
magicxyyz Aug 12, 2024
01e2210
remove rawdb.TargetFromString and rawdb.Target.ToString
magicxyyz Aug 12, 2024
5ed6b5f
return error from ReadWasmSchemaVersion
magicxyyz Aug 12, 2024
59cf3e3
add rawdb.DeprecatedKeysV0
magicxyyz Aug 12, 2024
d055235
Merge branch 'master' into wasm-store-compile-target
magicxyyz Aug 12, 2024
aa44bd4
add LocalTarget() to rawdb, use LocalTarget() in EvictWasm.Revert
magicxyyz Aug 15, 2024
abc46c6
rename DeprecatedKeysV0 to DeprecatedPrefixesV0
magicxyyz Aug 16, 2024
575062f
define WasmPrefix type as [3]byte
magicxyyz Aug 16, 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
73 changes: 67 additions & 6 deletions core/rawdb/accessors_state_arbitrum.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,76 @@ import (
"github.com/ethereum/go-ethereum/log"
)

// Stores the activated asm and module for a given codeHash
func WriteActivation(db ethdb.KeyValueWriter, moduleHash common.Hash, asm, module []byte) {
key := ActivatedAsmKey(moduleHash)
const (
TargetWavm = "wavm"
TargetArm64 = "arm64"
TargetAmd64 = "amd64"
TargetHost = "host"
)
magicxyyz marked this conversation as resolved.
Show resolved Hide resolved

var Targets = []string{TargetWavm, TargetArm64, TargetAmd64, TargetHost}

func WriteActivation(db ethdb.KeyValueWriter, moduleHash common.Hash, asmMap map[string][]byte) {
for target, asm := range asmMap {
WriteActivatedAsm(db, target, moduleHash, asm)
}
}

// Stores the activated asm for a given moduleHash and targetName
func WriteActivatedAsm(db ethdb.KeyValueWriter, targetName string, moduleHash common.Hash, asm []byte) {
var prefix []byte
switch targetName {
case TargetWavm:
prefix = activatedAsmWavmPrefix
case TargetArm64:
prefix = activatedAsmArmPrefix
case TargetAmd64:
prefix = activatedAsmX86Prefix
case TargetHost:
prefix = activatedAsmHostPrefix
default:
log.Crit("Failed to store activated wasm asm, invalid targetName specified", "targetName", targetName)
}
key := activatedKey(prefix, moduleHash)
magicxyyz marked this conversation as resolved.
Show resolved Hide resolved
if err := db.Put(key[:], asm); err != nil {
log.Crit("Failed to store activated wasm asm", "err", err)
}
}

func ReadActivatedAsm(db ethdb.KeyValueReader, targetName string, moduleHash common.Hash) []byte {
var prefix []byte
switch targetName {
case TargetWavm:
prefix = activatedAsmWavmPrefix
case TargetArm64:
prefix = activatedAsmArmPrefix
case TargetAmd64:
prefix = activatedAsmX86Prefix
case TargetHost:
prefix = activatedAsmHostPrefix
default:
log.Crit("Failed to store activated wasm asm, invalid targetName specified", "targetName", targetName)
}
key := activatedKey(prefix, moduleHash)
asm, err := db.Get(key[:])
if err != nil {
return nil
}
return asm
}

// Stores wasm schema version
func WriteWasmSchemaVersion(db ethdb.KeyValueWriter) {
if err := db.Put(wasmSchemaVersionKey, []byte{WasmSchemaVersion}); err != nil {
log.Crit("Failed to store wasm schema version", "err", err)
}
}

key = ActivatedModuleKey(moduleHash)
if err := db.Put(key[:], module); err != nil {
log.Crit("Failed to store activated wasm module", "err", err)
// Retrieves wasm schema version, if the corresponding key is not found returns version 0
func ReadWasmSchemaVersion(db ethdb.KeyValueReader) []byte {
version, err := db.Get(wasmSchemaVersionKey)
if err != nil || len(version) == 0 {
return []byte{0}
gligneul marked this conversation as resolved.
Show resolved Hide resolved
}
return version
}
40 changes: 11 additions & 29 deletions core/rawdb/schema_arbitrum.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,48 +19,30 @@
package rawdb

import (
"bytes"

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

const WasmSchemaVersion byte = 0x01

var (
activatedAsmPrefix = []byte{0x00, 'w', 'a'} // (prefix, moduleHash) -> stylus asm
activatedModulePrefix = []byte{0x00, 'w', 'm'} // (prefix, moduleHash) -> stylus module
wasmSchemaVersionKey = []byte("WasmSchemaVersion")

// 0x00 prefix to avoid conflicts when wasmdb is not separate database
activatedAsmWavmPrefix = []byte{0x00, 'w', 'w'} // (prefix, moduleHash) -> stylus module (wavm)
activatedAsmArmPrefix = []byte{0x00, 'w', 'r'} // (prefix, moduleHash) -> stylus asm for ARM system
activatedAsmX86Prefix = []byte{0x00, 'w', 'x'} // (prefix, moduleHash) -> stylus asm for x86 system
activatedAsmHostPrefix = []byte{0x00, 'w', 'h'} // (prefix, moduleHash) -> stylus asm for system other then ARM and x86
)

// WasmKeyLen = CompiledWasmCodePrefix + moduleHash
const WasmKeyLen = 3 + 32
const WasmKeyLen = 3 + common.HashLength

type WasmKey = [WasmKeyLen]byte

func ActivatedAsmKey(moduleHash common.Hash) WasmKey {
return newWasmKey(activatedAsmPrefix, moduleHash)
}

func ActivatedModuleKey(moduleHash common.Hash) WasmKey {
return newWasmKey(activatedModulePrefix, moduleHash)
}

// key = prefix + moduleHash
func newWasmKey(prefix []byte, moduleHash common.Hash) WasmKey {
func activatedKey(prefix []byte, moduleHash common.Hash) WasmKey {
var key WasmKey
copy(key[:3], prefix)
magicxyyz marked this conversation as resolved.
Show resolved Hide resolved
copy(key[3:], moduleHash[:])
return key
}

func IsActivatedAsmKey(key []byte) (bool, common.Hash) {
return extractWasmKey(activatedAsmPrefix, key)
}

func IsActivatedModuleKey(key []byte) (bool, common.Hash) {
return extractWasmKey(activatedModulePrefix, key)
}

func extractWasmKey(prefix, key []byte) (bool, common.Hash) {
if !bytes.HasPrefix(key, prefix) || len(key) != WasmKeyLen {
return false, common.Hash{}
}
return true, common.BytesToHash(key[len(prefix):])
}
23 changes: 12 additions & 11 deletions core/state/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ const (
// Database wraps access to tries and contract code.
type Database interface {
// Arbitrum: Read activated Stylus contracts
ActivatedAsm(moduleHash common.Hash) (asm []byte, err error)
ActivatedModule(moduleHash common.Hash) (module []byte, err error)
ActivatedAsm(targetName string, moduleHash common.Hash) (asm []byte, err error)
WasmStore() ethdb.KeyValueStore
WasmCacheTag() uint32

Expand Down Expand Up @@ -164,9 +163,8 @@ func NewDatabaseWithConfig(db ethdb.Database, config *triedb.Config) Database {
wasmdb, wasmTag := db.WasmDataBase()
cdb := &cachingDB{
// Arbitrum only
activatedAsmCache: lru.NewSizeConstrainedCache[common.Hash, []byte](activatedWasmCacheSize),
activatedModuleCache: lru.NewSizeConstrainedCache[common.Hash, []byte](activatedWasmCacheSize),
wasmTag: wasmTag,
activatedAsmCache: lru.NewSizeConstrainedCache[activatedAsmCacheKey, []byte](activatedWasmCacheSize),
wasmTag: wasmTag,

disk: db,
wasmdb: wasmdb,
Expand All @@ -182,9 +180,8 @@ func NewDatabaseWithNodeDB(db ethdb.Database, triedb *triedb.Database) Database
wasmdb, wasmTag := db.WasmDataBase()
cdb := &cachingDB{
// Arbitrum only
activatedAsmCache: lru.NewSizeConstrainedCache[common.Hash, []byte](activatedWasmCacheSize),
activatedModuleCache: lru.NewSizeConstrainedCache[common.Hash, []byte](activatedWasmCacheSize),
wasmTag: wasmTag,
activatedAsmCache: lru.NewSizeConstrainedCache[activatedAsmCacheKey, []byte](activatedWasmCacheSize),
wasmTag: wasmTag,

disk: db,
wasmdb: wasmdb,
Expand All @@ -195,11 +192,15 @@ func NewDatabaseWithNodeDB(db ethdb.Database, triedb *triedb.Database) Database
return cdb
}

type activatedAsmCacheKey struct {
moduleHash common.Hash
targetName string
}

type cachingDB struct {
// Arbitrum
activatedAsmCache *lru.SizeConstrainedCache[common.Hash, []byte]
activatedModuleCache *lru.SizeConstrainedCache[common.Hash, []byte]
wasmTag uint32
activatedAsmCache *lru.SizeConstrainedCache[activatedAsmCacheKey, []byte]
wasmTag uint32

disk ethdb.KeyValueStore
wasmdb ethdb.KeyValueStore
Expand Down
30 changes: 5 additions & 25 deletions core/state/database_arbitrum.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,14 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
)

func (db *cachingDB) ActivatedAsm(moduleHash common.Hash) ([]byte, error) {
if asm, _ := db.activatedAsmCache.Get(moduleHash); len(asm) > 0 {
func (db *cachingDB) ActivatedAsm(targetName string, moduleHash common.Hash) ([]byte, error) {
cacheKey := activatedAsmCacheKey{moduleHash, targetName}
if asm, _ := db.activatedAsmCache.Get(cacheKey); len(asm) > 0 {
return asm, nil
}
wasmKey := rawdb.ActivatedAsmKey(moduleHash)
asm, err := db.wasmdb.Get(wasmKey[:])
if err != nil {
return nil, err
}
if len(asm) > 0 {
db.activatedAsmCache.Add(moduleHash, asm)
if asm := rawdb.ReadActivatedAsm(db.wasmdb, targetName, moduleHash); len(asm) > 0 {
db.activatedAsmCache.Add(cacheKey, asm)
return asm, nil
}
return nil, errors.New("not found")
}

func (db *cachingDB) ActivatedModule(moduleHash common.Hash) ([]byte, error) {
if module, _ := db.activatedModuleCache.Get(moduleHash); len(module) > 0 {
return module, nil
}
wasmKey := rawdb.ActivatedModuleKey(moduleHash)
module, err := db.wasmdb.Get(wasmKey[:])
if err != nil {
return nil, err
}
if len(module) > 0 {
db.activatedModuleCache.Add(moduleHash, module)
return module, nil
}
return nil, errors.New("not found")
}
3 changes: 2 additions & 1 deletion core/state/journal_arbitrum.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,15 @@ func (ch CacheWasm) dirtied() *common.Address {
}

type EvictWasm struct {
Arch string
ModuleHash common.Hash
Version uint16
Tag uint32
Debug bool
}

func (ch EvictWasm) revert(s *StateDB) {
asm, err := s.TryGetActivatedAsm(ch.ModuleHash) // only happens in native mode
asm, err := s.TryGetActivatedAsm(ch.Arch, ch.ModuleHash) // only happens in native mode
if err == nil && len(asm) != 0 {
//if we failed to get it - it's not in the current rust cache
CacheWasmRust(asm, ch.ModuleHash, ch.Version, ch.Tag, ch.Debug)
Expand Down
14 changes: 7 additions & 7 deletions core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error)
unexpectedBalanceDelta: new(big.Int),
openWasmPages: 0,
everWasmPages: 0,
activatedWasms: make(map[common.Hash]*ActivatedWasm),
activatedWasms: make(map[common.Hash]ActivatedWasm),
recentWasms: NewRecentWasms(),
},

Expand Down Expand Up @@ -722,7 +722,7 @@ func (s *StateDB) Copy() *StateDB {
state := &StateDB{
arbExtraData: &ArbitrumExtraData{
unexpectedBalanceDelta: new(big.Int).Set(s.arbExtraData.unexpectedBalanceDelta),
activatedWasms: make(map[common.Hash]*ActivatedWasm, len(s.arbExtraData.activatedWasms)),
activatedWasms: make(map[common.Hash]ActivatedWasm, len(s.arbExtraData.activatedWasms)),
recentWasms: s.arbExtraData.recentWasms.Copy(),
openWasmPages: s.arbExtraData.openWasmPages,
everWasmPages: s.arbExtraData.everWasmPages,
Expand Down Expand Up @@ -825,9 +825,9 @@ func (s *StateDB) Copy() *StateDB {
state.arbExtraData.userWasms[call] = wasm
}
}
for moduleHash, info := range s.arbExtraData.activatedWasms {
for moduleHash, asmMap := range s.arbExtraData.activatedWasms {
// It's fine to skip a deep copy since activations are immutable.
state.arbExtraData.activatedWasms[moduleHash] = info
state.arbExtraData.activatedWasms[moduleHash] = asmMap
}

// If there's a prefetcher running, make an inactive copy of it that can
Expand Down Expand Up @@ -1284,11 +1284,11 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er
}

// Arbitrum: write Stylus programs to disk
for moduleHash, info := range s.arbExtraData.activatedWasms {
rawdb.WriteActivation(wasmCodeWriter, moduleHash, info.Asm, info.Module)
for moduleHash, asmMap := range s.arbExtraData.activatedWasms {
rawdb.WriteActivation(wasmCodeWriter, moduleHash, asmMap)
}
if len(s.arbExtraData.activatedWasms) > 0 {
s.arbExtraData.activatedWasms = make(map[common.Hash]*ActivatedWasm)
s.arbExtraData.activatedWasms = make(map[common.Hash]ActivatedWasm)
}

if codeWriter.ValueSize() > 0 {
Expand Down
Loading
Loading