Skip to content

Commit

Permalink
l2geth: Add OVM ETH and message passer state dump (ethereum-optimism#…
Browse files Browse the repository at this point in the history
…3742)

This is necessary in order to perform the mainnet OVM ETH and withdrawal hashes migration. Operates using a L2GETH_STATE_DUMP_PATH environment variable that specifies the file that addresses should be dump to. They are not deduplicated. The format of the file is:

```
ETH|<ovm eth address>
MSG|<sender>|<msg>
```
  • Loading branch information
mslipper authored Oct 20, 2022
1 parent fa0915f commit 9e58c9e
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 2 deletions.
10 changes: 8 additions & 2 deletions l2geth/core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import (
"sort"
"time"

"github.com/ethereum-optimism/optimism/l2geth/statedumper"

"github.com/ethereum-optimism/optimism/l2geth/common"
"github.com/ethereum-optimism/optimism/l2geth/core/types"
"github.com/ethereum-optimism/optimism/l2geth/crypto"
Expand Down Expand Up @@ -244,6 +246,7 @@ func (s *StateDB) GetBalance(addr common.Address) *big.Int {
if rcfg.UsingOVM {
// Get balance from the OVM_ETH contract.
// NOTE: We may remove this feature in a future release.
statedumper.WriteETH(addr)
key := GetOVMBalanceKey(addr)
bal := s.GetState(dump.OvmEthAddress, key)
return bal.Big()
Expand Down Expand Up @@ -377,6 +380,7 @@ func (s *StateDB) AddBalance(addr common.Address, amount *big.Int) {
// Note that we don't need to check for overflows or underflows here because the code that
// uses this codepath already checks for them. You can follow the original codepath below
// (stateObject.AddBalance) to confirm that there are no checks being performed here.
statedumper.WriteETH(addr)
key := GetOVMBalanceKey(addr)
value := s.GetState(dump.OvmEthAddress, key)
bal := value.Big()
Expand All @@ -397,6 +401,7 @@ func (s *StateDB) SubBalance(addr common.Address, amount *big.Int) {
// Note that we don't need to check for overflows or underflows here because the code that
// uses this codepath already checks for them. You can follow the original codepath below
// (stateObject.SubBalance) to confirm that there are no checks being performed here.
statedumper.WriteETH(addr)
key := GetOVMBalanceKey(addr)
value := s.GetState(dump.OvmEthAddress, key)
bal := value.Big()
Expand All @@ -413,6 +418,7 @@ func (s *StateDB) SubBalance(addr common.Address, amount *big.Int) {
func (s *StateDB) SetBalance(addr common.Address, amount *big.Int) {
if rcfg.UsingOVM {
// Mutate the storage slot inside of OVM_ETH to change balances.
statedumper.WriteETH(addr)
key := GetOVMBalanceKey(addr)
s.SetState(dump.OvmEthAddress, key, common.BigToHash(amount))
} else {
Expand Down Expand Up @@ -580,8 +586,8 @@ func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject)
// CreateAccount is called during the EVM CREATE operation. The situation might arise that
// a contract does the following:
//
// 1. sends funds to sha(account ++ (nonce + 1))
// 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1)
// 1. sends funds to sha(account ++ (nonce + 1))
// 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1)
//
// Carrying over the balance ensures that Ether doesn't disappear.
func (s *StateDB) CreateAccount(addr common.Address) {
Expand Down
5 changes: 5 additions & 0 deletions l2geth/core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package vm

import (
"fmt"
"github.com/ethereum-optimism/optimism/l2geth/statedumper"
"math/big"
"sync/atomic"
"time"
Expand Down Expand Up @@ -198,6 +199,10 @@ func (evm *EVM) Interpreter() Interpreter {
// the necessary steps to create accounts and reverses the state in case of an
// execution error or failed value transfer.
func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
if addr == dump.MessagePasserAddress {
statedumper.WriteMessage(caller.Address(), input)
}

if evm.vmConfig.NoRecursion && evm.depth > 0 {
return nil, gas, nil
}
Expand Down
1 change: 1 addition & 0 deletions l2geth/rollup/dump/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ import (
var OvmEthAddress = common.HexToAddress("0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000")
var OvmFeeWallet = common.HexToAddress("0x4200000000000000000000000000000000000011")
var OvmWhitelistAddress = common.HexToAddress("0x4200000000000000000000000000000000000002")
var MessagePasserAddress = common.HexToAddress("0x4200000000000000000000000000000000000000")
74 changes: 74 additions & 0 deletions l2geth/statedumper/dumper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package statedumper

import (
"fmt"
"github.com/ethereum-optimism/optimism/l2geth/common"
"io"
"os"
"sync"
)

type StateDumper interface {
WriteETH(address common.Address)
WriteMessage(sender common.Address, msg []byte)
}

var DefaultStateDumper StateDumper

func NewStateDumper() StateDumper {
path := os.Getenv("L2GETH_STATE_DUMP_PATH")
if path == "" {
return &noopStateDumper{}
}

f, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE, 0o755)
if err != nil {
panic(err)
}

return &FileStateDumper{
f: f,
}
}

type FileStateDumper struct {
f io.Writer
mtx sync.Mutex
}

func (s *FileStateDumper) WriteETH(address common.Address) {
s.mtx.Lock()
defer s.mtx.Unlock()
if _, err := s.f.Write([]byte(fmt.Sprintf("ETH|%s\n", address.Hex()))); err != nil {
panic(err)
}
}

func (s *FileStateDumper) WriteMessage(sender common.Address, msg []byte) {
s.mtx.Lock()
defer s.mtx.Unlock()
if _, err := s.f.Write([]byte(fmt.Sprintf("MSG|%s|%x\n", sender.Hex(), msg))); err != nil {
panic(err)
}
}

type noopStateDumper struct {
}

func (n *noopStateDumper) WriteETH(address common.Address) {
}

func (n *noopStateDumper) WriteMessage(sender common.Address, msg []byte) {
}

func init() {
DefaultStateDumper = NewStateDumper()
}

func WriteETH(address common.Address) {
DefaultStateDumper.WriteETH(address)
}

func WriteMessage(sender common.Address, msg []byte) {
DefaultStateDumper.WriteMessage(sender, msg)
}

0 comments on commit 9e58c9e

Please sign in to comment.