Skip to content

Commit

Permalink
Merge pull request ethereum#21 from OffchainLabs/compiled-onchain
Browse files Browse the repository at this point in the history
stateDb userWasm: update fields
  • Loading branch information
rachel-bousfield authored Oct 16, 2023
2 parents b9c8fa5 + e081057 commit 991e082
Show file tree
Hide file tree
Showing 12 changed files with 163 additions and 225 deletions.
9 changes: 5 additions & 4 deletions arbitrum/recordingdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,11 @@ 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.IsCompiledWasmCodeKey(key); ok {
// Arbitrum:
// Just return the compiled wasm without recording it since it's not in consensus
// and the replay will regenerate it
} 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
15 changes: 10 additions & 5 deletions core/rawdb/accessors_state_arbitrum.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,15 @@ import (
"github.com/ethereum/go-ethereum/log"
)

// WriteCompiledWasmCode writes the provided contract compiled wasm code database.
func WriteCompiledWasmCode(db ethdb.KeyValueWriter, version uint16, hash common.Hash, code []byte) {
key := CompiledWasmCodeKey(version, hash)
if err := db.Put(key[:], code); err != nil {
log.Crit("Failed to store compiled wasm contract code", "err", err)
// Stores the activated asm and module for a given codeHash
func WriteActivation(db ethdb.KeyValueWriter, moduleHash common.Hash, asm, module []byte) {
key := ActivatedAsmKey(moduleHash)
if err := db.Put(key[:], asm); err != nil {
log.Crit("Failed to store activated wasm asm", "err", err)
}

key = ActivatedModuleKey(moduleHash)
if err := db.Put(key[:], module); err != nil {
log.Crit("Failed to store activated wasm module", "err", err)
}
}
45 changes: 27 additions & 18 deletions core/rawdb/schema_arbitrum.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,38 +20,47 @@ package rawdb

import (
"bytes"
"encoding/binary"

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

var (
CompiledWasmCodePrefix = []byte{0x00, 'w'} // (prefix, version, code_hash) -> account compiled wasm code
activatedAsmPrefix = []byte{0x00, 'w', 'a'} // (prefix, moduleHash) -> stylus asm
activatedModulePrefix = []byte{0x00, 'w', 'm'} // (prefix, moduleHash) -> stylus module
)

// CompiledWasmCodeKey = CompiledWasmCodePrefix + version + hash
const WasmKeyLen = 2 + 2 + 32
// WasmKeyLen = CompiledWasmCodePrefix + moduleHash
const WasmKeyLen = 3 + 32

type WasmKey = [WasmKeyLen]byte

// CompiledWasmCodeKey = CompiledWasmCodePrefix + version + hash
func CompiledWasmCodeKey(version uint16, hash common.Hash) WasmKey {
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 {
var key WasmKey
copy(key[:2], CompiledWasmCodePrefix)
binary.BigEndian.PutUint16(key[2:4], version)
copy(key[4:], hash[:])
copy(key[:3], prefix)
copy(key[3:], moduleHash[:])
return key
}

// IsCompiledWasmCodeKey reports whether the given byte slice is the key of compiled wasm contract code,
// if so return the raw code hash and version as well.
func IsCompiledWasmCodeKey(key []byte) (bool, common.Hash, uint16) {
start := len(CompiledWasmCodePrefix)
func IsActivatedAsmKey(key []byte) (bool, common.Hash) {
return extractWasmKey(activatedAsmPrefix, key)
}

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

if bytes.HasPrefix(key, CompiledWasmCodePrefix) && len(key) == WasmKeyLen {
version := binary.BigEndian.Uint16(key[start : start+2])
codeHash := common.BytesToHash(key[start+2:])
return true, codeHash, version
func extractWasmKey(prefix, key []byte) (bool, common.Hash) {
if !bytes.HasPrefix(key, prefix) || len(key) != WasmKeyLen {
return false, common.Hash{}
}
return false, common.Hash{}, 0
return true, common.BytesToHash(key[len(prefix):])
}
18 changes: 10 additions & 8 deletions core/state/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import (

const (
// Arbitrum: Cache size granted for caching clean compiled wasm code.
compiledWasmCodeCacheSize = 64 * 1024 * 1024
activatedWasmCacheSize = 64 * 1024 * 1024

// Number of codehash->size associations to keep.
codeSizeCacheSize = 100000
Expand All @@ -42,10 +42,9 @@ const (

// Database wraps access to tries and contract code.
type Database interface {
// Arbitrum: CompiledWasmContractCode retrieves a particular contract's user wasm code.
CompiledWasmContractCode(version uint16, codeHash common.Hash) ([]byte, error)
// Arbitrum: SetCompiledWasmContractCode sets a user wasm code.
SetCompiledWasmContractCode(version uint16, codeHash common.Hash, code []byte) error
// Arbitrum: Read activated Stylus contracts
ActivatedAsm(moduleHash common.Hash) (asm []byte, err error)
ActivatedModule(moduleHash common.Hash) (module []byte, err error)

// OpenTrie opens the main account trie.
OpenTrie(root common.Hash) (Trie, error)
Expand Down Expand Up @@ -147,7 +146,8 @@ func NewDatabase(db ethdb.Database) Database {
func NewDatabaseWithConfig(db ethdb.Database, config *trie.Config) Database {
cdb := &cachingDB{
// Arbitrum only
compiledWasmCache: lru.NewSizeConstrainedCache[rawdb.WasmKey, []byte](compiledWasmCodeCacheSize),
activatedAsmCache: lru.NewSizeConstrainedCache[common.Hash, []byte](activatedWasmCacheSize),
activatedModuleCache: lru.NewSizeConstrainedCache[common.Hash, []byte](activatedWasmCacheSize),

disk: db,
codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize),
Expand All @@ -161,7 +161,8 @@ func NewDatabaseWithConfig(db ethdb.Database, config *trie.Config) Database {
func NewDatabaseWithNodeDB(db ethdb.Database, triedb *trie.Database) Database {
cdb := &cachingDB{
// Arbitrum only
compiledWasmCache: lru.NewSizeConstrainedCache[rawdb.WasmKey, []byte](compiledWasmCodeCacheSize),
activatedAsmCache: lru.NewSizeConstrainedCache[common.Hash, []byte](activatedWasmCacheSize),
activatedModuleCache: lru.NewSizeConstrainedCache[common.Hash, []byte](activatedWasmCacheSize),

disk: db,
codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize),
Expand All @@ -173,7 +174,8 @@ func NewDatabaseWithNodeDB(db ethdb.Database, triedb *trie.Database) Database {

type cachingDB struct {
// Arbitrum
compiledWasmCache *lru.SizeConstrainedCache[rawdb.WasmKey, []byte]
activatedAsmCache *lru.SizeConstrainedCache[common.Hash, []byte]
activatedModuleCache *lru.SizeConstrainedCache[common.Hash, []byte]

disk ethdb.KeyValueStore
codeSizeCache *lru.Cache[common.Hash, int]
Expand Down
35 changes: 21 additions & 14 deletions core/state/database_arbitrum.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,34 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
)

func (db *cachingDB) CompiledWasmContractCode(version uint16, codeHash common.Hash) ([]byte, error) {
wasmKey := rawdb.CompiledWasmCodeKey(version, codeHash)
if code, _ := db.compiledWasmCache.Get(wasmKey); len(code) > 0 {
return code, nil
func (db *cachingDB) ActivatedAsm(moduleHash common.Hash) ([]byte, error) {
if asm, _ := db.activatedAsmCache.Get(moduleHash); len(asm) > 0 {
return asm, nil
}
code, err := db.disk.Get(wasmKey[:])
wasmKey := rawdb.ActivatedAsmKey(moduleHash)
asm, err := db.disk.Get(wasmKey[:])
if err != nil {
return nil, err
}
if len(code) > 0 {
db.compiledWasmCache.Add(wasmKey, code)
return code, nil
if len(asm) > 0 {
db.activatedAsmCache.Add(moduleHash, asm)
return asm, nil
}
return nil, errors.New("not found")
}

func (db *cachingDB) SetCompiledWasmContractCode(version uint16, codeHash common.Hash, code []byte) error {
wasmKey := rawdb.CompiledWasmCodeKey(version, codeHash)
if code, _ := db.compiledWasmCache.Get(wasmKey); len(code) > 0 {
return nil
func (db *cachingDB) ActivatedModule(moduleHash common.Hash) ([]byte, error) {
if module, _ := db.activatedModuleCache.Get(moduleHash); len(module) > 0 {
return module, nil
}
db.compiledWasmCache.Add(wasmKey, code)
return nil
wasmKey := rawdb.ActivatedModuleKey(moduleHash)
module, err := db.disk.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")
}
13 changes: 6 additions & 7 deletions core/state/journal_arbitrum.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@ package state

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

type wasmCodeChange struct {
account *common.Address
version uint16
type wasmActivation struct {
moduleHash common.Hash
}

func (ch wasmCodeChange) revert(s *StateDB) {
s.getStateObject(*ch.account).setWASMCode(nil, ch.version)
func (ch wasmActivation) revert(s *StateDB) {
delete(s.activatedWasms, ch.moduleHash)
}

func (ch wasmCodeChange) dirtied() *common.Address {
return ch.account
func (ch wasmActivation) dirtied() *common.Address {
return nil
}
9 changes: 0 additions & 9 deletions core/state/state_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,6 @@ func (s Storage) Copy() Storage {
// Account values can be accessed and modified through the object.
// Finally, call commitTrie to write the modified storage trie into a database.
type stateObject struct {
// Arbitrum: write caches and cache flags
compiledWasmCode CompiledWasms // compiled wasm bytecode which gets set when wasm is loaded

address common.Address
addrHash common.Hash // hash of ethereum address of the account
data types.StateAccount
Expand Down Expand Up @@ -110,9 +107,6 @@ func newObject(db *StateDB, address common.Address, data types.StateAccount) *st
originStorage: make(Storage),
pendingStorage: make(Storage),
dirtyStorage: make(Storage),

// Arbitrum Only
compiledWasmCode: make(CompiledWasms),
}
}

Expand Down Expand Up @@ -435,9 +429,6 @@ func (s *stateObject) deepCopy(db *StateDB) *stateObject {
stateObject.dirtyCode = s.dirtyCode
stateObject.deleted = s.deleted

// Arbitrum Only
stateObject.compiledWasmCode = s.compiledWasmCode.Copy()

return stateObject
}

Expand Down
76 changes: 0 additions & 76 deletions core/state/state_object_arbitrum.go

This file was deleted.

Loading

0 comments on commit 991e082

Please sign in to comment.