Skip to content

Commit 85dc1b7

Browse files
authored
Merge pull request #339 from OffchainLabs/wasm-store-compile-target
add support for wasm compile targets
2 parents 5b905ae + 575062f commit 85dc1b7

8 files changed

+180
-116
lines changed

core/rawdb/accessors_state_arbitrum.go

+85-6
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,99 @@
1717
package rawdb
1818

1919
import (
20+
"fmt"
21+
"runtime"
22+
2023
"github.com/ethereum/go-ethereum/common"
2124
"github.com/ethereum/go-ethereum/ethdb"
2225
"github.com/ethereum/go-ethereum/log"
2326
)
2427

25-
// Stores the activated asm and module for a given codeHash
26-
func WriteActivation(db ethdb.KeyValueWriter, moduleHash common.Hash, asm, module []byte) {
27-
key := ActivatedAsmKey(moduleHash)
28+
type Target string
29+
30+
const (
31+
TargetWavm Target = "wavm"
32+
TargetArm64 Target = "arm64"
33+
TargetAmd64 Target = "amd64"
34+
TargetHost Target = "host"
35+
)
36+
37+
func LocalTarget() Target {
38+
if runtime.GOOS == "linux" {
39+
switch runtime.GOARCH {
40+
case "arm64":
41+
return TargetArm64
42+
case "amd64":
43+
return TargetAmd64
44+
}
45+
}
46+
return TargetHost
47+
}
48+
49+
func (t Target) keyPrefix() (WasmPrefix, error) {
50+
var prefix WasmPrefix
51+
switch t {
52+
case TargetWavm:
53+
prefix = activatedAsmWavmPrefix
54+
case TargetArm64:
55+
prefix = activatedAsmArmPrefix
56+
case TargetAmd64:
57+
prefix = activatedAsmX86Prefix
58+
case TargetHost:
59+
prefix = activatedAsmHostPrefix
60+
default:
61+
return WasmPrefix{}, fmt.Errorf("invalid target: %v", t)
62+
}
63+
return prefix, nil
64+
}
65+
66+
func (t Target) IsValid() bool {
67+
_, err := t.keyPrefix()
68+
return err == nil
69+
}
70+
71+
var Targets = []Target{TargetWavm, TargetArm64, TargetAmd64, TargetHost}
72+
73+
func WriteActivation(db ethdb.KeyValueWriter, moduleHash common.Hash, asmMap map[Target][]byte) {
74+
for target, asm := range asmMap {
75+
WriteActivatedAsm(db, target, moduleHash, asm)
76+
}
77+
}
78+
79+
// Stores the activated asm for a given moduleHash and target
80+
func WriteActivatedAsm(db ethdb.KeyValueWriter, target Target, moduleHash common.Hash, asm []byte) {
81+
prefix, err := target.keyPrefix()
82+
if err != nil {
83+
log.Crit("Failed to store activated wasm asm", "err", err)
84+
}
85+
key := activatedKey(prefix, moduleHash)
2886
if err := db.Put(key[:], asm); err != nil {
2987
log.Crit("Failed to store activated wasm asm", "err", err)
3088
}
89+
}
90+
91+
// Retrieves the activated asm for a given moduleHash and target
92+
func ReadActivatedAsm(db ethdb.KeyValueReader, target Target, moduleHash common.Hash) []byte {
93+
prefix, err := target.keyPrefix()
94+
if err != nil {
95+
log.Crit("Failed to read activated wasm asm", "err", err)
96+
}
97+
key := activatedKey(prefix, moduleHash)
98+
asm, err := db.Get(key[:])
99+
if err != nil {
100+
return nil
101+
}
102+
return asm
103+
}
31104

32-
key = ActivatedModuleKey(moduleHash)
33-
if err := db.Put(key[:], module); err != nil {
34-
log.Crit("Failed to store activated wasm module", "err", err)
105+
// Stores wasm schema version
106+
func WriteWasmSchemaVersion(db ethdb.KeyValueWriter) {
107+
if err := db.Put(wasmSchemaVersionKey, []byte{WasmSchemaVersion}); err != nil {
108+
log.Crit("Failed to store wasm schema version", "err", err)
35109
}
36110
}
111+
112+
// Retrieves wasm schema version
113+
func ReadWasmSchemaVersion(db ethdb.KeyValueReader) ([]byte, error) {
114+
return db.Get(wasmSchemaVersionKey)
115+
}

core/rawdb/schema_arbitrum.go

+23-30
Original file line numberDiff line numberDiff line change
@@ -19,48 +19,41 @@
1919
package rawdb
2020

2121
import (
22-
"bytes"
23-
2422
"github.com/ethereum/go-ethereum/common"
2523
)
2624

27-
var (
28-
activatedAsmPrefix = []byte{0x00, 'w', 'a'} // (prefix, moduleHash) -> stylus asm
29-
activatedModulePrefix = []byte{0x00, 'w', 'm'} // (prefix, moduleHash) -> stylus module
30-
)
25+
const WasmSchemaVersion byte = 0x01
26+
27+
const WasmPrefixLen = 3
3128

3229
// WasmKeyLen = CompiledWasmCodePrefix + moduleHash
33-
const WasmKeyLen = 3 + 32
30+
const WasmKeyLen = WasmPrefixLen + common.HashLength
3431

32+
type WasmPrefix = [WasmPrefixLen]byte
3533
type WasmKey = [WasmKeyLen]byte
3634

37-
func ActivatedAsmKey(moduleHash common.Hash) WasmKey {
38-
return newWasmKey(activatedAsmPrefix, moduleHash)
39-
}
35+
var (
36+
wasmSchemaVersionKey = []byte("WasmSchemaVersion")
37+
38+
// 0x00 prefix to avoid conflicts when wasmdb is not separate database
39+
activatedAsmWavmPrefix = WasmPrefix{0x00, 'w', 'w'} // (prefix, moduleHash) -> stylus module (wavm)
40+
activatedAsmArmPrefix = WasmPrefix{0x00, 'w', 'r'} // (prefix, moduleHash) -> stylus asm for ARM system
41+
activatedAsmX86Prefix = WasmPrefix{0x00, 'w', 'x'} // (prefix, moduleHash) -> stylus asm for x86 system
42+
activatedAsmHostPrefix = WasmPrefix{0x00, 'w', 'h'} // (prefix, moduleHash) -> stylus asm for system other then ARM and x86
43+
)
4044

41-
func ActivatedModuleKey(moduleHash common.Hash) WasmKey {
42-
return newWasmKey(activatedModulePrefix, moduleHash)
45+
func DeprecatedPrefixesV0() (keyPrefixes [][]byte, keyLength int) {
46+
return [][]byte{
47+
// deprecated prefixes, used in version 0x00, purged in version 0x01
48+
[]byte{0x00, 'w', 'a'}, // ActivatedAsmPrefix
49+
[]byte{0x00, 'w', 'm'}, // ActivatedModulePrefix
50+
}, 3 + 32
4351
}
4452

4553
// key = prefix + moduleHash
46-
func newWasmKey(prefix []byte, moduleHash common.Hash) WasmKey {
54+
func activatedKey(prefix WasmPrefix, moduleHash common.Hash) WasmKey {
4755
var key WasmKey
48-
copy(key[:3], prefix)
49-
copy(key[3:], moduleHash[:])
56+
copy(key[:WasmPrefixLen], prefix[:])
57+
copy(key[WasmPrefixLen:], moduleHash[:])
5058
return key
5159
}
52-
53-
func IsActivatedAsmKey(key []byte) (bool, common.Hash) {
54-
return extractWasmKey(activatedAsmPrefix, key)
55-
}
56-
57-
func IsActivatedModuleKey(key []byte) (bool, common.Hash) {
58-
return extractWasmKey(activatedModulePrefix, key)
59-
}
60-
61-
func extractWasmKey(prefix, key []byte) (bool, common.Hash) {
62-
if !bytes.HasPrefix(key, prefix) || len(key) != WasmKeyLen {
63-
return false, common.Hash{}
64-
}
65-
return true, common.BytesToHash(key[len(prefix):])
66-
}

core/state/database.go

+12-11
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ const (
5353
// Database wraps access to tries and contract code.
5454
type Database interface {
5555
// Arbitrum: Read activated Stylus contracts
56-
ActivatedAsm(moduleHash common.Hash) (asm []byte, err error)
57-
ActivatedModule(moduleHash common.Hash) (module []byte, err error)
56+
ActivatedAsm(target rawdb.Target, moduleHash common.Hash) (asm []byte, err error)
5857
WasmStore() ethdb.KeyValueStore
5958
WasmCacheTag() uint32
6059

@@ -164,9 +163,8 @@ func NewDatabaseWithConfig(db ethdb.Database, config *triedb.Config) Database {
164163
wasmdb, wasmTag := db.WasmDataBase()
165164
cdb := &cachingDB{
166165
// Arbitrum only
167-
activatedAsmCache: lru.NewSizeConstrainedCache[common.Hash, []byte](activatedWasmCacheSize),
168-
activatedModuleCache: lru.NewSizeConstrainedCache[common.Hash, []byte](activatedWasmCacheSize),
169-
wasmTag: wasmTag,
166+
activatedAsmCache: lru.NewSizeConstrainedCache[activatedAsmCacheKey, []byte](activatedWasmCacheSize),
167+
wasmTag: wasmTag,
170168

171169
disk: db,
172170
wasmdb: wasmdb,
@@ -182,9 +180,8 @@ func NewDatabaseWithNodeDB(db ethdb.Database, triedb *triedb.Database) Database
182180
wasmdb, wasmTag := db.WasmDataBase()
183181
cdb := &cachingDB{
184182
// Arbitrum only
185-
activatedAsmCache: lru.NewSizeConstrainedCache[common.Hash, []byte](activatedWasmCacheSize),
186-
activatedModuleCache: lru.NewSizeConstrainedCache[common.Hash, []byte](activatedWasmCacheSize),
187-
wasmTag: wasmTag,
183+
activatedAsmCache: lru.NewSizeConstrainedCache[activatedAsmCacheKey, []byte](activatedWasmCacheSize),
184+
wasmTag: wasmTag,
188185

189186
disk: db,
190187
wasmdb: wasmdb,
@@ -195,11 +192,15 @@ func NewDatabaseWithNodeDB(db ethdb.Database, triedb *triedb.Database) Database
195192
return cdb
196193
}
197194

195+
type activatedAsmCacheKey struct {
196+
moduleHash common.Hash
197+
target rawdb.Target
198+
}
199+
198200
type cachingDB struct {
199201
// Arbitrum
200-
activatedAsmCache *lru.SizeConstrainedCache[common.Hash, []byte]
201-
activatedModuleCache *lru.SizeConstrainedCache[common.Hash, []byte]
202-
wasmTag uint32
202+
activatedAsmCache *lru.SizeConstrainedCache[activatedAsmCacheKey, []byte]
203+
wasmTag uint32
203204

204205
disk ethdb.KeyValueStore
205206
wasmdb ethdb.KeyValueStore

core/state/database_arbitrum.go

+5-25
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,14 @@ import (
77
"github.com/ethereum/go-ethereum/core/rawdb"
88
)
99

10-
func (db *cachingDB) ActivatedAsm(moduleHash common.Hash) ([]byte, error) {
11-
if asm, _ := db.activatedAsmCache.Get(moduleHash); len(asm) > 0 {
10+
func (db *cachingDB) ActivatedAsm(target rawdb.Target, moduleHash common.Hash) ([]byte, error) {
11+
cacheKey := activatedAsmCacheKey{moduleHash, target}
12+
if asm, _ := db.activatedAsmCache.Get(cacheKey); len(asm) > 0 {
1213
return asm, nil
1314
}
14-
wasmKey := rawdb.ActivatedAsmKey(moduleHash)
15-
asm, err := db.wasmdb.Get(wasmKey[:])
16-
if err != nil {
17-
return nil, err
18-
}
19-
if len(asm) > 0 {
20-
db.activatedAsmCache.Add(moduleHash, asm)
15+
if asm := rawdb.ReadActivatedAsm(db.wasmdb, target, moduleHash); len(asm) > 0 {
16+
db.activatedAsmCache.Add(cacheKey, asm)
2117
return asm, nil
2218
}
2319
return nil, errors.New("not found")
2420
}
25-
26-
func (db *cachingDB) ActivatedModule(moduleHash common.Hash) ([]byte, error) {
27-
if module, _ := db.activatedModuleCache.Get(moduleHash); len(module) > 0 {
28-
return module, nil
29-
}
30-
wasmKey := rawdb.ActivatedModuleKey(moduleHash)
31-
module, err := db.wasmdb.Get(wasmKey[:])
32-
if err != nil {
33-
return nil, err
34-
}
35-
if len(module) > 0 {
36-
db.activatedModuleCache.Add(moduleHash, module)
37-
return module, nil
38-
}
39-
return nil, errors.New("not found")
40-
}

core/state/journal_arbitrum.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package state
22

33
import (
44
"github.com/ethereum/go-ethereum/common"
5+
"github.com/ethereum/go-ethereum/core/rawdb"
56
)
67

78
type wasmActivation struct {
@@ -43,7 +44,7 @@ type EvictWasm struct {
4344
}
4445

4546
func (ch EvictWasm) revert(s *StateDB) {
46-
asm, err := s.TryGetActivatedAsm(ch.ModuleHash) // only happens in native mode
47+
asm, err := s.TryGetActivatedAsm(rawdb.LocalTarget(), ch.ModuleHash) // only happens in native mode
4748
if err == nil && len(asm) != 0 {
4849
//if we failed to get it - it's not in the current rust cache
4950
CacheWasmRust(asm, ch.ModuleHash, ch.Version, ch.Tag, ch.Debug)

core/state/statedb.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error)
160160
unexpectedBalanceDelta: new(big.Int),
161161
openWasmPages: 0,
162162
everWasmPages: 0,
163-
activatedWasms: make(map[common.Hash]*ActivatedWasm),
163+
activatedWasms: make(map[common.Hash]ActivatedWasm),
164164
recentWasms: NewRecentWasms(),
165165
},
166166

@@ -722,7 +722,7 @@ func (s *StateDB) Copy() *StateDB {
722722
state := &StateDB{
723723
arbExtraData: &ArbitrumExtraData{
724724
unexpectedBalanceDelta: new(big.Int).Set(s.arbExtraData.unexpectedBalanceDelta),
725-
activatedWasms: make(map[common.Hash]*ActivatedWasm, len(s.arbExtraData.activatedWasms)),
725+
activatedWasms: make(map[common.Hash]ActivatedWasm, len(s.arbExtraData.activatedWasms)),
726726
recentWasms: s.arbExtraData.recentWasms.Copy(),
727727
openWasmPages: s.arbExtraData.openWasmPages,
728728
everWasmPages: s.arbExtraData.everWasmPages,
@@ -825,9 +825,9 @@ func (s *StateDB) Copy() *StateDB {
825825
state.arbExtraData.userWasms[call] = wasm
826826
}
827827
}
828-
for moduleHash, info := range s.arbExtraData.activatedWasms {
828+
for moduleHash, asmMap := range s.arbExtraData.activatedWasms {
829829
// It's fine to skip a deep copy since activations are immutable.
830-
state.arbExtraData.activatedWasms[moduleHash] = info
830+
state.arbExtraData.activatedWasms[moduleHash] = asmMap
831831
}
832832

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

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

12941294
if codeWriter.ValueSize() > 0 {

0 commit comments

Comments
 (0)