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 all 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
91 changes: 85 additions & 6 deletions core/rawdb/accessors_state_arbitrum.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,99 @@
package rawdb

import (
"fmt"
"runtime"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethdb"
"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)
type Target string

const (
TargetWavm Target = "wavm"
TargetArm64 Target = "arm64"
TargetAmd64 Target = "amd64"
TargetHost Target = "host"
)

func LocalTarget() Target {
if runtime.GOOS == "linux" {
switch runtime.GOARCH {
case "arm64":
return TargetArm64
case "amd64":
return TargetAmd64
}
}
return TargetHost
}

func (t Target) keyPrefix() (WasmPrefix, error) {
var prefix WasmPrefix
switch t {
case TargetWavm:
prefix = activatedAsmWavmPrefix
case TargetArm64:
prefix = activatedAsmArmPrefix
case TargetAmd64:
prefix = activatedAsmX86Prefix
case TargetHost:
prefix = activatedAsmHostPrefix
default:
return WasmPrefix{}, fmt.Errorf("invalid target: %v", t)
}
return prefix, nil
}

func (t Target) IsValid() bool {
_, err := t.keyPrefix()
return err == nil
}

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

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

// Stores the activated asm for a given moduleHash and target
func WriteActivatedAsm(db ethdb.KeyValueWriter, target Target, moduleHash common.Hash, asm []byte) {
prefix, err := target.keyPrefix()
if err != nil {
log.Crit("Failed to store activated wasm asm", "err", err)
}
key := activatedKey(prefix, moduleHash)
if err := db.Put(key[:], asm); err != nil {
log.Crit("Failed to store activated wasm asm", "err", err)
}
}

// Retrieves the activated asm for a given moduleHash and target
func ReadActivatedAsm(db ethdb.KeyValueReader, target Target, moduleHash common.Hash) []byte {
prefix, err := target.keyPrefix()
if err != nil {
log.Crit("Failed to read activated wasm asm", "err", err)
}
key := activatedKey(prefix, moduleHash)
asm, err := db.Get(key[:])
if err != nil {
return nil
}
return asm
}

key = ActivatedModuleKey(moduleHash)
if err := db.Put(key[:], module); err != nil {
log.Crit("Failed to store activated wasm module", "err", err)
// 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)
}
}

// Retrieves wasm schema version
func ReadWasmSchemaVersion(db ethdb.KeyValueReader) ([]byte, error) {
return db.Get(wasmSchemaVersionKey)
}
53 changes: 23 additions & 30 deletions core/rawdb/schema_arbitrum.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,48 +19,41 @@
package rawdb

import (
"bytes"

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

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

const WasmPrefixLen = 3

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

type WasmPrefix = [WasmPrefixLen]byte
type WasmKey = [WasmKeyLen]byte

func ActivatedAsmKey(moduleHash common.Hash) WasmKey {
return newWasmKey(activatedAsmPrefix, moduleHash)
}
var (
wasmSchemaVersionKey = []byte("WasmSchemaVersion")

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

func ActivatedModuleKey(moduleHash common.Hash) WasmKey {
return newWasmKey(activatedModulePrefix, moduleHash)
func DeprecatedPrefixesV0() (keyPrefixes [][]byte, keyLength int) {
return [][]byte{
// deprecated prefixes, used in version 0x00, purged in version 0x01
[]byte{0x00, 'w', 'a'}, // ActivatedAsmPrefix
[]byte{0x00, 'w', 'm'}, // ActivatedModulePrefix
}, 3 + 32
}

// key = prefix + moduleHash
func newWasmKey(prefix []byte, moduleHash common.Hash) WasmKey {
func activatedKey(prefix WasmPrefix, moduleHash common.Hash) WasmKey {
var key WasmKey
copy(key[:3], prefix)
copy(key[3:], moduleHash[:])
copy(key[:WasmPrefixLen], prefix[:])
copy(key[WasmPrefixLen:], 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(target rawdb.Target, 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
target rawdb.Target
}

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(target rawdb.Target, moduleHash common.Hash) ([]byte, error) {
cacheKey := activatedAsmCacheKey{moduleHash, target}
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, target, 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 @@ -2,6 +2,7 @@ package state

import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
)

type wasmActivation struct {
Expand Down Expand Up @@ -43,7 +44,7 @@ type EvictWasm struct {
}

func (ch EvictWasm) revert(s *StateDB) {
asm, err := s.TryGetActivatedAsm(ch.ModuleHash) // only happens in native mode
asm, err := s.TryGetActivatedAsm(rawdb.LocalTarget(), 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