Skip to content

Commit

Permalink
merge master and resolve conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
ganeshvanahalli committed Nov 7, 2024
2 parents 2a2149b + ed53c04 commit 27cb298
Show file tree
Hide file tree
Showing 72 changed files with 9,014 additions and 368 deletions.
4 changes: 2 additions & 2 deletions arbitrum/apibackend.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ func createRegisterAPIBackend(backend *Backend, filterConfig filters.Config, fal
// 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)
if tag != 0 || len(backend.chainDb.WasmTargets()) > 1 {
dbForAPICalls = rawdb.WrapDatabaseWithWasm(backend.chainDb, wasmStore, 0, []ethdb.WasmTarget{rawdb.LocalTarget()})
}
backend.apiBackend = &APIBackend{
b: backend,
Expand Down
19 changes: 4 additions & 15 deletions arbitrum/recordingdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/triedb"
"github.com/ethereum/go-ethereum/triedb/hashdb"
flag "github.com/spf13/pflag"
)

var (
Expand Down Expand Up @@ -159,18 +158,8 @@ func (r *RecordingChainContext) GetMinBlockNumberAccessed() uint64 {
}

type RecordingDatabaseConfig struct {
TrieDirtyCache int `koanf:"trie-dirty-cache"`
TrieCleanCache int `koanf:"trie-clean-cache"`
}

var DefaultRecordingDatabaseConfig = RecordingDatabaseConfig{
TrieDirtyCache: 1024,
TrieCleanCache: 16,
}

func RecordingDatabaseConfigAddOptions(prefix string, f *flag.FlagSet) {
f.Int(prefix+".trie-dirty-cache", DefaultRecordingDatabaseConfig.TrieDirtyCache, "like trie-dirty-cache for the separate, recording database (used for validation)")
f.Int(prefix+".trie-clean-cache", DefaultRecordingDatabaseConfig.TrieCleanCache, "like trie-clean-cache for the separate, recording database (used for validation)")
TrieDirtyCache int
TrieCleanCache int
}

type RecordingDatabase struct {
Expand Down Expand Up @@ -269,7 +258,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.WrapDatabaseWithWasm(rawdb.NewDatabase(recordingKeyValue), r.db.WasmStore(), 0))
recordingStateDatabase := state.NewDatabase(rawdb.WrapDatabaseWithWasm(rawdb.NewDatabase(recordingKeyValue), r.db.WasmStore(), 0, r.db.WasmTargets()))
var prevRoot common.Hash
if lastBlockHeader != nil {
prevRoot = lastBlockHeader.Root
Expand Down Expand Up @@ -333,7 +322,7 @@ func (r *RecordingDatabase) GetOrRecreateState(ctx context.Context, header *type
returnedBlockNumber := header.Number.Uint64()
for ctx.Err() == nil {
var block *types.Block
state, block, err = AdvanceStateByBlock(ctx, r.bc, state, header, blockToRecreate, prevHash, logFunc)
state, block, err = AdvanceStateByBlock(ctx, r.bc, state, blockToRecreate, prevHash, logFunc)
if err != nil {
return nil, err
}
Expand Down
29 changes: 4 additions & 25 deletions arbitrum/recreatestate.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type StateReleaseFunc tracers.StateReleaseFunc

var NoopStateRelease StateReleaseFunc = func() {}

type StateBuildingLogFunction func(targetHeader, header *types.Header, hasState bool)
type StateBuildingLogFunction func(header *types.Header, hasState bool)
type StateForHeaderFunction func(header *types.Header) (*state.StateDB, StateReleaseFunc, error)

// finds last available state and header checking it first for targetHeader then looking backwards
Expand Down Expand Up @@ -56,7 +56,7 @@ func FindLastAvailableState(ctx context.Context, bc *core.BlockChain, stateFor S
return nil, lastHeader, nil, err
}
if logFunc != nil {
logFunc(targetHeader, currentHeader, false)
logFunc(currentHeader, false)
}
if currentHeader.Number.Uint64() <= genesis {
return nil, lastHeader, nil, errors.Wrap(err, fmt.Sprintf("moved beyond genesis looking for state %d, genesis %d", targetHeader.Number.Uint64(), genesis))
Expand All @@ -69,7 +69,7 @@ func FindLastAvailableState(ctx context.Context, bc *core.BlockChain, stateFor S
return state, currentHeader, release, ctx.Err()
}

func AdvanceStateByBlock(ctx context.Context, bc *core.BlockChain, state *state.StateDB, targetHeader *types.Header, blockToRecreate uint64, prevBlockHash common.Hash, logFunc StateBuildingLogFunction) (*state.StateDB, *types.Block, error) {
func AdvanceStateByBlock(ctx context.Context, bc *core.BlockChain, state *state.StateDB, blockToRecreate uint64, prevBlockHash common.Hash, logFunc StateBuildingLogFunction) (*state.StateDB, *types.Block, error) {
block := bc.GetBlockByNumber(blockToRecreate)
if block == nil {
return nil, nil, fmt.Errorf("block not found while recreating: %d", blockToRecreate)
Expand All @@ -78,32 +78,11 @@ func AdvanceStateByBlock(ctx context.Context, bc *core.BlockChain, state *state.
return nil, nil, fmt.Errorf("reorg detected: number %d expectedPrev: %v foundPrev: %v", blockToRecreate, prevBlockHash, block.ParentHash())
}
if logFunc != nil {
logFunc(targetHeader, block.Header(), true)
logFunc(block.Header(), true)
}
_, _, _, err := bc.Processor().Process(block, state, vm.Config{})
if err != nil {
return nil, nil, fmt.Errorf("failed recreating state for block %d : %w", blockToRecreate, err)
}
return state, block, nil
}

func AdvanceStateUpToBlock(ctx context.Context, bc *core.BlockChain, state *state.StateDB, targetHeader *types.Header, lastAvailableHeader *types.Header, logFunc StateBuildingLogFunction) (*state.StateDB, error) {
returnedBlockNumber := targetHeader.Number.Uint64()
blockToRecreate := lastAvailableHeader.Number.Uint64() + 1
prevHash := lastAvailableHeader.Hash()
for ctx.Err() == nil {
state, block, err := AdvanceStateByBlock(ctx, bc, state, targetHeader, blockToRecreate, prevHash, logFunc)
if err != nil {
return nil, err
}
prevHash = block.Hash()
if blockToRecreate >= returnedBlockNumber {
if block.Hash() != targetHeader.Hash() {
return nil, fmt.Errorf("blockHash doesn't match when recreating number: %d expected: %v got: %v", blockToRecreate, targetHeader.Hash(), block.Hash())
}
return state, nil
}
blockToRecreate++
}
return nil, ctx.Err()
}
2 changes: 0 additions & 2 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,8 +359,6 @@ func geth(ctx *cli.Context) error {
// it unlocks any requested accounts, and starts the RPC/IPC interfaces and the
// miner.
func startNode(ctx *cli.Context, stack *node.Node, isConsole bool) {
debug.Memsize.Add("node", stack)

// Start up the node itself
utils.StartNode(ctx, stack, isConsole)

Expand Down
4 changes: 2 additions & 2 deletions core/arbitrum_hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ var InterceptRPCMessage = func(
// Gets ArbOS's maximum intended gas per second
var GetArbOSSpeedLimitPerSecond func(statedb *state.StateDB) (uint64, error)

// Allows ArbOS to update the gas cap so that it ignores the message's specific L1 poster costs.
var InterceptRPCGasCap = func(gascap *uint64, msg *Message, header *types.Header, statedb *state.StateDB) {}
// While processing RPC only - Ask ArbOS what are the poster costs for this message.
var RPCPostingGasHook = func(msg *Message, header *types.Header, statedb *state.StateDB) (uint64, error) { return 0, nil }

// Renders a solidity error in human-readable form
var RenderRPCError func(data []byte) error
Expand Down
56 changes: 16 additions & 40 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@ type CacheConfig struct {
}

// arbitrum: exposing CacheConfig.triedbConfig to be used by Nitro when initializing arbos in database
func (c *CacheConfig) TriedbConfig(isVerkle bool) *triedb.Config {
return c.triedbConfig(isVerkle)
func (c *CacheConfig) TriedbConfig() *triedb.Config {
return c.triedbConfig(false)
}

// triedbConfig derives the configures for trie database.
Expand Down Expand Up @@ -773,14 +773,14 @@ func (bc *BlockChain) rewindHashHead(head *types.Header, root common.Hash, rewin
}

// rewindPathHead implements the logic of rewindHead in the context of path scheme.
func (bc *BlockChain) rewindPathHead(head *types.Header, root common.Hash, rewindLimit uint64) (*types.Header, uint64, bool) {
func (bc *BlockChain) rewindPathHead(head *types.Header, root common.Hash) (*types.Header, uint64) {
var (
pivot = rawdb.ReadLastPivotNumber(bc.db) // Associated block number of pivot block
rootNumber uint64 // Associated block number of requested root

// RootFound represents whether the requested root is already
// BeyondRoot represents whether the requested root is already
// crossed. The flag value is set to true if the root is empty.
rootFound = root == common.Hash{}
beyondRoot = root == common.Hash{}

// noState represents if the target state requested for search
// is unavailable and impossible to be recovered.
Expand All @@ -789,10 +789,6 @@ func (bc *BlockChain) rewindPathHead(head *types.Header, root common.Hash, rewin
start = time.Now() // Timestamp the rewinding is restarted
logged = time.Now() // Timestamp last progress log was printed
)

lastFullBlock := uint64(0)
lastFullBlockHash := common.Hash{}
gasRolledBack := uint64(0)
// Rewind the head block tag until an available state is found.
for {
logger := log.Trace
Expand All @@ -802,64 +798,43 @@ func (bc *BlockChain) rewindPathHead(head *types.Header, root common.Hash, rewin
}
logger("Block state missing, rewinding further", "number", head.Number, "hash", head.Hash(), "elapsed", common.PrettyDuration(time.Since(start)))

if rewindLimit > 0 && lastFullBlock != 0 {
// Arbitrum: track the amount of gas rolled back and stop the rollback early if necessary
gasUsedInBlock := head.GasUsed
if bc.chainConfig.IsArbitrum() {
receipts := bc.GetReceiptsByHash(head.Hash())
for _, receipt := range receipts {
gasUsedInBlock -= receipt.GasUsedForL1
}
}
gasRolledBack += gasUsedInBlock
if gasRolledBack >= rewindLimit {
rootNumber = lastFullBlock
head = bc.GetHeader(lastFullBlockHash, lastFullBlock)
log.Debug("Rewound to block with state but not snapshot", "number", head.Number.Uint64(), "hash", head.Hash())
break
}
}
// If a root threshold was requested but not yet crossed, check
if !rootFound && head.Root == root {
rootFound, rootNumber = true, head.Number.Uint64()
if !beyondRoot && head.Root == root {
beyondRoot, rootNumber = true, head.Number.Uint64()
}
// If the root threshold hasn't been crossed but the available
// state is reached, quickly determine if the target state is
// possible to be reached or not.
if !rootFound && noState && bc.HasState(head.Root) {
rootFound = true
if !beyondRoot && noState && bc.HasState(head.Root) {
beyondRoot = true
log.Info("Disable the search for unattainable state", "root", root)
}
// Check if the associated state is available or recoverable if
// the requested root has already been crossed.
if rootFound && (bc.HasState(head.Root) || bc.stateRecoverable(head.Root)) {
if beyondRoot && (bc.HasState(head.Root) || bc.stateRecoverable(head.Root)) {
break
}
if (bc.HasState(head.Root) || bc.stateRecoverable(head.Root)) && lastFullBlock == 0 {
lastFullBlock = head.Number.Uint64()
lastFullBlockHash = head.Hash()
}
// If pivot block is reached, return the genesis block as the
// new chain head. Theoretically there must be a persistent
// state before or at the pivot block, prevent endless rewinding
// towards the genesis just in case.
if pivot != nil && *pivot >= head.Number.Uint64() {
log.Info("Pivot block reached, resetting to genesis", "number", head.Number, "hash", head.Hash())
return bc.genesisBlock.Header(), rootNumber, rootFound
return bc.genesisBlock.Header(), rootNumber
}
// If the chain is gapped in the middle, return the genesis
// block as the new chain head
parent := bc.GetHeader(head.ParentHash, head.Number.Uint64()-1) // Keep rewinding
if parent == nil {
log.Error("Missing block in the middle, resetting to genesis", "number", head.Number.Uint64()-1, "hash", head.ParentHash)
return bc.genesisBlock.Header(), rootNumber, rootFound
return bc.genesisBlock.Header(), rootNumber
}
head = parent

// If the genesis block is reached, stop searching.
if head.Number.Uint64() == 0 {
log.Info("Genesis block reached", "number", head.Number, "hash", head.Hash())
return head, rootNumber, rootFound
return head, rootNumber
}
}
// Recover if the target state if it's not available yet.
Expand All @@ -869,7 +844,7 @@ func (bc *BlockChain) rewindPathHead(head *types.Header, root common.Hash, rewin
}
}
log.Info("Rewound to block with state", "number", head.Number, "hash", head.Hash())
return head, rootNumber, rootFound
return head, rootNumber
}

// rewindHead searches the available states in the database and returns the associated
Expand All @@ -882,7 +857,8 @@ func (bc *BlockChain) rewindPathHead(head *types.Header, root common.Hash, rewin
// and the whole snapshot should be auto-generated in case of head mismatch.
func (bc *BlockChain) rewindHead(head *types.Header, root common.Hash, rewindLimit uint64) (*types.Header, uint64, bool) {
if bc.triedb.Scheme() == rawdb.PathScheme {
return bc.rewindPathHead(head, root, rewindLimit)
newHead, rootNumber := bc.rewindPathHead(head, root)
return newHead, rootNumber, head.Number.Uint64() != 0
}
return bc.rewindHashHead(head, root, rewindLimit)
}
Expand Down
10 changes: 4 additions & 6 deletions core/rawdb/accessors_snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,8 @@ func DeleteSnapshotRoot(db ethdb.KeyValueWriter) {
}

// ReadAccountSnapshot retrieves the snapshot entry of an account trie leaf.
func ReadAccountSnapshot(db ethdb.KeyValueReader, hash common.Hash) []byte {
data, _ := db.Get(accountSnapshotKey(hash))
return data
func ReadAccountSnapshot(db ethdb.KeyValueReader, hash common.Hash) ([]byte, error) {
return ignoreNotFound(db.Get(accountSnapshotKey(hash)))
}

// WriteAccountSnapshot stores the snapshot entry of an account trie leaf.
Expand All @@ -93,9 +92,8 @@ func DeleteAccountSnapshot(db ethdb.KeyValueWriter, hash common.Hash) {
}

// ReadStorageSnapshot retrieves the snapshot entry of a storage trie leaf.
func ReadStorageSnapshot(db ethdb.KeyValueReader, accountHash, storageHash common.Hash) []byte {
data, _ := db.Get(storageSnapshotKey(accountHash, storageHash))
return data
func ReadStorageSnapshot(db ethdb.KeyValueReader, accountHash, storageHash common.Hash) ([]byte, error) {
return ignoreNotFound(db.Get(storageSnapshotKey(accountHash, storageHash)))
}

// WriteStorageSnapshot stores the snapshot entry of a storage trie leaf.
Expand Down
34 changes: 15 additions & 19 deletions core/rawdb/accessors_state_arbitrum.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,14 @@ import (
"github.com/ethereum/go-ethereum/log"
)

type Target string

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

func LocalTarget() Target {
func LocalTarget() ethdb.WasmTarget {
if runtime.GOOS == "linux" {
switch runtime.GOARCH {
case "arm64":
Expand All @@ -46,9 +44,9 @@ func LocalTarget() Target {
return TargetHost
}

func (t Target) keyPrefix() (WasmPrefix, error) {
func activatedAsmKeyPrefix(target ethdb.WasmTarget) (WasmPrefix, error) {
var prefix WasmPrefix
switch t {
switch target {
case TargetWavm:
prefix = activatedAsmWavmPrefix
case TargetArm64:
Expand All @@ -58,27 +56,25 @@ func (t Target) keyPrefix() (WasmPrefix, error) {
case TargetHost:
prefix = activatedAsmHostPrefix
default:
return WasmPrefix{}, fmt.Errorf("invalid target: %v", t)
return WasmPrefix{}, fmt.Errorf("invalid target: %v", target)
}
return prefix, nil
}

func (t Target) IsValid() bool {
_, err := t.keyPrefix()
func IsSupportedWasmTarget(target ethdb.WasmTarget) bool {
_, err := activatedAsmKeyPrefix(target)
return err == nil
}

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

func WriteActivation(db ethdb.KeyValueWriter, moduleHash common.Hash, asmMap map[Target][]byte) {
func WriteActivation(db ethdb.KeyValueWriter, moduleHash common.Hash, asmMap map[ethdb.WasmTarget][]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()
func WriteActivatedAsm(db ethdb.KeyValueWriter, target ethdb.WasmTarget, moduleHash common.Hash, asm []byte) {
prefix, err := activatedAsmKeyPrefix(target)
if err != nil {
log.Crit("Failed to store activated wasm asm", "err", err)
}
Expand All @@ -89,8 +85,8 @@ func WriteActivatedAsm(db ethdb.KeyValueWriter, target Target, moduleHash common
}

// 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()
func ReadActivatedAsm(db ethdb.KeyValueReader, target ethdb.WasmTarget, moduleHash common.Hash) []byte {
prefix, err := activatedAsmKeyPrefix(target)
if err != nil {
log.Crit("Failed to read activated wasm asm", "err", err)
}
Expand Down
Loading

0 comments on commit 27cb298

Please sign in to comment.