Skip to content

Commit

Permalink
Merge branch 'master' into pebble-extra-options
Browse files Browse the repository at this point in the history
  • Loading branch information
magicxyyz authored May 22, 2024
2 parents 5b7b36a + 3ad1488 commit 07f6d7a
Show file tree
Hide file tree
Showing 14 changed files with 107 additions and 26 deletions.
11 changes: 10 additions & 1 deletion arbitrum/apibackend.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ var (
type APIBackend struct {
b *Backend

dbForAPICalls ethdb.Database

fallbackClient types.FallbackClient
sync SyncProgressBackend
}
Expand Down Expand Up @@ -101,8 +103,15 @@ func createRegisterAPIBackend(backend *Backend, filterConfig filters.Config, fal
if err != nil {
return nil, err
}
// discard stylus-tag on any call made from api database
dbForAPICalls := backend.chainDb
wasmStore, tag := backend.chainDb.WasmDataBase()
if tag != 0 {
dbForAPICalls = rawdb.WrapDatabaseWithWasm(backend.chainDb, wasmStore, 0)
}
backend.apiBackend = &APIBackend{
b: backend,
dbForAPICalls: dbForAPICalls,
fallbackClient: fallbackClient,
}
filterSystem := filters.NewFilterSystem(backend.apiBackend, filterConfig)
Expand Down Expand Up @@ -314,7 +323,7 @@ func (a *APIBackend) FeeHistory(
}

func (a *APIBackend) ChainDb() ethdb.Database {
return a.b.chainDb
return a.dbForAPICalls
}

func (a *APIBackend) AccountManager() *accounts.Manager {
Expand Down
8 changes: 1 addition & 7 deletions arbitrum/recordingdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,6 @@ func (db *RecordingKV) Get(key []byte) ([]byte, error) {
// Retrieving code
copy(hash[:], key[len(rawdb.CodePrefix):])
res, err = db.diskDb.Get(key)
} else if ok, _ := rawdb.IsActivatedAsmKey(key); ok {
// Arbitrum: the asm is non-consensus
return db.diskDb.Get(key)
} else if ok, _ := rawdb.IsActivatedModuleKey(key); ok {
// Arbitrum: the module is non-consensus (only its hash is)
return db.diskDb.Get(key)
} else {
err = fmt.Errorf("recording KV attempted to access non-hash key %v", hex.EncodeToString(key))
}
Expand Down Expand Up @@ -275,7 +269,7 @@ func (r *RecordingDatabase) PrepareRecording(ctx context.Context, lastBlockHeade
defer func() { r.Dereference(finalDereference) }()
recordingKeyValue := newRecordingKV(r.db.TrieDB(), r.db.DiskDB())

recordingStateDatabase := state.NewDatabase(rawdb.NewDatabase(recordingKeyValue))
recordingStateDatabase := state.NewDatabase(rawdb.WrapDatabaseWithWasm(rawdb.NewDatabase(recordingKeyValue), r.db.WasmStore(), 0))
var prevRoot common.Hash
if lastBlockHeader != nil {
prevRoot = lastBlockHeader.Root
Expand Down
33 changes: 33 additions & 0 deletions core/rawdb/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ type freezerdb struct {
ethdb.AncientStore
}

// AncientDatadir returns the path of root ancient directory.
func (frdb *freezerdb) WasmDataBase() (ethdb.KeyValueStore, uint32) {
return frdb, 0
}

// AncientDatadir returns the path of root ancient directory.
func (frdb *freezerdb) AncientDatadir() (string, error) {
return frdb.ancientRoot, nil
Expand Down Expand Up @@ -165,12 +170,40 @@ func (db *nofreezedb) AncientDatadir() (string, error) {
return "", errNotSupported
}

// AncientDatadir returns the path of root ancient directory.
func (db *nofreezedb) WasmDataBase() (ethdb.KeyValueStore, uint32) {
return db, 0
}

// NewDatabase creates a high level database on top of a given key-value data
// store without a freezer moving immutable chain segments into cold storage.
func NewDatabase(db ethdb.KeyValueStore) ethdb.Database {
return &nofreezedb{KeyValueStore: db}
}

type dbWithWasmEntry struct {
ethdb.Database
wasmDb ethdb.KeyValueStore
wasmCacheTag uint32
}

func (db *dbWithWasmEntry) WasmDataBase() (ethdb.KeyValueStore, uint32) {
return db.wasmDb, db.wasmCacheTag
}

func (db *dbWithWasmEntry) Close() error {
dbErr := db.Database.Close()
wasmErr := db.wasmDb.Close()
if dbErr != nil {
return dbErr
}
return wasmErr
}

func WrapDatabaseWithWasm(db ethdb.Database, wasm ethdb.KeyValueStore, cacheTag uint32) ethdb.Database {
return &dbWithWasmEntry{db, wasm, cacheTag}
}

// resolveChainFreezerDir is a helper function which resolves the absolute path
// of chain freezer by considering backward compatibility.
func resolveChainFreezerDir(ancient string) string {
Expand Down
4 changes: 4 additions & 0 deletions core/rawdb/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ func (t *table) Close() error {
return nil
}

func (t *table) WasmDataBase() (ethdb.KeyValueStore, uint32) {
return t.db.WasmDataBase()
}

// Has retrieves if a prefixed version of a key is present in the database.
func (t *table) Has(key []byte) (bool, error) {
return t.db.Has(append([]byte(t.prefix), key...))
Expand Down
18 changes: 18 additions & 0 deletions core/state/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ type Database interface {
// Arbitrum: Read activated Stylus contracts
ActivatedAsm(moduleHash common.Hash) (asm []byte, err error)
ActivatedModule(moduleHash common.Hash) (module []byte, err error)
WasmStore() ethdb.KeyValueStore
WasmCacheTag() uint32

// OpenTrie opens the main account trie.
OpenTrie(root common.Hash) (Trie, error)
Expand Down Expand Up @@ -158,12 +160,15 @@ func NewDatabase(db ethdb.Database) Database {
// is safe for concurrent use and retains a lot of collapsed RLP trie nodes in a
// large memory cache.
func NewDatabaseWithConfig(db ethdb.Database, config *trie.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,

disk: db,
wasmdb: wasmdb,
codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize),
codeCache: lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize),
triedb: trie.NewDatabase(db, config),
Expand All @@ -173,12 +178,15 @@ func NewDatabaseWithConfig(db ethdb.Database, config *trie.Config) Database {

// NewDatabaseWithNodeDB creates a state database with an already initialized node database.
func NewDatabaseWithNodeDB(db ethdb.Database, triedb *trie.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,

disk: db,
wasmdb: wasmdb,
codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize),
codeCache: lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize),
triedb: triedb,
Expand All @@ -190,13 +198,23 @@ type cachingDB struct {
// Arbitrum
activatedAsmCache *lru.SizeConstrainedCache[common.Hash, []byte]
activatedModuleCache *lru.SizeConstrainedCache[common.Hash, []byte]
wasmTag uint32

disk ethdb.KeyValueStore
wasmdb ethdb.KeyValueStore
codeSizeCache *lru.Cache[common.Hash, int]
codeCache *lru.SizeConstrainedCache[common.Hash, []byte]
triedb *trie.Database
}

func (db *cachingDB) WasmStore() ethdb.KeyValueStore {
return db.wasmdb
}

func (db *cachingDB) WasmCacheTag() uint32 {
return db.wasmTag
}

// OpenTrie opens the main account trie at a specific root hash.
func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
if db.triedb.IsVerkle() {
Expand Down
4 changes: 2 additions & 2 deletions core/state/database_arbitrum.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ func (db *cachingDB) ActivatedAsm(moduleHash common.Hash) ([]byte, error) {
return asm, nil
}
wasmKey := rawdb.ActivatedAsmKey(moduleHash)
asm, err := db.disk.Get(wasmKey[:])
asm, err := db.wasmdb.Get(wasmKey[:])
if err != nil {
return nil, err
}
Expand All @@ -28,7 +28,7 @@ func (db *cachingDB) ActivatedModule(moduleHash common.Hash) ([]byte, error) {
return module, nil
}
wasmKey := rawdb.ActivatedModuleKey(moduleHash)
module, err := db.disk.Get(wasmKey[:])
module, err := db.wasmdb.Get(wasmKey[:])
if err != nil {
return nil, err
}
Expand Down
15 changes: 10 additions & 5 deletions core/state/journal_arbitrum.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,18 @@ func (ch wasmActivation) dirtied() *common.Address {
}

// Updates the Rust-side recent program cache
var CacheWasmRust func(asm []byte, moduleHash common.Hash, version uint16, debug bool) = func([]byte, common.Hash, uint16, bool) {}
var EvictWasmRust func(moduleHash common.Hash, version uint16, debug bool) = func(common.Hash, uint16, bool) {}
var CacheWasmRust func(asm []byte, moduleHash common.Hash, version uint16, tag uint32, debug bool) = func([]byte, common.Hash, uint16, uint32, bool) {}
var EvictWasmRust func(moduleHash common.Hash, version uint16, tag uint32, debug bool) = func(common.Hash, uint16, uint32, bool) {}

type CacheWasm struct {
ModuleHash common.Hash
Version uint16
Tag uint32
Debug bool
}

func (ch CacheWasm) revert(s *StateDB) {
EvictWasmRust(ch.ModuleHash, ch.Version, ch.Debug)
EvictWasmRust(ch.ModuleHash, ch.Version, ch.Tag, ch.Debug)
}

func (ch CacheWasm) dirtied() *common.Address {
Expand All @@ -37,12 +38,16 @@ func (ch CacheWasm) dirtied() *common.Address {
type EvictWasm struct {
ModuleHash common.Hash
Version uint16
Tag uint32
Debug bool
}

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

func (ch EvictWasm) dirtied() *common.Address {
Expand Down
8 changes: 7 additions & 1 deletion core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -1249,6 +1249,7 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er
storageTrieNodesDeleted int
nodes = trienode.NewMergedNodeSet()
codeWriter = s.db.DiskDB().NewBatch()
wasmCodeWriter = s.db.WasmStore().NewBatch()
)
// Handle all state deletions first
incomplete, err := s.handleDestruction(nodes)
Expand Down Expand Up @@ -1286,7 +1287,7 @@ 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(codeWriter, moduleHash, info.Asm, info.Module)
rawdb.WriteActivation(wasmCodeWriter, moduleHash, info.Asm, info.Module)
}
if len(s.arbExtraData.activatedWasms) > 0 {
s.arbExtraData.activatedWasms = make(map[common.Hash]*ActivatedWasm)
Expand All @@ -1297,6 +1298,11 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er
log.Crit("Failed to commit dirty codes", "error", err)
}
}
if wasmCodeWriter.ValueSize() > 0 {
if err := wasmCodeWriter.Write(); err != nil {
log.Crit("Failed to commit dirty stylus codes", "error", err)
}
}
// Write the account trie changes, measuring the amount of wasted time
var start time.Time
if metrics.EnabledExpensive {
Expand Down
17 changes: 9 additions & 8 deletions core/state/statedb_arbitrum.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/lru"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
)
Expand Down Expand Up @@ -89,16 +90,12 @@ func (s *StateDB) ActivateWasm(moduleHash common.Hash, asm, module []byte) {
})
}

func (s *StateDB) GetActivatedAsm(moduleHash common.Hash) []byte {
func (s *StateDB) TryGetActivatedAsm(moduleHash common.Hash) ([]byte, error) {
info, exists := s.arbExtraData.activatedWasms[moduleHash]
if exists {
return info.Asm
return info.Asm, nil
}
asm, err := s.db.ActivatedAsm(moduleHash)
if err != nil {
s.setError(fmt.Errorf("failed to load asm for %x: %v", moduleHash, err))
}
return asm
return s.db.ActivatedAsm(moduleHash)
}

func (s *StateDB) GetActivatedModule(moduleHash common.Hash) []byte {
Expand Down Expand Up @@ -237,9 +234,13 @@ func (s *StateDB) StartRecording() {
}

func (s *StateDB) RecordProgram(moduleHash common.Hash) {
asm, err := s.TryGetActivatedAsm(moduleHash)
if err != nil {
log.Crit("can't find activated wasm while recording", "modulehash", moduleHash)
}
if s.arbExtraData.userWasms != nil {
s.arbExtraData.userWasms[moduleHash] = ActivatedWasm{
Asm: s.GetActivatedAsm(moduleHash),
Asm: asm,
Module: s.GetActivatedModule(moduleHash),
}
}
Expand Down
2 changes: 1 addition & 1 deletion core/vm/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import (
type StateDB interface {
// Arbitrum: manage Stylus wasms
ActivateWasm(moduleHash common.Hash, asm, module []byte)
GetActivatedAsm(moduleHash common.Hash) (asm []byte)
TryGetActivatedAsm(moduleHash common.Hash) (asm []byte, err error)
GetActivatedModule(moduleHash common.Hash) (module []byte)
RecordCacheWasm(wasm state.CacheWasm)
RecordEvictWasm(wasm state.EvictWasm)
Expand Down
5 changes: 5 additions & 0 deletions ethdb/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,10 @@ type AncientStore interface {
io.Closer
}

type WasmDataBaseRetriever interface {
WasmDataBase() (KeyValueStore, uint32)
}

// Database contains all the methods required by the high level database to not
// only access the key-value data store but also the chain freezer.
type Database interface {
Expand All @@ -189,4 +193,5 @@ type Database interface {
Compacter
Snapshotter
io.Closer
WasmDataBaseRetriever
}
4 changes: 4 additions & 0 deletions ethdb/remotedb/remotedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ func (db *Database) Has(key []byte) (bool, error) {
return true, nil
}

func (t *Database) WasmDataBase() (ethdb.KeyValueStore, uint32) {
return t, 0
}

func (db *Database) Get(key []byte) ([]byte, error) {
var resp hexutil.Bytes
err := db.remote.Call(&resp, "debug_dbGet", hexutil.Bytes(key))
Expand Down
3 changes: 3 additions & 0 deletions internal/ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -968,6 +968,9 @@ func (diff *StateOverride) Apply(state *state.StateDB) error {
return nil
}
for addr, account := range *diff {
if addr == types.ArbosStateAddress {
return fmt.Errorf("overriding address %v not allowed", types.ArbosStateAddress)
}
// Override account nonce.
if account.Nonce != nil {
state.SetNonce(addr, uint64(*account.Nonce))
Expand Down
1 change: 0 additions & 1 deletion node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,6 @@ func (n *Node) OpenDatabaseWithFreezerWithExtraOptions(name string, cache, handl
PebbleExtraOptions: pebbleExtraOptions,
})
}

if err == nil {
db = n.wrapDatabase(db)
}
Expand Down

0 comments on commit 07f6d7a

Please sign in to comment.