Commit 234d6863 authored by mergify[bot]'s avatar mergify[bot] Committed by GitHub

Merge branch 'develop' into clabby/update-forge-and-forge-std

parents de7ba3ca e9045720
...@@ -9,7 +9,7 @@ require ( ...@@ -9,7 +9,7 @@ require (
github.com/docker/docker v20.10.21+incompatible github.com/docker/docker v20.10.21+incompatible
github.com/docker/go-connections v0.4.0 github.com/docker/go-connections v0.4.0
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3
github.com/ethereum/go-ethereum v1.10.26 github.com/ethereum/go-ethereum v1.11.2
github.com/fsnotify/fsnotify v1.6.0 github.com/fsnotify/fsnotify v1.6.0
github.com/golang/snappy v0.0.4 github.com/golang/snappy v0.0.4
github.com/google/go-cmp v0.5.9 github.com/google/go-cmp v0.5.9
...@@ -31,11 +31,12 @@ require ( ...@@ -31,11 +31,12 @@ require (
github.com/stretchr/testify v1.8.1 github.com/stretchr/testify v1.8.1
github.com/urfave/cli v1.22.9 github.com/urfave/cli v1.22.9
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa
golang.org/x/crypto v0.4.0 golang.org/x/crypto v0.6.0
golang.org/x/term v0.5.0 golang.org/x/term v0.5.0
) )
require ( require (
github.com/DataDog/zstd v1.5.2 // indirect
github.com/Microsoft/go-winio v0.6.0 // indirect github.com/Microsoft/go-winio v0.6.0 // indirect
github.com/VictoriaMetrics/fastcache v1.10.0 // indirect github.com/VictoriaMetrics/fastcache v1.10.0 // indirect
github.com/allegro/bigcache v1.2.1 // indirect github.com/allegro/bigcache v1.2.1 // indirect
...@@ -45,12 +46,16 @@ require ( ...@@ -45,12 +46,16 @@ require (
github.com/btcsuite/btcd/btcutil v1.1.0 // indirect github.com/btcsuite/btcd/btcutil v1.1.0 // indirect
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/containerd/cgroups v1.0.4 // indirect github.com/cockroachdb/errors v1.9.1 // indirect
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 // indirect
github.com/cockroachdb/redact v1.1.3 // indirect
github.com/containerd/cgroups v1.1.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
github.com/deckarep/golang-set v1.8.0 // indirect github.com/deckarep/golang-set/v2 v2.1.0 // indirect
github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect
github.com/deepmap/oapi-codegen v1.8.2 // indirect github.com/deepmap/oapi-codegen v1.8.2 // indirect
github.com/docker/distribution v2.8.1+incompatible // indirect github.com/docker/distribution v2.8.1+incompatible // indirect
...@@ -62,6 +67,7 @@ require ( ...@@ -62,6 +67,7 @@ require (
github.com/flynn/noise v1.0.0 // indirect github.com/flynn/noise v1.0.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect github.com/francoispqt/gojay v1.2.13 // indirect
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect
github.com/getsentry/sentry-go v0.18.0 // indirect
github.com/go-kit/kit v0.10.0 // indirect github.com/go-kit/kit v0.10.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-stack/stack v1.8.1 // indirect github.com/go-stack/stack v1.8.1 // indirect
...@@ -72,7 +78,7 @@ require ( ...@@ -72,7 +78,7 @@ require (
github.com/golang/mock v1.6.0 // indirect github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect github.com/golang/protobuf v1.5.2 // indirect
github.com/google/gopacket v1.1.19 // indirect github.com/google/gopacket v1.1.19 // indirect
github.com/google/pprof v0.0.0-20221203041831-ce31453925ec // indirect github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect
github.com/google/uuid v1.3.0 // indirect github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect
github.com/graph-gophers/graphql-go v1.3.0 // indirect github.com/graph-gophers/graphql-go v1.3.0 // indirect
...@@ -81,7 +87,7 @@ require ( ...@@ -81,7 +87,7 @@ require (
github.com/hashicorp/golang-lru/v2 v2.0.1 // indirect github.com/hashicorp/golang-lru/v2 v2.0.1 // indirect
github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
github.com/huin/goupnp v1.0.3 // indirect github.com/huin/goupnp v1.1.0 // indirect
github.com/influxdata/influxdb v1.8.3 // indirect github.com/influxdata/influxdb v1.8.3 // indirect
github.com/influxdata/influxdb-client-go/v2 v2.4.0 // indirect github.com/influxdata/influxdb-client-go/v2 v2.4.0 // indirect
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect
...@@ -95,6 +101,7 @@ require ( ...@@ -95,6 +101,7 @@ require (
github.com/klauspost/cpuid/v2 v2.2.3 // indirect github.com/klauspost/cpuid/v2 v2.2.3 // indirect
github.com/koron/go-ssdp v0.0.3 // indirect github.com/koron/go-ssdp v0.0.3 // indirect
github.com/kr/pretty v0.3.1 // indirect github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect
github.com/libp2p/go-cidranger v1.1.0 // indirect github.com/libp2p/go-cidranger v1.1.0 // indirect
github.com/libp2p/go-flow-metrics v0.1.0 // indirect github.com/libp2p/go-flow-metrics v0.1.0 // indirect
...@@ -106,7 +113,7 @@ require ( ...@@ -106,7 +113,7 @@ require (
github.com/libp2p/go-reuseport v0.2.0 // indirect github.com/libp2p/go-reuseport v0.2.0 // indirect
github.com/libp2p/go-yamux/v4 v4.0.0 // indirect github.com/libp2p/go-yamux/v4 v4.0.0 // indirect
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/miekg/dns v1.1.50 // indirect github.com/miekg/dns v1.1.50 // indirect
...@@ -148,13 +155,13 @@ require ( ...@@ -148,13 +155,13 @@ require (
github.com/quic-go/webtransport-go v0.5.1 // indirect github.com/quic-go/webtransport-go v0.5.1 // indirect
github.com/raulk/go-watchdog v1.3.0 // indirect github.com/raulk/go-watchdog v1.3.0 // indirect
github.com/rivo/uniseg v0.4.3 // indirect github.com/rivo/uniseg v0.4.3 // indirect
github.com/rjeczalik/notify v0.9.2 // indirect github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/rs/cors v1.8.2 // indirect github.com/rs/cors v1.8.2 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/sirupsen/logrus v1.9.0 // indirect github.com/sirupsen/logrus v1.9.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d // indirect github.com/status-im/keycard-go v0.2.0 // indirect
github.com/stretchr/objx v0.5.0 // indirect github.com/stretchr/objx v0.5.0 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect
github.com/tklauser/go-sysconf v0.3.10 // indirect github.com/tklauser/go-sysconf v0.3.10 // indirect
...@@ -184,4 +191,6 @@ require ( ...@@ -184,4 +191,6 @@ require (
nhooyr.io/websocket v1.8.7 // indirect nhooyr.io/websocket v1.8.7 // indirect
) )
replace github.com/ethereum/go-ethereum v1.10.26 => github.com/ethereum-optimism/op-geth v0.0.0-20230214215134-401b7fd3309b replace github.com/ethereum/go-ethereum v1.11.2 => github.com/ethereum-optimism/op-geth v0.0.0-20230222154945-12d211246519
//replace github.com/ethereum/go-ethereum v1.11.2 => ../go-ethereum
This diff is collapsed.
...@@ -120,7 +120,7 @@ func (t *TransactionManager) CraftTx(ctx context.Context, data []byte) (*types.T ...@@ -120,7 +120,7 @@ func (t *TransactionManager) CraftTx(ctx context.Context, data []byte) (*types.T
} }
t.log.Info("creating tx", "to", rawTx.To, "from", t.senderAddress) t.log.Info("creating tx", "to", rawTx.To, "from", t.senderAddress)
gas, err := core.IntrinsicGas(rawTx.Data, nil, false, true, true) gas, err := core.IntrinsicGas(rawTx.Data, nil, false, true, true, false)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to calculate intrinsic gas: %w", err) return nil, fmt.Errorf("failed to calculate intrinsic gas: %w", err)
} }
......
...@@ -284,11 +284,11 @@ func main() { ...@@ -284,11 +284,11 @@ func main() {
if !isFinalized { if !isFinalized {
// Get the ETH balance of the withdrawal target *before* the finalization // Get the ETH balance of the withdrawal target *before* the finalization
targetBalBefore, err := clients.L1Client.BalanceAt(context.Background(), *wd.Target, nil) targetBalBefore, err := clients.L1Client.BalanceAt(context.Background(), wd.XDomainTarget, nil)
if err != nil { if err != nil {
return err return err
} }
log.Debug("Balance before finalization", "balance", targetBalBefore, "account", *wd.Target) log.Debug("Balance before finalization", "balance", targetBalBefore, "account", wd.XDomainTarget)
log.Info("Finalizing withdrawal") log.Info("Finalizing withdrawal")
receipt, err := finalizeWithdrawalTransaction(contracts, clients, opts, wd, withdrawal) receipt, err := finalizeWithdrawalTransaction(contracts, clients, opts, wd, withdrawal)
...@@ -369,14 +369,14 @@ func main() { ...@@ -369,14 +369,14 @@ func main() {
if method != nil { if method != nil {
log.Info("withdrawal action", "function", method.Name, "value", wdValue) log.Info("withdrawal action", "function", method.Name, "value", wdValue)
} else { } else {
log.Info("unknown method", "to", wd.Target, "data", hexutil.Encode(wd.Data)) log.Info("unknown method", "to", wd.XDomainTarget, "data", hexutil.Encode(wd.XDomainData))
if err := writeSuspicious(f, withdrawal, wd, finalizationTrace, i, "unknown method"); err != nil { if err := writeSuspicious(f, withdrawal, wd, finalizationTrace, i, "unknown method"); err != nil {
return err return err
} }
} }
// check that the user's intents are actually executed // check that the user's intents are actually executed
if common.HexToAddress(callFrame.To) != *wd.Target { if common.HexToAddress(callFrame.To) != wd.XDomainTarget {
log.Info("target mismatch", "index", i) log.Info("target mismatch", "index", i)
if err := writeSuspicious(f, withdrawal, wd, finalizationTrace, i, "target mismatch"); err != nil { if err := writeSuspicious(f, withdrawal, wd, finalizationTrace, i, "target mismatch"); err != nil {
...@@ -384,7 +384,7 @@ func main() { ...@@ -384,7 +384,7 @@ func main() {
} }
continue continue
} }
if !bytes.Equal(hexutil.MustDecode(callFrame.Input), wd.Data) { if !bytes.Equal(hexutil.MustDecode(callFrame.Input), wd.XDomainData) {
log.Info("calldata mismatch", "index", i) log.Info("calldata mismatch", "index", i)
if err := writeSuspicious(f, withdrawal, wd, finalizationTrace, i, "calldata mismatch"); err != nil { if err := writeSuspicious(f, withdrawal, wd, finalizationTrace, i, "calldata mismatch"); err != nil {
...@@ -401,7 +401,7 @@ func main() { ...@@ -401,7 +401,7 @@ func main() {
} }
// Get the ETH balance of the withdrawal target *after* the finalization // Get the ETH balance of the withdrawal target *after* the finalization
targetBalAfter, err := clients.L1Client.BalanceAt(context.Background(), *wd.Target, nil) targetBalAfter, err := clients.L1Client.BalanceAt(context.Background(), wd.XDomainTarget, nil)
if err != nil { if err != nil {
return err return err
} }
...@@ -621,7 +621,7 @@ func finalizeWithdrawalTransaction( ...@@ -621,7 +621,7 @@ func finalizeWithdrawalTransaction(
wd *crossdomain.LegacyWithdrawal, wd *crossdomain.LegacyWithdrawal,
withdrawal *crossdomain.Withdrawal, withdrawal *crossdomain.Withdrawal,
) (*types.Receipt, error) { ) (*types.Receipt, error) {
if wd.Target == nil { if wd.XDomainTarget == (common.Address{}) {
return nil, errors.New("withdrawal target is nil, should never happen") return nil, errors.New("withdrawal target is nil, should never happen")
} }
...@@ -833,7 +833,7 @@ func newTransactor(ctx *cli.Context) (*bind.TransactOpts, error) { ...@@ -833,7 +833,7 @@ func newTransactor(ctx *cli.Context) (*bind.TransactOpts, error) {
// represents the user's intent. // represents the user's intent.
func findWithdrawalCall(trace *callFrame, wd *crossdomain.LegacyWithdrawal, l1xdm common.Address) *callFrame { func findWithdrawalCall(trace *callFrame, wd *crossdomain.LegacyWithdrawal, l1xdm common.Address) *callFrame {
isCall := trace.Type == "CALL" isCall := trace.Type == "CALL"
isTarget := common.HexToAddress(trace.To) == *wd.Target isTarget := common.HexToAddress(trace.To) == wd.XDomainTarget
isFrom := common.HexToAddress(trace.From) == l1xdm isFrom := common.HexToAddress(trace.From) == l1xdm
if isCall && isTarget && isFrom { if isCall && isTarget && isFrom {
return trace return trace
......
...@@ -37,8 +37,8 @@ func init() { ...@@ -37,8 +37,8 @@ func init() {
// EncodeCrossDomainMessageV0 will encode the calldata for // EncodeCrossDomainMessageV0 will encode the calldata for
// "relayMessage(address,address,bytes,uint256)", // "relayMessage(address,address,bytes,uint256)",
func EncodeCrossDomainMessageV0( func EncodeCrossDomainMessageV0(
target *common.Address, target common.Address,
sender *common.Address, sender common.Address,
message []byte, message []byte,
nonce *big.Int, nonce *big.Int,
) ([]byte, error) { ) ([]byte, error) {
...@@ -49,8 +49,8 @@ func EncodeCrossDomainMessageV0( ...@@ -49,8 +49,8 @@ func EncodeCrossDomainMessageV0(
// "relayMessage(uint256,address,address,uint256,uint256,bytes)", // "relayMessage(uint256,address,address,uint256,uint256,bytes)",
func EncodeCrossDomainMessageV1( func EncodeCrossDomainMessageV1(
nonce *big.Int, nonce *big.Int,
sender *common.Address, sender common.Address,
target *common.Address, target common.Address,
value *big.Int, value *big.Int,
gasLimit *big.Int, gasLimit *big.Int,
data []byte, data []byte,
......
...@@ -10,8 +10,8 @@ import ( ...@@ -10,8 +10,8 @@ import (
// HashCrossDomainMessageV0 computes the pre bedrock cross domain messaging // HashCrossDomainMessageV0 computes the pre bedrock cross domain messaging
// hashing scheme. // hashing scheme.
func HashCrossDomainMessageV0( func HashCrossDomainMessageV0(
target *common.Address, target common.Address,
sender *common.Address, sender common.Address,
data []byte, data []byte,
nonce *big.Int, nonce *big.Int,
) (common.Hash, error) { ) (common.Hash, error) {
...@@ -27,8 +27,8 @@ func HashCrossDomainMessageV0( ...@@ -27,8 +27,8 @@ func HashCrossDomainMessageV0(
// messaging hashing scheme. // messaging hashing scheme.
func HashCrossDomainMessageV1( func HashCrossDomainMessageV1(
nonce *big.Int, nonce *big.Int,
sender *common.Address, sender common.Address,
target *common.Address, target common.Address,
value *big.Int, value *big.Int,
gasLimit *big.Int, gasLimit *big.Int,
data []byte, data []byte,
......
...@@ -16,21 +16,28 @@ import ( ...@@ -16,21 +16,28 @@ import (
// LegacyWithdrawal represents a pre bedrock upgrade withdrawal. // LegacyWithdrawal represents a pre bedrock upgrade withdrawal.
type LegacyWithdrawal struct { type LegacyWithdrawal struct {
Target *common.Address `json:"target"` // MessageSender is the caller of the message passer
Sender *common.Address `json:"sender"` MessageSender common.Address `json:"who"`
Data hexutil.Bytes `json:"data"` // XDomainTarget is the L1 target of the withdrawal message
Nonce *big.Int `json:"nonce"` XDomainTarget common.Address `json:"target"`
// XDomainSender is the L2 withdrawing account
XDomainSender common.Address `json:"sender"`
// XDomainData represents the calldata of the withdrawal message
XDomainData hexutil.Bytes `json:"data"`
// XDomainNonce represents the nonce of the withdrawal
XDomainNonce *big.Int `json:"nonce"`
} }
var _ WithdrawalMessage = (*LegacyWithdrawal)(nil) var _ WithdrawalMessage = (*LegacyWithdrawal)(nil)
// NewLegacyWithdrawal will construct a LegacyWithdrawal // NewLegacyWithdrawal will construct a LegacyWithdrawal
func NewLegacyWithdrawal(target, sender *common.Address, data []byte, nonce *big.Int) *LegacyWithdrawal { func NewLegacyWithdrawal(msgSender, target, sender common.Address, data []byte, nonce *big.Int) *LegacyWithdrawal {
return &LegacyWithdrawal{ return &LegacyWithdrawal{
Target: target, MessageSender: msgSender,
Sender: sender, XDomainTarget: target,
Data: data, XDomainSender: sender,
Nonce: nonce, XDomainData: data,
XDomainNonce: nonce,
} }
} }
...@@ -39,7 +46,7 @@ func NewLegacyWithdrawal(target, sender *common.Address, data []byte, nonce *big ...@@ -39,7 +46,7 @@ func NewLegacyWithdrawal(target, sender *common.Address, data []byte, nonce *big
// through the standard optimism cross domain messaging system by hashing in // through the standard optimism cross domain messaging system by hashing in
// the L2CrossDomainMessenger address. // the L2CrossDomainMessenger address.
func (w *LegacyWithdrawal) Encode() ([]byte, error) { func (w *LegacyWithdrawal) Encode() ([]byte, error) {
enc, err := EncodeCrossDomainMessageV0(w.Target, w.Sender, []byte(w.Data), w.Nonce) enc, err := EncodeCrossDomainMessageV0(w.XDomainTarget, w.XDomainSender, []byte(w.XDomainData), w.XDomainNonce)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot encode LegacyWithdrawal: %w", err) return nil, fmt.Errorf("cannot encode LegacyWithdrawal: %w", err)
} }
...@@ -62,9 +69,6 @@ func (w *LegacyWithdrawal) Decode(data []byte) error { ...@@ -62,9 +69,6 @@ func (w *LegacyWithdrawal) Decode(data []byte) error {
} }
msgSender := data[len(data)-len(predeploys.L2CrossDomainMessengerAddr):] msgSender := data[len(data)-len(predeploys.L2CrossDomainMessengerAddr):]
if !bytes.Equal(msgSender, predeploys.L2CrossDomainMessengerAddr.Bytes()) {
return errors.New("invalid msg.sender")
}
raw := data[4 : len(data)-len(predeploys.L2CrossDomainMessengerAddr)] raw := data[4 : len(data)-len(predeploys.L2CrossDomainMessengerAddr)]
...@@ -97,10 +101,11 @@ func (w *LegacyWithdrawal) Decode(data []byte) error { ...@@ -97,10 +101,11 @@ func (w *LegacyWithdrawal) Decode(data []byte) error {
return errors.New("cannot abi decode nonce") return errors.New("cannot abi decode nonce")
} }
w.Target = &target w.MessageSender = common.BytesToAddress(msgSender)
w.Sender = &sender w.XDomainTarget = target
w.Data = hexutil.Bytes(msgData) w.XDomainSender = sender
w.Nonce = nonce w.XDomainData = msgData
w.XDomainNonce = nonce
return nil return nil
} }
...@@ -142,19 +147,15 @@ func (w *LegacyWithdrawal) Value() (*big.Int, error) { ...@@ -142,19 +147,15 @@ func (w *LegacyWithdrawal) Value() (*big.Int, error) {
value := new(big.Int) value := new(big.Int)
// Parse the 4byte selector // Parse the 4byte selector
method, err := abi.MethodById(w.Data) method, err := abi.MethodById(w.XDomainData)
// If it is an unknown selector, there is no value // If it is an unknown selector, there is no value
if err != nil { if err != nil {
return value, nil return value, nil
} }
if w.Sender == nil { isFromL2StandardBridge := w.XDomainSender == predeploys.L2StandardBridgeAddr
return nil, errors.New("sender is nil")
}
isFromL2StandardBridge := *w.Sender == predeploys.L2StandardBridgeAddr
if isFromL2StandardBridge && method.Name == "finalizeETHWithdrawal" { if isFromL2StandardBridge && method.Name == "finalizeETHWithdrawal" {
data, err := method.Inputs.Unpack(w.Data[4:]) data, err := method.Inputs.Unpack(w.XDomainData[4:])
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -177,11 +178,11 @@ func (w *LegacyWithdrawal) Value() (*big.Int, error) { ...@@ -177,11 +178,11 @@ func (w *LegacyWithdrawal) Value() (*big.Int, error) {
// the concept of value or gaslimit, so set them to 0. // the concept of value or gaslimit, so set them to 0.
func (w *LegacyWithdrawal) CrossDomainMessage() *CrossDomainMessage { func (w *LegacyWithdrawal) CrossDomainMessage() *CrossDomainMessage {
return &CrossDomainMessage{ return &CrossDomainMessage{
Nonce: w.Nonce, Nonce: w.XDomainNonce,
Sender: w.Sender, Sender: w.XDomainSender,
Target: w.Target, Target: w.XDomainTarget,
Value: new(big.Int), Value: new(big.Int),
GasLimit: new(big.Int), GasLimit: new(big.Int),
Data: []byte(w.Data), Data: []byte(w.XDomainData),
} }
} }
...@@ -133,8 +133,7 @@ func TestWithdrawalLegacyStorageSlot(t *testing.T) { ...@@ -133,8 +133,7 @@ func TestWithdrawalLegacyStorageSlot(t *testing.T) {
// Cast the cross domain message to a withdrawal. Note that // Cast the cross domain message to a withdrawal. Note that
// this only works for legacy style messages // this only works for legacy style messages
withdrawal, err := msg.ToWithdrawal() withdrawal := toWithdrawal(t, common.HexToAddress(call.From), msg)
require.Nil(t, err)
// Compute the legacy storage slot for the withdrawal // Compute the legacy storage slot for the withdrawal
slot, err := withdrawal.StorageSlot() slot, err := withdrawal.StorageSlot()
...@@ -160,12 +159,13 @@ func TestWithdrawalLegacyStorageSlot(t *testing.T) { ...@@ -160,12 +159,13 @@ func TestWithdrawalLegacyStorageSlot(t *testing.T) {
} }
func FuzzEncodeDecodeLegacyWithdrawal(f *testing.F) { func FuzzEncodeDecodeLegacyWithdrawal(f *testing.F) {
f.Fuzz(func(t *testing.T, _target, _sender, _nonce, data []byte) { f.Fuzz(func(t *testing.T, _msgSender, _target, _sender, _nonce, data []byte) {
msgSender := common.BytesToAddress(_msgSender)
target := common.BytesToAddress(_target) target := common.BytesToAddress(_target)
sender := common.BytesToAddress(_sender) sender := common.BytesToAddress(_sender)
nonce := new(big.Int).SetBytes(_nonce) nonce := new(big.Int).SetBytes(_nonce)
withdrawal := crossdomain.NewLegacyWithdrawal(&target, &sender, data, nonce) withdrawal := crossdomain.NewLegacyWithdrawal(msgSender, target, sender, data, nonce)
encoded, err := withdrawal.Encode() encoded, err := withdrawal.Encode()
require.Nil(t, err) require.Nil(t, err)
...@@ -174,10 +174,10 @@ func FuzzEncodeDecodeLegacyWithdrawal(f *testing.F) { ...@@ -174,10 +174,10 @@ func FuzzEncodeDecodeLegacyWithdrawal(f *testing.F) {
err = w.Decode(encoded) err = w.Decode(encoded)
require.Nil(t, err) require.Nil(t, err)
require.Equal(t, withdrawal.Nonce.Uint64(), w.Nonce.Uint64()) require.Equal(t, withdrawal.XDomainNonce.Uint64(), w.XDomainNonce.Uint64())
require.Equal(t, withdrawal.Sender, w.Sender) require.Equal(t, withdrawal.XDomainSender, w.XDomainSender)
require.Equal(t, withdrawal.Target, w.Target) require.Equal(t, withdrawal.XDomainTarget, w.XDomainTarget)
require.Equal(t, withdrawal.Data, w.Data) require.Equal(t, withdrawal.XDomainData, w.XDomainData)
}) })
} }
...@@ -221,8 +221,8 @@ func findCrossDomainMessage(receipt *types.Receipt) (*crossdomain.CrossDomainMes ...@@ -221,8 +221,8 @@ func findCrossDomainMessage(receipt *types.Receipt) (*crossdomain.CrossDomainMes
// Parse the legacy event // Parse the legacy event
if event.Name == "SentMessage" { if event.Name == "SentMessage" {
e, _ := l2xdm.ParseSentMessage(*log) e, _ := l2xdm.ParseSentMessage(*log)
msg.Target = &e.Target msg.Target = e.Target
msg.Sender = &e.Sender msg.Sender = e.Sender
msg.Data = e.Message msg.Data = e.Message
msg.Nonce = e.MessageNonce msg.Nonce = e.MessageNonce
msg.GasLimit = e.GasLimit msg.GasLimit = e.GasLimit
...@@ -336,3 +336,30 @@ func readStateDiff(hash string) (stateDiff, error) { ...@@ -336,3 +336,30 @@ func readStateDiff(hash string) (stateDiff, error) {
} }
return diff, nil return diff, nil
} }
// ToWithdrawal will turn a CrossDomainMessage into a Withdrawal.
// This only works for version 0 CrossDomainMessages as not all of
// the data is present for version 1 CrossDomainMessages to be turned
// into Withdrawals.
func toWithdrawal(t *testing.T, msgSender common.Address, c *crossdomain.CrossDomainMessage) *crossdomain.LegacyWithdrawal {
version := c.Version()
switch version {
case 0:
if c.Value != nil && c.Value.Cmp(common.Big0) != 0 {
t.Fatalf("version 0 messages must have 0 value")
}
w := &crossdomain.LegacyWithdrawal{
MessageSender: msgSender,
XDomainTarget: c.Target,
XDomainSender: c.Sender,
XDomainData: c.Data,
XDomainNonce: c.Nonce,
}
return w
case 1:
t.Fatalf("cannot convert version 1 messages to withdrawals")
default:
t.Fatalf("unknown message version: %d", version)
}
return nil
}
package crossdomain package crossdomain
import ( import (
"errors"
"fmt" "fmt"
"math/big" "math/big"
...@@ -14,18 +13,18 @@ import ( ...@@ -14,18 +13,18 @@ import (
// version 1 messages have a value and the most significant // version 1 messages have a value and the most significant
// byte of the nonce is a 1 // byte of the nonce is a 1
type CrossDomainMessage struct { type CrossDomainMessage struct {
Nonce *big.Int `json:"nonce"` Nonce *big.Int `json:"nonce"`
Sender *common.Address `json:"sender"` Sender common.Address `json:"sender"`
Target *common.Address `json:"target"` Target common.Address `json:"target"`
Value *big.Int `json:"value"` Value *big.Int `json:"value"`
GasLimit *big.Int `json:"gasLimit"` GasLimit *big.Int `json:"gasLimit"`
Data []byte `json:"data"` Data []byte `json:"data"`
} }
// NewCrossDomainMessage creates a CrossDomainMessage. // NewCrossDomainMessage creates a CrossDomainMessage.
func NewCrossDomainMessage( func NewCrossDomainMessage(
nonce *big.Int, nonce *big.Int,
sender, target *common.Address, sender, target common.Address,
value, gasLimit *big.Int, value, gasLimit *big.Int,
data []byte, data []byte,
) *CrossDomainMessage { ) *CrossDomainMessage {
...@@ -77,23 +76,3 @@ func (c *CrossDomainMessage) Hash() (common.Hash, error) { ...@@ -77,23 +76,3 @@ func (c *CrossDomainMessage) Hash() (common.Hash, error) {
func (c *CrossDomainMessage) HashV1() (common.Hash, error) { func (c *CrossDomainMessage) HashV1() (common.Hash, error) {
return HashCrossDomainMessageV1(c.Nonce, c.Sender, c.Target, c.Value, c.GasLimit, c.Data) return HashCrossDomainMessageV1(c.Nonce, c.Sender, c.Target, c.Value, c.GasLimit, c.Data)
} }
// ToWithdrawal will turn a CrossDomainMessage into a Withdrawal.
// This only works for version 0 CrossDomainMessages as not all of
// the data is present for version 1 CrossDomainMessages to be turned
// into Withdrawals.
func (c *CrossDomainMessage) ToWithdrawal() (WithdrawalMessage, error) {
version := c.Version()
switch version {
case 0:
if c.Value != nil && c.Value.Cmp(common.Big0) != 0 {
return nil, errors.New("version 0 messages must have 0 value")
}
w := NewLegacyWithdrawal(c.Target, c.Sender, c.Data, c.Nonce)
return w, nil
case 1:
return nil, errors.New("version 1 messages cannot be turned into withdrawals")
default:
return nil, fmt.Errorf("unknown version %d", version)
}
}
...@@ -18,8 +18,8 @@ func TestEncode(t *testing.T) { ...@@ -18,8 +18,8 @@ func TestEncode(t *testing.T) {
t.Run("V0", func(t *testing.T) { t.Run("V0", func(t *testing.T) {
msg := crossdomain.NewCrossDomainMessage( msg := crossdomain.NewCrossDomainMessage(
crossdomain.EncodeVersionedNonce(common.Big0, common.Big0), crossdomain.EncodeVersionedNonce(common.Big0, common.Big0),
&common.Address{}, common.Address{},
&common.Address{19: 0x01}, common.Address{19: 0x01},
big.NewInt(0), big.NewInt(0),
big.NewInt(5), big.NewInt(5),
[]byte{}, []byte{},
...@@ -37,8 +37,8 @@ func TestEncode(t *testing.T) { ...@@ -37,8 +37,8 @@ func TestEncode(t *testing.T) {
t.Run("V1", func(t *testing.T) { t.Run("V1", func(t *testing.T) {
msg := crossdomain.NewCrossDomainMessage( msg := crossdomain.NewCrossDomainMessage(
crossdomain.EncodeVersionedNonce(common.Big1, common.Big1), crossdomain.EncodeVersionedNonce(common.Big1, common.Big1),
&common.Address{19: 0x01}, common.Address{19: 0x01},
&common.Address{19: 0x02}, common.Address{19: 0x02},
big.NewInt(100), big.NewInt(100),
big.NewInt(555), big.NewInt(555),
[]byte{}, []byte{},
...@@ -63,8 +63,8 @@ func TestHash(t *testing.T) { ...@@ -63,8 +63,8 @@ func TestHash(t *testing.T) {
t.Run("V0", func(t *testing.T) { t.Run("V0", func(t *testing.T) {
msg := crossdomain.NewCrossDomainMessage( msg := crossdomain.NewCrossDomainMessage(
crossdomain.EncodeVersionedNonce(common.Big0, common.Big0), crossdomain.EncodeVersionedNonce(common.Big0, common.Big0),
&common.Address{}, common.Address{},
&common.Address{19: 0x01}, common.Address{19: 0x01},
big.NewInt(10), big.NewInt(10),
big.NewInt(5), big.NewInt(5),
[]byte{}, []byte{},
...@@ -82,8 +82,8 @@ func TestHash(t *testing.T) { ...@@ -82,8 +82,8 @@ func TestHash(t *testing.T) {
t.Run("V1", func(t *testing.T) { t.Run("V1", func(t *testing.T) {
msg := crossdomain.NewCrossDomainMessage( msg := crossdomain.NewCrossDomainMessage(
crossdomain.EncodeVersionedNonce(common.Big0, common.Big1), crossdomain.EncodeVersionedNonce(common.Big0, common.Big1),
&common.Address{}, common.Address{},
&common.Address{19: 0x01}, common.Address{19: 0x01},
big.NewInt(0), big.NewInt(0),
big.NewInt(5), big.NewInt(5),
[]byte{}, []byte{},
......
...@@ -19,7 +19,7 @@ var ( ...@@ -19,7 +19,7 @@ var (
) )
// MigrateWithdrawals will migrate a list of pending withdrawals given a StateDB. // MigrateWithdrawals will migrate a list of pending withdrawals given a StateDB.
func MigrateWithdrawals(withdrawals []*LegacyWithdrawal, db vm.StateDB, l1CrossDomainMessenger *common.Address, noCheck bool) error { func MigrateWithdrawals(withdrawals SafeFilteredWithdrawals, db vm.StateDB, l1CrossDomainMessenger *common.Address, noCheck bool) error {
for i, legacy := range withdrawals { for i, legacy := range withdrawals {
legacySlot, err := legacy.StorageSlot() legacySlot, err := legacy.StorageSlot()
if err != nil { if err != nil {
...@@ -66,17 +66,17 @@ func MigrateWithdrawal(withdrawal *LegacyWithdrawal, l1CrossDomainMessenger *com ...@@ -66,17 +66,17 @@ func MigrateWithdrawal(withdrawal *LegacyWithdrawal, l1CrossDomainMessenger *com
// Migrated withdrawals are specified as version 0. Both the // Migrated withdrawals are specified as version 0. Both the
// L2ToL1MessagePasser and the CrossDomainMessenger use the same // L2ToL1MessagePasser and the CrossDomainMessenger use the same
// versioning scheme. Both should be set to version 0 // versioning scheme. Both should be set to version 0
versionedNonce := EncodeVersionedNonce(withdrawal.Nonce, new(big.Int)) versionedNonce := EncodeVersionedNonce(withdrawal.XDomainNonce, new(big.Int))
// Encode the call to `relayMessage` on the `CrossDomainMessenger`. // Encode the call to `relayMessage` on the `CrossDomainMessenger`.
// The minGasLimit can safely be 0 here. // The minGasLimit can safely be 0 here.
data, err := abi.Pack( data, err := abi.Pack(
"relayMessage", "relayMessage",
versionedNonce, versionedNonce,
withdrawal.Sender, withdrawal.XDomainSender,
withdrawal.Target, withdrawal.XDomainTarget,
value, value,
new(big.Int), new(big.Int),
[]byte(withdrawal.Data), []byte(withdrawal.XDomainData),
) )
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot abi encode relayMessage: %w", err) return nil, fmt.Errorf("cannot abi encode relayMessage: %w", err)
......
...@@ -17,10 +17,7 @@ func TestMigrateWithdrawal(t *testing.T) { ...@@ -17,10 +17,7 @@ func TestMigrateWithdrawal(t *testing.T) {
for _, receipt := range receipts { for _, receipt := range receipts {
msg, err := findCrossDomainMessage(receipt) msg, err := findCrossDomainMessage(receipt)
require.Nil(t, err) require.Nil(t, err)
withdrawal, err := msg.ToWithdrawal() legacyWithdrawal := toWithdrawal(t, predeploys.L2CrossDomainMessengerAddr, msg)
require.Nil(t, err)
legacyWithdrawal, ok := withdrawal.(*crossdomain.LegacyWithdrawal)
require.True(t, ok)
withdrawals = append(withdrawals, legacyWithdrawal) withdrawals = append(withdrawals, legacyWithdrawal)
} }
...@@ -31,7 +28,7 @@ func TestMigrateWithdrawal(t *testing.T) { ...@@ -31,7 +28,7 @@ func TestMigrateWithdrawal(t *testing.T) {
require.Nil(t, err) require.Nil(t, err)
require.NotNil(t, withdrawal) require.NotNil(t, withdrawal)
require.Equal(t, legacy.Nonce.Uint64(), withdrawal.Nonce.Uint64()) require.Equal(t, legacy.XDomainNonce.Uint64(), withdrawal.Nonce.Uint64())
require.Equal(t, *withdrawal.Sender, predeploys.L2CrossDomainMessengerAddr) require.Equal(t, *withdrawal.Sender, predeploys.L2CrossDomainMessengerAddr)
require.Equal(t, *withdrawal.Target, l1CrossDomainMessenger) require.Equal(t, *withdrawal.Target, l1CrossDomainMessenger)
}) })
......
package crossdomain package crossdomain
import ( import (
"errors"
"fmt" "fmt"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys" "github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
var (
ErrUnknownSlotInMessagePasser = errors.New("unknown slot in legacy message passer")
ErrMissingSlotInWitness = errors.New("missing storage slot in witness data")
)
// PreCheckWithdrawals checks that the given list of withdrawals represents all withdrawals made // PreCheckWithdrawals checks that the given list of withdrawals represents all withdrawals made
// in the legacy system and filters out any extra withdrawals not included in the legacy system. // in the legacy system and filters out any extra withdrawals not included in the legacy system.
func PreCheckWithdrawals(db *state.StateDB, withdrawals []*LegacyWithdrawal) ([]*LegacyWithdrawal, error) { func PreCheckWithdrawals(db *state.StateDB, withdrawals DangerousUnfilteredWithdrawals) (SafeFilteredWithdrawals, error) {
// Convert each withdrawal into a storage slot, and build a map of those slots. // Convert each withdrawal into a storage slot, and build a map of those slots.
slotsInp := make(map[common.Hash]*LegacyWithdrawal) slotsInp := make(map[common.Hash]*LegacyWithdrawal)
for _, wd := range withdrawals { for _, wd := range withdrawals {
...@@ -26,6 +31,7 @@ func PreCheckWithdrawals(db *state.StateDB, withdrawals []*LegacyWithdrawal) ([] ...@@ -26,6 +31,7 @@ func PreCheckWithdrawals(db *state.StateDB, withdrawals []*LegacyWithdrawal) ([]
// Build a mapping of the slots of all messages actually sent in the legacy system. // Build a mapping of the slots of all messages actually sent in the legacy system.
var count int var count int
var innerErr error
slotsAct := make(map[common.Hash]bool) slotsAct := make(map[common.Hash]bool)
err := db.ForEachStorage(predeploys.LegacyMessagePasserAddr, func(key, value common.Hash) bool { err := db.ForEachStorage(predeploys.LegacyMessagePasserAddr, func(key, value common.Hash) bool {
// When a message is inserted into the LegacyMessagePasser, it is stored with the value // When a message is inserted into the LegacyMessagePasser, it is stored with the value
...@@ -33,7 +39,7 @@ func PreCheckWithdrawals(db *state.StateDB, withdrawals []*LegacyWithdrawal) ([] ...@@ -33,7 +39,7 @@ func PreCheckWithdrawals(db *state.StateDB, withdrawals []*LegacyWithdrawal) ([]
// can safely ignore anything that is not "true". // can safely ignore anything that is not "true".
if value != abiTrue { if value != abiTrue {
// Should not happen! // Should not happen!
log.Error("found unknown slot in LegacyMessagePasser", "key", key.String(), "val", value.String()) innerErr = fmt.Errorf("%w: key: %s, val: %s", ErrUnknownSlotInMessagePasser, key.String(), value.String())
return true return true
} }
...@@ -45,6 +51,9 @@ func PreCheckWithdrawals(db *state.StateDB, withdrawals []*LegacyWithdrawal) ([] ...@@ -45,6 +51,9 @@ func PreCheckWithdrawals(db *state.StateDB, withdrawals []*LegacyWithdrawal) ([]
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot iterate over LegacyMessagePasser: %w", err) return nil, fmt.Errorf("cannot iterate over LegacyMessagePasser: %w", err)
} }
if innerErr != nil {
return nil, innerErr
}
// Log the number of messages we found. // Log the number of messages we found.
log.Info("Iterated legacy messages", "count", count) log.Info("Iterated legacy messages", "count", count)
...@@ -53,13 +62,13 @@ func PreCheckWithdrawals(db *state.StateDB, withdrawals []*LegacyWithdrawal) ([] ...@@ -53,13 +62,13 @@ func PreCheckWithdrawals(db *state.StateDB, withdrawals []*LegacyWithdrawal) ([]
for slot := range slotsAct { for slot := range slotsAct {
_, ok := slotsInp[slot] _, ok := slotsInp[slot]
if !ok { if !ok {
return nil, fmt.Errorf("unknown storage slot in state: %s", slot) return nil, ErrMissingSlotInWitness
} }
} }
// Iterate over the list of input messages and check that we have a known slot for each one. // Iterate over the list of input messages and check that we have a known slot for each one.
// We'll filter out any extra messages that are not in the legacy system. // We'll filter out any extra messages that are not in the legacy system.
filtered := make([]*LegacyWithdrawal, 0) filtered := make(SafeFilteredWithdrawals, 0)
for slot := range slotsInp { for slot := range slotsInp {
_, ok := slotsAct[slot] _, ok := slotsAct[slot]
if !ok { if !ok {
...@@ -67,7 +76,13 @@ func PreCheckWithdrawals(db *state.StateDB, withdrawals []*LegacyWithdrawal) ([] ...@@ -67,7 +76,13 @@ func PreCheckWithdrawals(db *state.StateDB, withdrawals []*LegacyWithdrawal) ([]
continue continue
} }
filtered = append(filtered, slotsInp[slot]) wd := slotsInp[slot]
if wd.MessageSender != predeploys.L2CrossDomainMessengerAddr {
log.Info("filtering out message from sender other than the L2XDM", "sender", wd.MessageSender)
continue
}
filtered = append(filtered, wd)
} }
// At this point, we know that the list of filtered withdrawals MUST be exactly the same as the // At this point, we know that the list of filtered withdrawals MUST be exactly the same as the
......
package crossdomain
import (
"math/big"
"testing"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/trie"
"github.com/stretchr/testify/require"
)
func TestPreCheckWithdrawals_Filtering(t *testing.T) {
dbWds := []*LegacyWithdrawal{
// Random legacy WD to something other than the L2XDM.
{
MessageSender: common.Address{19: 0xFF},
XDomainTarget: common.Address{19: 0x01},
XDomainSender: common.Address{19: 0x02},
XDomainData: []byte{0x01, 0x02, 0x03},
XDomainNonce: big.NewInt(0),
},
// Random legacy WD to the L2XDM. Should be the only thing
// returned by the prechecker.
{
MessageSender: predeploys.L2CrossDomainMessengerAddr,
XDomainTarget: common.Address{19: 0x01},
XDomainSender: common.Address{19: 0x02},
XDomainData: []byte{0x01, 0x02, 0x03},
XDomainNonce: big.NewInt(1),
},
}
// Add an additional witness to the witnesses list to
// test how the prechecker handles witness data that
// isn't in state.
witnessWds := append([]*LegacyWithdrawal{
{
MessageSender: common.Address{19: 0xAA},
XDomainTarget: common.Address{19: 0x03},
XDomainSender: predeploys.L2CrossDomainMessengerAddr,
XDomainData: []byte{0x01, 0x02, 0x03},
XDomainNonce: big.NewInt(0),
},
}, dbWds...)
filteredWds, err := runPrecheck(t, dbWds, witnessWds)
require.NoError(t, err)
require.EqualValues(t, []*LegacyWithdrawal{dbWds[1]}, filteredWds)
}
func TestPreCheckWithdrawals_InvalidSlotInStorage(t *testing.T) {
rawDB := rawdb.NewMemoryDatabase()
rawStateDB := state.NewDatabaseWithConfig(rawDB, &trie.Config{
Preimages: true,
Cache: 1024,
})
stateDB, err := state.New(common.Hash{}, rawStateDB, nil)
require.NoError(t, err)
// Create account, and set a random storage slot to a value
// other than abiTrue.
stateDB.CreateAccount(predeploys.LegacyMessagePasserAddr)
stateDB.SetState(predeploys.LegacyMessagePasserAddr, common.Hash{0: 0xff}, common.Hash{0: 0xff})
root, err := stateDB.Commit(false)
require.NoError(t, err)
err = stateDB.Database().TrieDB().Commit(root, true, nil)
require.NoError(t, err)
_, err = PreCheckWithdrawals(stateDB, nil)
require.ErrorIs(t, err, ErrUnknownSlotInMessagePasser)
}
func TestPreCheckWithdrawals_MissingStorageSlot(t *testing.T) {
// Add a legacy WD to state that does not appear in witness data.
dbWds := []*LegacyWithdrawal{
{
XDomainTarget: common.Address{19: 0x01},
XDomainSender: predeploys.L2CrossDomainMessengerAddr,
XDomainData: []byte{0x01, 0x02, 0x03},
XDomainNonce: big.NewInt(1),
},
}
// Create some witness data that includes both a valid
// and an invalid witness, but neither of which correspond
// to the value above in state.
witnessWds := []*LegacyWithdrawal{
{
XDomainTarget: common.Address{19: 0x01},
XDomainSender: common.Address{19: 0x02},
XDomainData: []byte{0x01, 0x02, 0x03},
XDomainNonce: big.NewInt(0),
},
{
XDomainTarget: common.Address{19: 0x03},
XDomainSender: predeploys.L2CrossDomainMessengerAddr,
XDomainData: []byte{0x01, 0x02, 0x03},
XDomainNonce: big.NewInt(0),
},
}
_, err := runPrecheck(t, dbWds, witnessWds)
require.ErrorIs(t, err, ErrMissingSlotInWitness)
}
func runPrecheck(t *testing.T, dbWds []*LegacyWithdrawal, witnessWds []*LegacyWithdrawal) ([]*LegacyWithdrawal, error) {
rawDB := rawdb.NewMemoryDatabase()
rawStateDB := state.NewDatabaseWithConfig(rawDB, &trie.Config{
Preimages: true,
Cache: 1024,
})
stateDB, err := state.New(common.Hash{}, rawStateDB, nil)
require.NoError(t, err)
stateDB.CreateAccount(predeploys.LegacyMessagePasserAddr)
for _, wd := range dbWds {
slot, err := wd.StorageSlot()
require.NoError(t, err)
stateDB.SetState(predeploys.LegacyMessagePasserAddr, slot, abiTrue)
}
root, err := stateDB.Commit(false)
require.NoError(t, err)
err = stateDB.Database().TrieDB().Commit(root, true, nil)
require.NoError(t, err)
return PreCheckWithdrawals(stateDB, witnessWds)
}
...@@ -5,6 +5,15 @@ import ( ...@@ -5,6 +5,15 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
) )
// DangerousUnfilteredWithdrawals is a list of raw withdrawal witness
// data. It has not been filtered for messages from sources other than
// the
type DangerousUnfilteredWithdrawals []*LegacyWithdrawal
// SafeFilteredWithdrawals is a list of withdrawals that have been filtered to only include
// withdrawals that were from the L2XDM.
type SafeFilteredWithdrawals []*LegacyWithdrawal
var ( var (
// Standard ABI types // Standard ABI types
Uint256Type, _ = abi.NewType("uint256", "", nil) Uint256Type, _ = abi.NewType("uint256", "", nil)
......
...@@ -87,8 +87,8 @@ func GetPendingWithdrawals(messengers *Messengers, version *big.Int, start, end ...@@ -87,8 +87,8 @@ func GetPendingWithdrawals(messengers *Messengers, version *big.Int, start, end
msg := NewCrossDomainMessage( msg := NewCrossDomainMessage(
event.MessageNonce, event.MessageNonce,
&event.Sender, event.Sender,
&event.Target, event.Target,
common.Big0, common.Big0,
event.GasLimit, event.GasLimit,
event.Message, event.Message,
...@@ -116,10 +116,10 @@ func GetPendingWithdrawals(messengers *Messengers, version *big.Int, start, end ...@@ -116,10 +116,10 @@ func GetPendingWithdrawals(messengers *Messengers, version *big.Int, start, end
withdrawal := PendingWithdrawal{ withdrawal := PendingWithdrawal{
LegacyWithdrawal: LegacyWithdrawal{ LegacyWithdrawal: LegacyWithdrawal{
Target: &event.Target, XDomainTarget: event.Target,
Sender: &event.Sender, XDomainSender: event.Sender,
Data: event.Message, XDomainData: event.Message,
Nonce: event.MessageNonce, XDomainNonce: event.MessageNonce,
}, },
TransactionHash: event.Raw.TxHash, TransactionHash: event.Raw.TxHash,
} }
......
...@@ -146,8 +146,8 @@ func sendCrossDomainMessage( ...@@ -146,8 +146,8 @@ func sendCrossDomainMessage(
// Parse the legacy event // Parse the legacy event
if event.Name == "SentMessage" { if event.Name == "SentMessage" {
e, _ := l2xdm.ParseSentMessage(*log) e, _ := l2xdm.ParseSentMessage(*log)
msg.Target = &e.Target msg.Target = e.Target
msg.Sender = &e.Sender msg.Sender = e.Sender
msg.Data = e.Message msg.Data = e.Message
msg.Nonce = e.MessageNonce msg.Nonce = e.MessageNonce
msg.GasLimit = e.GasLimit msg.GasLimit = e.GasLimit
...@@ -272,7 +272,7 @@ func TestGetPendingWithdrawals(t *testing.T) { ...@@ -272,7 +272,7 @@ func TestGetPendingWithdrawals(t *testing.T) {
for i, msg := range msgs[3:] { for i, msg := range msgs[3:] {
withdrawal := withdrawals[i] withdrawal := withdrawals[i]
require.Equal(t, msg.Target, *withdrawal.Target) require.Equal(t, msg.Target, withdrawal.XDomainTarget)
require.Equal(t, msg.Message, []byte(withdrawal.Data)) require.Equal(t, msg.Message, []byte(withdrawal.XDomainData))
} }
} }
...@@ -10,7 +10,15 @@ import ( ...@@ -10,7 +10,15 @@ import (
func Open(path string, cache int, handles int) (ethdb.Database, error) { func Open(path string, cache int, handles int) (ethdb.Database, error) {
chaindataPath := filepath.Join(path, "geth", "chaindata") chaindataPath := filepath.Join(path, "geth", "chaindata")
ancientPath := filepath.Join(chaindataPath, "ancient") ancientPath := filepath.Join(chaindataPath, "ancient")
ldb, err := rawdb.NewLevelDBDatabaseWithFreezer(chaindataPath, cache, handles, ancientPath, "", false) ldb, err := rawdb.Open(rawdb.OpenOptions{
Type: "leveldb",
Directory: chaindataPath,
AncientsDirectory: ancientPath,
Namespace: "",
Cache: cache,
Handles: handles,
ReadOnly: false,
})
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -63,8 +63,6 @@ func NewBackendWithGenesisTimestamp(ts uint64) *backends.SimulatedBackend { ...@@ -63,8 +63,6 @@ func NewBackendWithGenesisTimestamp(ts uint64) *backends.SimulatedBackend {
LondonBlock: big.NewInt(0), LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0), ArrowGlacierBlock: big.NewInt(0),
GrayGlacierBlock: big.NewInt(0), GrayGlacierBlock: big.NewInt(0),
ShanghaiBlock: nil,
CancunBlock: nil,
// Activated proof of stake. We manually build/commit blocks in the simulator anyway, // Activated proof of stake. We manually build/commit blocks in the simulator anyway,
// and the timestamp verification of PoS is not against the wallclock, // and the timestamp verification of PoS is not against the wallclock,
// preventing blocks from getting stuck temporarily in the future-blocks queue, decreasing setup time a lot. // preventing blocks from getting stuck temporarily in the future-blocks queue, decreasing setup time a lot.
......
...@@ -19,14 +19,15 @@ func MustOpenDB(dataDir string) ethdb.Database { ...@@ -19,14 +19,15 @@ func MustOpenDB(dataDir string) ethdb.Database {
// the caller to pass in LevelDB cache parameters. // the caller to pass in LevelDB cache parameters.
func MustOpenDBWithCacheOpts(dataDir string, cacheSize, handles int) ethdb.Database { func MustOpenDBWithCacheOpts(dataDir string, cacheSize, handles int) ethdb.Database {
dir := filepath.Join(dataDir, "geth", "chaindata") dir := filepath.Join(dataDir, "geth", "chaindata")
db, err := rawdb.NewLevelDBDatabaseWithFreezer( db, err := rawdb.Open(rawdb.OpenOptions{
dir, Type: "leveldb",
cacheSize, Directory: dir,
handles, AncientsDirectory: filepath.Join(dir, "ancient"),
filepath.Join(dir, "ancient"), Namespace: "",
"", Cache: cacheSize,
true, Handles: handles,
) ReadOnly: true,
})
if err != nil { if err != nil {
log.Crit("error opening raw DB", "err", err) log.Crit("error opening raw DB", "err", err)
} }
......
...@@ -7,20 +7,20 @@ import ( ...@@ -7,20 +7,20 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis/migration"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis/migration"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
) )
// MaxSlotChecks is the maximum number of storage slots to check // MaxSlotChecks is the maximum number of storage slots to check
...@@ -181,8 +181,25 @@ func PostCheckUntouchables(udb state.Database, currDB *state.StateDB, prevRoot c ...@@ -181,8 +181,25 @@ func PostCheckUntouchables(udb state.Database, currDB *state.StateDB, prevRoot c
log.Info("checked code hash", "address", addr, "hash", hash) log.Info("checked code hash", "address", addr, "hash", hash)
// Ensure that the current/previous roots match // Ensure that the current/previous roots match
prevRoot := prevDB.StorageTrie(addr).Hash() var prevRoot, currRoot common.Hash
currRoot := currDB.StorageTrie(addr).Hash() prevStorage, err := prevDB.StorageTrie(addr)
if err != nil {
return fmt.Errorf("failed to open previous-db storage trie of %s: %w", addr, err)
}
if prevStorage == nil {
prevRoot = types.EmptyRootHash
} else {
prevRoot = prevStorage.Hash()
}
currStorage, err := currDB.StorageTrie(addr)
if err != nil {
return fmt.Errorf("failed to open current-db storage trie of %s: %w", addr, err)
}
if currStorage == nil {
currRoot = types.EmptyRootHash
} else {
currRoot = currStorage.Hash()
}
if prevRoot != currRoot { if prevRoot != currRoot {
return fmt.Errorf("expected storage root for %s to be %s, but got %s", addr, prevRoot, currRoot) return fmt.Errorf("expected storage root for %s to be %s, but got %s", addr, prevRoot, currRoot)
} }
...@@ -191,12 +208,11 @@ func PostCheckUntouchables(udb state.Database, currDB *state.StateDB, prevRoot c ...@@ -191,12 +208,11 @@ func PostCheckUntouchables(udb state.Database, currDB *state.StateDB, prevRoot c
// Sample storage slots to ensure that they are not modified. // Sample storage slots to ensure that they are not modified.
var count int var count int
expSlots := make(map[common.Hash]common.Hash) expSlots := make(map[common.Hash]common.Hash)
err := prevDB.ForEachStorage(addr, func(key, value common.Hash) bool { if err := prevDB.ForEachStorage(addr, func(key, value common.Hash) bool {
count++ count++
expSlots[key] = value expSlots[key] = value
return count < MaxSlotChecks return count < MaxSlotChecks
}) }); err != nil {
if err != nil {
return fmt.Errorf("error iterating over storage: %w", err) return fmt.Errorf("error iterating over storage: %w", err)
} }
...@@ -461,7 +477,8 @@ func CheckWithdrawalsAfter(db vm.StateDB, data migration.MigrationData, l1CrossD ...@@ -461,7 +477,8 @@ func CheckWithdrawalsAfter(db vm.StateDB, data migration.MigrationData, l1CrossD
// First, make a mapping between old withdrawal slots and new ones. // First, make a mapping between old withdrawal slots and new ones.
// This list can be a superset of what was actually migrated, since // This list can be a superset of what was actually migrated, since
// some witness data may references withdrawals that reverted. // some witness data may references withdrawals that reverted.
oldToNew := make(map[common.Hash]common.Hash) oldToNewSlots := make(map[common.Hash]common.Hash)
wdsByOldSlot := make(map[common.Hash]*crossdomain.LegacyWithdrawal)
for _, wd := range wds { for _, wd := range wds {
migrated, err := crossdomain.MigrateWithdrawal(wd, l1CrossDomainMessenger) migrated, err := crossdomain.MigrateWithdrawal(wd, l1CrossDomainMessenger)
if err != nil { if err != nil {
...@@ -477,7 +494,8 @@ func CheckWithdrawalsAfter(db vm.StateDB, data migration.MigrationData, l1CrossD ...@@ -477,7 +494,8 @@ func CheckWithdrawalsAfter(db vm.StateDB, data migration.MigrationData, l1CrossD
return fmt.Errorf("cannot compute migrated storage slot: %w", err) return fmt.Errorf("cannot compute migrated storage slot: %w", err)
} }
oldToNew[legacySlot] = migratedSlot oldToNewSlots[legacySlot] = migratedSlot
wdsByOldSlot[legacySlot] = wd
} }
// Now, iterate over each legacy withdrawal and check if there is a corresponding // Now, iterate over each legacy withdrawal and check if there is a corresponding
...@@ -498,17 +516,29 @@ func CheckWithdrawalsAfter(db vm.StateDB, data migration.MigrationData, l1CrossD ...@@ -498,17 +516,29 @@ func CheckWithdrawalsAfter(db vm.StateDB, data migration.MigrationData, l1CrossD
} }
// Grab the migrated slot. // Grab the migrated slot.
migratedSlot := oldToNew[key] migratedSlot := oldToNewSlots[key]
if migratedSlot == (common.Hash{}) { if migratedSlot == (common.Hash{}) {
innerErr = fmt.Errorf("no migrated slot found for legacy slot %s", key) innerErr = fmt.Errorf("no migrated slot found for legacy slot %s", key)
return false return false
} }
// Look up the migrated slot in the DB, and make sure it is abiTrue. // Look up the migrated slot in the DB.
migratedValue := db.GetState(predeploys.L2ToL1MessagePasserAddr, migratedSlot) migratedValue := db.GetState(predeploys.L2ToL1MessagePasserAddr, migratedSlot)
if migratedValue != abiTrue {
innerErr = fmt.Errorf("expected migrated value to be true, but got %s", migratedValue) // If the sender is _not_ the L2XDM, the value should not be migrated.
return false wd := wdsByOldSlot[key]
if wd.XDomainSender == predeploys.L2CrossDomainMessengerAddr {
// Make sure the value is abiTrue if this withdrawal should be migrated.
if migratedValue != abiTrue {
innerErr = fmt.Errorf("expected migrated value to be true, but got %s", migratedValue)
return false
}
} else {
// Otherwise, ensure that withdrawals from senders other than the L2XDM are _not_ migrated.
if migratedValue != abiFalse {
innerErr = fmt.Errorf("a migration from a sender other than the L2XDM was migrated")
return false
}
} }
return true return true
......
...@@ -20,7 +20,8 @@ import ( ...@@ -20,7 +20,8 @@ import (
) )
var ( var (
abiTrue = common.Hash{31: 0x01} abiTrue = common.Hash{31: 0x01}
abiFalse = common.Hash{}
// BedrockTransitionBlockExtraData represents the extradata // BedrockTransitionBlockExtraData represents the extradata
// set in the very first bedrock block. This value must be // set in the very first bedrock block. This value must be
// less than 32 bytes long or it will create an invalid block. // less than 32 bytes long or it will create an invalid block.
...@@ -120,7 +121,7 @@ func MigrateDB(ldb ethdb.Database, config *DeployConfig, l1Block *types.Block, m ...@@ -120,7 +121,7 @@ func MigrateDB(ldb ethdb.Database, config *DeployConfig, l1Block *types.Block, m
// We now need to check that we have all of the withdrawals that we expect to have. An error // We now need to check that we have all of the withdrawals that we expect to have. An error
// will be thrown if there are any missing messages, and any extra messages will be removed. // will be thrown if there are any missing messages, and any extra messages will be removed.
var filteredWithdrawals []*crossdomain.LegacyWithdrawal var filteredWithdrawals crossdomain.SafeFilteredWithdrawals
if !noCheck { if !noCheck {
log.Info("Checking withdrawals...") log.Info("Checking withdrawals...")
filteredWithdrawals, err = crossdomain.PreCheckWithdrawals(db, unfilteredWithdrawals) filteredWithdrawals, err = crossdomain.PreCheckWithdrawals(db, unfilteredWithdrawals)
...@@ -129,7 +130,7 @@ func MigrateDB(ldb ethdb.Database, config *DeployConfig, l1Block *types.Block, m ...@@ -129,7 +130,7 @@ func MigrateDB(ldb ethdb.Database, config *DeployConfig, l1Block *types.Block, m
} }
} else { } else {
log.Info("Skipping checking withdrawals") log.Info("Skipping checking withdrawals")
filteredWithdrawals = unfilteredWithdrawals filteredWithdrawals = crossdomain.SafeFilteredWithdrawals(unfilteredWithdrawals)
} }
// We also need to verify that we have all of the storage slots for the LegacyERC20ETH contract // We also need to verify that we have all of the storage slots for the LegacyERC20ETH contract
...@@ -255,7 +256,7 @@ func MigrateDB(ldb ethdb.Database, config *DeployConfig, l1Block *types.Block, m ...@@ -255,7 +256,7 @@ func MigrateDB(ldb ethdb.Database, config *DeployConfig, l1Block *types.Block, m
// Otherwise we need to write the changes to disk. First we commit the state changes. // Otherwise we need to write the changes to disk. First we commit the state changes.
log.Info("Committing trie DB") log.Info("Committing trie DB")
if err := db.Database().TrieDB().Commit(newRoot, true, nil); err != nil { if err := db.Database().TrieDB().Commit(newRoot, true); err != nil {
return nil, err return nil, err
} }
......
...@@ -51,8 +51,6 @@ func NewL2Genesis(config *DeployConfig, block *types.Block) (*core.Genesis, erro ...@@ -51,8 +51,6 @@ func NewL2Genesis(config *DeployConfig, block *types.Block) (*core.Genesis, erro
ArrowGlacierBlock: big.NewInt(0), ArrowGlacierBlock: big.NewInt(0),
GrayGlacierBlock: big.NewInt(0), GrayGlacierBlock: big.NewInt(0),
MergeNetsplitBlock: big.NewInt(0), MergeNetsplitBlock: big.NewInt(0),
ShanghaiBlock: nil,
CancunBlock: nil,
TerminalTotalDifficulty: big.NewInt(0), TerminalTotalDifficulty: big.NewInt(0),
TerminalTotalDifficultyPassed: true, TerminalTotalDifficultyPassed: true,
BedrockBlock: new(big.Int).SetUint64(uint64(config.L2GenesisBlockNumber)), BedrockBlock: new(big.Int).SetUint64(uint64(config.L2GenesisBlockNumber)),
...@@ -121,8 +119,6 @@ func NewL1Genesis(config *DeployConfig) (*core.Genesis, error) { ...@@ -121,8 +119,6 @@ func NewL1Genesis(config *DeployConfig) (*core.Genesis, error) {
LondonBlock: big.NewInt(0), LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0), ArrowGlacierBlock: big.NewInt(0),
GrayGlacierBlock: big.NewInt(0), GrayGlacierBlock: big.NewInt(0),
ShanghaiBlock: nil,
CancunBlock: nil,
} }
if config.CliqueSignerAddress != (common.Address{}) { if config.CliqueSignerAddress != (common.Address{}) {
......
...@@ -216,7 +216,13 @@ func BuildL1DeveloperGenesis(config *DeployConfig) (*core.Genesis, error) { ...@@ -216,7 +216,13 @@ func BuildL1DeveloperGenesis(config *DeployConfig) (*core.Genesis, error) {
} }
for _, dep := range deployments { for _, dep := range deployments {
st := stateDB.StorageTrie(dep.Address) st, err := stateDB.StorageTrie(dep.Address)
if err != nil {
return nil, fmt.Errorf("failed to open storage trie of %s: %w", dep.Address, err)
}
if st == nil {
return nil, fmt.Errorf("missing account %s in state, address: %s", dep.Name, dep.Address)
}
iter := trie.NewIterator(st.NodeIterator(nil)) iter := trie.NewIterator(st.NodeIterator(nil))
depAddr := dep.Address depAddr := dep.Address
......
...@@ -5,8 +5,6 @@ import ( ...@@ -5,8 +5,6 @@ import (
"fmt" "fmt"
"os" "os"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain" "github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
...@@ -119,12 +117,9 @@ type MigrationData struct { ...@@ -119,12 +117,9 @@ type MigrationData struct {
EvmMessages []*SentMessage EvmMessages []*SentMessage
} }
func (m *MigrationData) ToWithdrawals() ([]*crossdomain.LegacyWithdrawal, error) { func (m *MigrationData) ToWithdrawals() (crossdomain.DangerousUnfilteredWithdrawals, error) {
messages := make([]*crossdomain.LegacyWithdrawal, 0) messages := make(crossdomain.DangerousUnfilteredWithdrawals, 0)
for _, msg := range m.OvmMessages { for _, msg := range m.OvmMessages {
if msg.Who != predeploys.L2CrossDomainMessengerAddr {
continue
}
wd, err := msg.ToLegacyWithdrawal() wd, err := msg.ToLegacyWithdrawal()
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -135,9 +130,6 @@ func (m *MigrationData) ToWithdrawals() ([]*crossdomain.LegacyWithdrawal, error) ...@@ -135,9 +130,6 @@ func (m *MigrationData) ToWithdrawals() ([]*crossdomain.LegacyWithdrawal, error)
} }
} }
for _, msg := range m.EvmMessages { for _, msg := range m.EvmMessages {
if msg.Who != predeploys.L2CrossDomainMessengerAddr {
continue
}
wd, err := msg.ToLegacyWithdrawal() wd, err := msg.ToLegacyWithdrawal()
if err != nil { if err != nil {
return nil, err return nil, err
......
...@@ -76,7 +76,16 @@ func Migrate(cfg *Config) (*genesis.MigrationResult, error) { ...@@ -76,7 +76,16 @@ func Migrate(cfg *Config) (*genesis.MigrationResult, error) {
chaindataPath := filepath.Join(cfg.L2DBPath, "geth", "chaindata") chaindataPath := filepath.Join(cfg.L2DBPath, "geth", "chaindata")
ancientPath := filepath.Join(chaindataPath, "ancient") ancientPath := filepath.Join(chaindataPath, "ancient")
ldb, err := rawdb.NewLevelDBDatabaseWithFreezer(chaindataPath, 4096, 120, ancientPath, "", false) ldb, err := rawdb.Open(
rawdb.OpenOptions{
Type: "leveldb",
Directory: chaindataPath,
Cache: 4096,
Handles: 120,
AncientsDirectory: ancientPath,
Namespace: "",
ReadOnly: false,
})
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -11,6 +11,7 @@ import ( ...@@ -11,6 +11,7 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
) )
var _ vm.StateDB = (*MemoryStateDB)(nil) var _ vm.StateDB = (*MemoryStateDB)(nil)
...@@ -312,3 +313,15 @@ func (db *MemoryStateDB) ForEachStorage(addr common.Address, cb func(common.Hash ...@@ -312,3 +313,15 @@ func (db *MemoryStateDB) ForEachStorage(addr common.Address, cb func(common.Hash
} }
return nil return nil
} }
func (db *MemoryStateDB) GetTransientState(addr common.Address, key common.Hash) common.Hash {
panic("transient state is unsupported")
}
func (db *MemoryStateDB) SetTransientState(addr common.Address, key, value common.Hash) {
panic("transient state is unsupported")
}
func (db *MemoryStateDB) Prepare(rules params.Rules, sender, coinbase common.Address, dest *common.Address, precompiles []common.Address, txAccesses types.AccessList) {
// no-op, no transient state to prepare, nor any access-list to set/prepare
}
...@@ -105,7 +105,7 @@ func (s *L1Miner) ActL1IncludeTx(from common.Address) Action { ...@@ -105,7 +105,7 @@ func (s *L1Miner) ActL1IncludeTx(from common.Address) Action {
return return
} }
s.pendingIndices[from] = i + 1 // won't retry the tx s.pendingIndices[from] = i + 1 // won't retry the tx
s.l1BuildingState.Prepare(tx.Hash(), len(s.l1Transactions)) s.l1BuildingState.SetTxContext(tx.Hash(), len(s.l1Transactions))
receipt, err := core.ApplyTransaction(s.l1Cfg.Config, s.l1Chain, &s.l1BuildingHeader.Coinbase, receipt, err := core.ApplyTransaction(s.l1Cfg.Config, s.l1Chain, &s.l1BuildingHeader.Coinbase,
s.l1GasPool, s.l1BuildingState, s.l1BuildingHeader, tx, &s.l1BuildingHeader.GasUsed, *s.l1Chain.GetVMConfig()) s.l1GasPool, s.l1BuildingState, s.l1BuildingHeader, tx, &s.l1BuildingHeader.GasUsed, *s.l1Chain.GetVMConfig())
if err != nil { if err != nil {
...@@ -141,7 +141,7 @@ func (s *L1Miner) ActL1EndBlock(t Testing) { ...@@ -141,7 +141,7 @@ func (s *L1Miner) ActL1EndBlock(t Testing) {
if err != nil { if err != nil {
t.Fatalf("l1 state write error: %v", err) t.Fatalf("l1 state write error: %v", err)
} }
if err := s.l1BuildingState.Database().TrieDB().Commit(root, false, nil); err != nil { if err := s.l1BuildingState.Database().TrieDB().Commit(root, false); err != nil {
t.Fatalf("l1 trie write error: %v", err) t.Fatalf("l1 trie write error: %v", err)
} }
......
...@@ -192,7 +192,7 @@ func (s *L2Batcher) ActL2BatchSubmit(t Testing) { ...@@ -192,7 +192,7 @@ func (s *L2Batcher) ActL2BatchSubmit(t Testing) {
GasFeeCap: gasFeeCap, GasFeeCap: gasFeeCap,
Data: data.Bytes(), Data: data.Bytes(),
} }
gas, err := core.IntrinsicGas(rawTx.Data, nil, false, true, true) gas, err := core.IntrinsicGas(rawTx.Data, nil, false, true, true, false)
require.NoError(t, err, "need to compute intrinsic gas") require.NoError(t, err, "need to compute intrinsic gas")
rawTx.Gas = gas rawTx.Gas = gas
...@@ -275,7 +275,7 @@ func (s *L2Batcher) ActL2BatchSubmitGarbage(t Testing, kind GarbageKind) { ...@@ -275,7 +275,7 @@ func (s *L2Batcher) ActL2BatchSubmitGarbage(t Testing, kind GarbageKind) {
GasFeeCap: gasFeeCap, GasFeeCap: gasFeeCap,
Data: outputFrame, Data: outputFrame,
} }
gas, err := core.IntrinsicGas(rawTx.Data, nil, false, true, true) gas, err := core.IntrinsicGas(rawTx.Data, nil, false, true, true, false)
require.NoError(t, err, "need to compute intrinsic gas") require.NoError(t, err, "need to compute intrinsic gas")
rawTx.Gas = gas rawTx.Gas = gas
......
...@@ -3,18 +3,18 @@ package actions ...@@ -3,18 +3,18 @@ package actions
import ( import (
"errors" "errors"
"github.com/ethereum/go-ethereum/ethclient/gethclient"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/ethereum/go-ethereum/beacon/engine"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/beacon"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
geth "github.com/ethereum/go-ethereum/eth" geth "github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/eth/tracers" "github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/ethclient/gethclient"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/node"
...@@ -53,7 +53,7 @@ type L2Engine struct { ...@@ -53,7 +53,7 @@ type L2Engine struct {
l2ForceEmpty bool // when no additional txs may be processed (i.e. when sequencer drift runs out) l2ForceEmpty bool // when no additional txs may be processed (i.e. when sequencer drift runs out)
l2TxFailed []*types.Transaction // log of failed transactions which could not be included l2TxFailed []*types.Transaction // log of failed transactions which could not be included
payloadID beacon.PayloadID // ID of payload that is currently being built payloadID engine.PayloadID // ID of payload that is currently being built
failL2RPC error // mock error failL2RPC error // mock error
} }
...@@ -182,7 +182,7 @@ func (e *L2Engine) ActL2IncludeTx(from common.Address) Action { ...@@ -182,7 +182,7 @@ func (e *L2Engine) ActL2IncludeTx(from common.Address) Action {
return return
} }
e.pendingIndices[from] = i + 1 // won't retry the tx e.pendingIndices[from] = i + 1 // won't retry the tx
e.l2BuildingState.Prepare(tx.Hash(), len(e.l2Transactions)) e.l2BuildingState.SetTxContext(tx.Hash(), len(e.l2Transactions))
receipt, err := core.ApplyTransaction(e.l2Cfg.Config, e.l2Chain, &e.l2BuildingHeader.Coinbase, receipt, err := core.ApplyTransaction(e.l2Cfg.Config, e.l2Chain, &e.l2BuildingHeader.Coinbase,
e.l2GasPool, e.l2BuildingState, e.l2BuildingHeader, tx, &e.l2BuildingHeader.GasUsed, *e.l2Chain.GetVMConfig()) e.l2GasPool, e.l2BuildingState, e.l2BuildingHeader, tx, &e.l2BuildingHeader.GasUsed, *e.l2Chain.GetVMConfig())
if err != nil { if err != nil {
......
...@@ -9,16 +9,15 @@ import ( ...@@ -9,16 +9,15 @@ import (
"math/big" "math/big"
"time" "time"
"github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/beacon/engine"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/beacon"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum-optimism/optimism/op-node/eth"
) )
...@@ -35,7 +34,7 @@ var ( ...@@ -35,7 +34,7 @@ var (
) )
// computePayloadId computes a pseudo-random payloadid, based on the parameters. // computePayloadId computes a pseudo-random payloadid, based on the parameters.
func computePayloadId(headBlockHash common.Hash, params *eth.PayloadAttributes) beacon.PayloadID { func computePayloadId(headBlockHash common.Hash, params *eth.PayloadAttributes) engine.PayloadID {
// Hash // Hash
hasher := sha256.New() hasher := sha256.New()
hasher.Write(headBlockHash[:]) hasher.Write(headBlockHash[:])
...@@ -49,7 +48,7 @@ func computePayloadId(headBlockHash common.Hash, params *eth.PayloadAttributes) ...@@ -49,7 +48,7 @@ func computePayloadId(headBlockHash common.Hash, params *eth.PayloadAttributes)
hasher.Write(tx) hasher.Write(tx)
} }
_ = binary.Write(hasher, binary.BigEndian, *params.GasLimit) _ = binary.Write(hasher, binary.BigEndian, *params.GasLimit)
var out beacon.PayloadID var out engine.PayloadID
copy(out[:], hasher.Sum(nil)[:8]) copy(out[:], hasher.Sum(nil)[:8])
return out return out
} }
...@@ -96,7 +95,7 @@ func (ea *L2EngineAPI) startBlock(parent common.Hash, params *eth.PayloadAttribu ...@@ -96,7 +95,7 @@ func (ea *L2EngineAPI) startBlock(parent common.Hash, params *eth.PayloadAttribu
if err := tx.UnmarshalBinary(otx); err != nil { if err := tx.UnmarshalBinary(otx); err != nil {
return fmt.Errorf("transaction %d is not valid: %w", i, err) return fmt.Errorf("transaction %d is not valid: %w", i, err)
} }
ea.l2BuildingState.Prepare(tx.Hash(), i) ea.l2BuildingState.SetTxContext(tx.Hash(), i)
receipt, err := core.ApplyTransaction(ea.l2Cfg.Config, ea.l2Chain, &ea.l2BuildingHeader.Coinbase, receipt, err := core.ApplyTransaction(ea.l2Cfg.Config, ea.l2Chain, &ea.l2BuildingHeader.Coinbase,
ea.l2GasPool, ea.l2BuildingState, ea.l2BuildingHeader, &tx, &ea.l2BuildingHeader.GasUsed, *ea.l2Chain.GetVMConfig()) ea.l2GasPool, ea.l2BuildingState, ea.l2BuildingHeader, &tx, &ea.l2BuildingHeader.GasUsed, *ea.l2Chain.GetVMConfig())
if err != nil { if err != nil {
...@@ -125,7 +124,7 @@ func (ea *L2EngineAPI) endBlock() (*types.Block, error) { ...@@ -125,7 +124,7 @@ func (ea *L2EngineAPI) endBlock() (*types.Block, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("l2 state write error: %w", err) return nil, fmt.Errorf("l2 state write error: %w", err)
} }
if err := ea.l2BuildingState.Database().TrieDB().Commit(root, false, nil); err != nil { if err := ea.l2BuildingState.Database().TrieDB().Commit(root, false); err != nil {
return nil, fmt.Errorf("l2 trie write error: %w", err) return nil, fmt.Errorf("l2 trie write error: %w", err)
} }
return block, nil return block, nil
...@@ -135,12 +134,12 @@ func (ea *L2EngineAPI) GetPayloadV1(ctx context.Context, payloadId eth.PayloadID ...@@ -135,12 +134,12 @@ func (ea *L2EngineAPI) GetPayloadV1(ctx context.Context, payloadId eth.PayloadID
ea.log.Trace("L2Engine API request received", "method", "GetPayload", "id", payloadId) ea.log.Trace("L2Engine API request received", "method", "GetPayload", "id", payloadId)
if ea.payloadID != payloadId { if ea.payloadID != payloadId {
ea.log.Warn("unexpected payload ID requested for block building", "expected", ea.payloadID, "got", payloadId) ea.log.Warn("unexpected payload ID requested for block building", "expected", ea.payloadID, "got", payloadId)
return nil, beacon.UnknownPayload return nil, engine.UnknownPayload
} }
bl, err := ea.endBlock() bl, err := ea.endBlock()
if err != nil { if err != nil {
ea.log.Error("failed to finish block building", "err", err) ea.log.Error("failed to finish block building", "err", err)
return nil, beacon.UnknownPayload return nil, engine.UnknownPayload
} }
return eth.BlockAsPayload(bl) return eth.BlockAsPayload(bl)
} }
...@@ -180,7 +179,7 @@ func (ea *L2EngineAPI) ForkchoiceUpdatedV1(ctx context.Context, state *eth.Forkc ...@@ -180,7 +179,7 @@ func (ea *L2EngineAPI) ForkchoiceUpdatedV1(ctx context.Context, state *eth.Forkc
return &eth.ForkchoiceUpdatedResult{PayloadStatus: INVALID_TERMINAL_BLOCK, PayloadID: nil}, nil return &eth.ForkchoiceUpdatedResult{PayloadStatus: INVALID_TERMINAL_BLOCK, PayloadID: nil}, nil
} }
} }
valid := func(id *beacon.PayloadID) *eth.ForkchoiceUpdatedResult { valid := func(id *engine.PayloadID) *eth.ForkchoiceUpdatedResult {
return &eth.ForkchoiceUpdatedResult{ return &eth.ForkchoiceUpdatedResult{
PayloadStatus: eth.PayloadStatusV1{Status: eth.ExecutionValid, LatestValidHash: &state.HeadBlockHash}, PayloadStatus: eth.PayloadStatusV1{Status: eth.ExecutionValid, LatestValidHash: &state.HeadBlockHash},
PayloadID: id, PayloadID: id,
...@@ -206,10 +205,10 @@ func (ea *L2EngineAPI) ForkchoiceUpdatedV1(ctx context.Context, state *eth.Forkc ...@@ -206,10 +205,10 @@ func (ea *L2EngineAPI) ForkchoiceUpdatedV1(ctx context.Context, state *eth.Forkc
finalBlock := ea.l2Chain.GetBlockByHash(state.FinalizedBlockHash) finalBlock := ea.l2Chain.GetBlockByHash(state.FinalizedBlockHash)
if finalBlock == nil { if finalBlock == nil {
ea.log.Warn("Final block not available in database", "hash", state.FinalizedBlockHash) ea.log.Warn("Final block not available in database", "hash", state.FinalizedBlockHash)
return STATUS_INVALID, beacon.InvalidForkChoiceState.With(errors.New("final block not available in database")) return STATUS_INVALID, engine.InvalidForkChoiceState.With(errors.New("final block not available in database"))
} else if rawdb.ReadCanonicalHash(ea.l2Database, finalBlock.NumberU64()) != state.FinalizedBlockHash { } else if rawdb.ReadCanonicalHash(ea.l2Database, finalBlock.NumberU64()) != state.FinalizedBlockHash {
ea.log.Warn("Final block not in canonical chain", "number", block.NumberU64(), "hash", state.HeadBlockHash) ea.log.Warn("Final block not in canonical chain", "number", block.NumberU64(), "hash", state.HeadBlockHash)
return STATUS_INVALID, beacon.InvalidForkChoiceState.With(errors.New("final block not in canonical chain")) return STATUS_INVALID, engine.InvalidForkChoiceState.With(errors.New("final block not in canonical chain"))
} }
// Set the finalized block // Set the finalized block
ea.l2Chain.SetFinalized(finalBlock) ea.l2Chain.SetFinalized(finalBlock)
...@@ -219,11 +218,11 @@ func (ea *L2EngineAPI) ForkchoiceUpdatedV1(ctx context.Context, state *eth.Forkc ...@@ -219,11 +218,11 @@ func (ea *L2EngineAPI) ForkchoiceUpdatedV1(ctx context.Context, state *eth.Forkc
safeBlock := ea.l2Chain.GetBlockByHash(state.SafeBlockHash) safeBlock := ea.l2Chain.GetBlockByHash(state.SafeBlockHash)
if safeBlock == nil { if safeBlock == nil {
ea.log.Warn("Safe block not available in database") ea.log.Warn("Safe block not available in database")
return STATUS_INVALID, beacon.InvalidForkChoiceState.With(errors.New("safe block not available in database")) return STATUS_INVALID, engine.InvalidForkChoiceState.With(errors.New("safe block not available in database"))
} }
if rawdb.ReadCanonicalHash(ea.l2Database, safeBlock.NumberU64()) != state.SafeBlockHash { if rawdb.ReadCanonicalHash(ea.l2Database, safeBlock.NumberU64()) != state.SafeBlockHash {
ea.log.Warn("Safe block not in canonical chain") ea.log.Warn("Safe block not in canonical chain")
return STATUS_INVALID, beacon.InvalidForkChoiceState.With(errors.New("safe block not in canonical chain")) return STATUS_INVALID, engine.InvalidForkChoiceState.With(errors.New("safe block not in canonical chain"))
} }
// Set the safe block // Set the safe block
ea.l2Chain.SetSafe(safeBlock) ea.l2Chain.SetSafe(safeBlock)
...@@ -235,7 +234,7 @@ func (ea *L2EngineAPI) ForkchoiceUpdatedV1(ctx context.Context, state *eth.Forkc ...@@ -235,7 +234,7 @@ func (ea *L2EngineAPI) ForkchoiceUpdatedV1(ctx context.Context, state *eth.Forkc
err := ea.startBlock(state.HeadBlockHash, attr) err := ea.startBlock(state.HeadBlockHash, attr)
if err != nil { if err != nil {
ea.log.Error("Failed to start block building", "err", err, "noTxPool", attr.NoTxPool, "txs", len(attr.Transactions), "timestamp", attr.Timestamp) ea.log.Error("Failed to start block building", "err", err, "noTxPool", attr.NoTxPool, "txs", len(attr.Transactions), "timestamp", attr.Timestamp)
return STATUS_INVALID, beacon.InvalidPayloadAttributes.With(err) return STATUS_INVALID, engine.InvalidPayloadAttributes.With(err)
} }
return valid(&ea.payloadID), nil return valid(&ea.payloadID), nil
...@@ -249,7 +248,7 @@ func (ea *L2EngineAPI) NewPayloadV1(ctx context.Context, payload *eth.ExecutionP ...@@ -249,7 +248,7 @@ func (ea *L2EngineAPI) NewPayloadV1(ctx context.Context, payload *eth.ExecutionP
for i, tx := range payload.Transactions { for i, tx := range payload.Transactions {
txs[i] = tx txs[i] = tx
} }
block, err := beacon.ExecutableDataToBlock(beacon.ExecutableDataV1{ block, err := engine.ExecutableDataToBlock(engine.ExecutableData{
ParentHash: payload.ParentHash, ParentHash: payload.ParentHash,
FeeRecipient: payload.FeeRecipient, FeeRecipient: payload.FeeRecipient,
StateRoot: common.Hash(payload.StateRoot), StateRoot: common.Hash(payload.StateRoot),
......
...@@ -112,6 +112,7 @@ func initL1Geth(cfg *SystemConfig, genesis *core.Genesis, opts ...GethOption) (* ...@@ -112,6 +112,7 @@ func initL1Geth(cfg *SystemConfig, genesis *core.Genesis, opts ...GethOption) (*
ethConfig := &ethconfig.Config{ ethConfig := &ethconfig.Config{
NetworkId: cfg.DeployConfig.L1ChainID, NetworkId: cfg.DeployConfig.L1ChainID,
Genesis: genesis, Genesis: genesis,
Miner: miner.Config{Etherbase: cfg.DeployConfig.CliqueSignerAddress},
} }
nodeConfig := &node.Config{ nodeConfig := &node.Config{
Name: "l1-geth", Name: "l1-geth",
......
...@@ -8,9 +8,9 @@ import ( ...@@ -8,9 +8,9 @@ import (
"github.com/holiman/uint256" "github.com/holiman/uint256"
"github.com/ethereum/go-ethereum/beacon/engine"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/beacon"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
) )
...@@ -123,7 +123,7 @@ type Uint256Quantity = uint256.Int ...@@ -123,7 +123,7 @@ type Uint256Quantity = uint256.Int
type Data = hexutil.Bytes type Data = hexutil.Bytes
type PayloadID = beacon.PayloadID type PayloadID = engine.PayloadID
type ExecutionPayload struct { type ExecutionPayload struct {
ParentHash common.Hash `json:"parentHash"` ParentHash common.Hash `json:"parentHash"`
......
...@@ -16,12 +16,13 @@ import ( ...@@ -16,12 +16,13 @@ import (
) )
func randConfig() *Config { func randConfig() *Config {
rng := rand.New(rand.NewSource(1234))
randHash := func() (out [32]byte) { randHash := func() (out [32]byte) {
rand.Read(out[:]) rng.Read(out[:])
return return
} }
randAddr := func() (out common.Address) { // we need generics... randAddr := func() (out common.Address) { // we need generics...
rand.Read(out[:]) rng.Read(out[:])
return return
} }
return &Config{ return &Config{
......
...@@ -35,7 +35,15 @@ type Cheater struct { ...@@ -35,7 +35,15 @@ type Cheater struct {
func OpenGethRawDB(dataDirPath string, readOnly bool) (ethdb.Database, error) { func OpenGethRawDB(dataDirPath string, readOnly bool) (ethdb.Database, error) {
// don't use readonly mode in actual DB, it doesn't work with Geth. // don't use readonly mode in actual DB, it doesn't work with Geth.
db, err := rawdb.NewLevelDBDatabaseWithFreezer(dataDirPath, 2048, 500, filepath.Join(dataDirPath, "ancient"), "", readOnly) db, err := rawdb.Open(rawdb.OpenOptions{
Type: "leveldb",
Directory: dataDirPath,
AncientsDirectory: filepath.Join(dataDirPath, "ancient"),
Namespace: "",
Cache: 2048,
Handles: 500,
ReadOnly: readOnly,
})
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to open leveldb: %w", err) return nil, fmt.Errorf("failed to open leveldb: %w", err)
} }
...@@ -99,7 +107,7 @@ func (ch *Cheater) RunAndClose(fn HeadFn) error { ...@@ -99,7 +107,7 @@ func (ch *Cheater) RunAndClose(fn HeadFn) error {
blockHash := header.Hash() blockHash := header.Hash()
// We have to manually commit the updated state root to the database. // We have to manually commit the updated state root to the database.
if err := state.Database().TrieDB().Commit(stateRoot, true, nil); err != nil { if err := state.Database().TrieDB().Commit(stateRoot, true); err != nil {
return fmt.Errorf("error committing trie db: %w", err) return fmt.Errorf("error committing trie db: %w", err)
} }
...@@ -178,7 +186,13 @@ func StorageGet(address common.Address, key common.Hash, w io.Writer) HeadFn { ...@@ -178,7 +186,13 @@ func StorageGet(address common.Address, key common.Hash, w io.Writer) HeadFn {
// to another account (maybe even in a different database!). // to another account (maybe even in a different database!).
func StorageReadAll(address common.Address, w io.Writer) HeadFn { func StorageReadAll(address common.Address, w io.Writer) HeadFn {
return func(headState *state.StateDB) error { return func(headState *state.StateDB) error {
storage := headState.StorageTrie(address) storage, err := headState.StorageTrie(address)
if err != nil {
return fmt.Errorf("failed to open storage trie of addr %s: %w", address, err)
}
if storage == nil {
return fmt.Errorf("no storage trie in state for account %s", address)
}
iter := trie.NewIterator(storage.NodeIterator(nil)) iter := trie.NewIterator(storage.NodeIterator(nil))
for iter.Next() { for iter.Next() {
if _, err := fmt.Fprintf(w, "+ %x = %x\n", iter.Key, dbValueToHash(iter.Value)); err != nil { if _, err := fmt.Fprintf(w, "+ %x = %x\n", iter.Key, dbValueToHash(iter.Value)); err != nil {
...@@ -205,8 +219,20 @@ func dbValueToHash(enc []byte) common.Hash { ...@@ -205,8 +219,20 @@ func dbValueToHash(enc []byte) common.Hash {
// Each difference is expressed with 1 character + or - to indicate the change from a to b, followed by key = value. // Each difference is expressed with 1 character + or - to indicate the change from a to b, followed by key = value.
func StorageDiff(out io.Writer, addressA, addressB common.Address) HeadFn { func StorageDiff(out io.Writer, addressA, addressB common.Address) HeadFn {
return func(headState *state.StateDB) error { return func(headState *state.StateDB) error {
aStorage := headState.StorageTrie(addressA) aStorage, err := headState.StorageTrie(addressA)
bStorage := headState.StorageTrie(addressB) if err != nil {
return fmt.Errorf("failed to open storage trie of addr A %s: %w", addressA, err)
}
if aStorage == nil {
return fmt.Errorf("no storage trie in state for account A %s", addressA)
}
bStorage, err := headState.StorageTrie(addressB)
if err != nil {
return fmt.Errorf("failed to open storage trie of addr B %s: %w", addressB, err)
}
if bStorage == nil {
return fmt.Errorf("no storage trie in state for account B %s", addressB)
}
aIter := trie.NewIterator(aStorage.NodeIterator(nil)) aIter := trie.NewIterator(aStorage.NodeIterator(nil))
bIter := trie.NewIterator(bStorage.NodeIterator(nil)) bIter := trie.NewIterator(bStorage.NodeIterator(nil))
hasA := aIter.Next() hasA := aIter.Next()
......
...@@ -6,9 +6,9 @@ import ( ...@@ -6,9 +6,9 @@ import (
"math/big" "math/big"
"time" "time"
"github.com/ethereum/go-ethereum/beacon/engine"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/beacon"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/node"
...@@ -67,8 +67,8 @@ func headSafeFinalized(ctx context.Context, client client.RPC) (head *types.Bloc ...@@ -67,8 +67,8 @@ func headSafeFinalized(ctx context.Context, client client.RPC) (head *types.Bloc
return head, safe, finalized, nil return head, safe, finalized, nil
} }
func insertBlock(ctx context.Context, client client.RPC, payload *beacon.ExecutableDataV1) error { func insertBlock(ctx context.Context, client client.RPC, payload *engine.ExecutableData) error {
var payloadResult *beacon.PayloadStatusV1 var payloadResult *engine.PayloadStatusV1
if err := client.CallContext(ctx, &payloadResult, "engine_newPayloadV1", payload); err != nil { if err := client.CallContext(ctx, &payloadResult, "engine_newPayloadV1", payload); err != nil {
return fmt.Errorf("failed to insert block %d: %w", payload.Number, err) return fmt.Errorf("failed to insert block %d: %w", payload.Number, err)
} }
...@@ -79,9 +79,9 @@ func insertBlock(ctx context.Context, client client.RPC, payload *beacon.Executa ...@@ -79,9 +79,9 @@ func insertBlock(ctx context.Context, client client.RPC, payload *beacon.Executa
} }
func updateForkchoice(ctx context.Context, client client.RPC, head, safe, finalized common.Hash) error { func updateForkchoice(ctx context.Context, client client.RPC, head, safe, finalized common.Hash) error {
var post beacon.ForkChoiceResponse var post engine.ForkChoiceResponse
if err := client.CallContext(ctx, &post, "engine_forkchoiceUpdatedV1", if err := client.CallContext(ctx, &post, "engine_forkchoiceUpdatedV1",
beacon.ForkchoiceStateV1{ engine.ForkchoiceStateV1{
HeadBlockHash: head, HeadBlockHash: head,
SafeBlockHash: safe, SafeBlockHash: safe,
FinalizedBlockHash: finalized, FinalizedBlockHash: finalized,
...@@ -101,14 +101,14 @@ type BlockBuildingSettings struct { ...@@ -101,14 +101,14 @@ type BlockBuildingSettings struct {
BuildTime time.Duration BuildTime time.Duration
} }
func BuildBlock(ctx context.Context, client client.RPC, status *StatusData, settings *BlockBuildingSettings) (*beacon.ExecutableDataV1, error) { func BuildBlock(ctx context.Context, client client.RPC, status *StatusData, settings *BlockBuildingSettings) (*engine.ExecutableData, error) {
var pre beacon.ForkChoiceResponse var pre engine.ForkChoiceResponse
if err := client.CallContext(ctx, &pre, "engine_forkchoiceUpdatedV1", if err := client.CallContext(ctx, &pre, "engine_forkchoiceUpdatedV1",
beacon.ForkchoiceStateV1{ engine.ForkchoiceStateV1{
HeadBlockHash: status.Head.Hash, HeadBlockHash: status.Head.Hash,
SafeBlockHash: status.Safe.Hash, SafeBlockHash: status.Safe.Hash,
FinalizedBlockHash: status.Finalized.Hash, FinalizedBlockHash: status.Finalized.Hash,
}, beacon.PayloadAttributesV1{ }, engine.PayloadAttributes{
Timestamp: status.Head.Time + settings.BlockTime, Timestamp: status.Head.Time + settings.BlockTime,
Random: settings.Random, Random: settings.Random,
SuggestedFeeRecipient: settings.FeeRecipient, SuggestedFeeRecipient: settings.FeeRecipient,
...@@ -130,7 +130,7 @@ func BuildBlock(ctx context.Context, client client.RPC, status *StatusData, sett ...@@ -130,7 +130,7 @@ func BuildBlock(ctx context.Context, client client.RPC, status *StatusData, sett
case <-time.After(settings.BuildTime): case <-time.After(settings.BuildTime):
} }
var payload *beacon.ExecutableDataV1 var payload *engine.ExecutableData
if err := client.CallContext(ctx, &payload, "engine_getPayloadV1", pre.PayloadID); err != nil { if err := client.CallContext(ctx, &payload, "engine_getPayloadV1", pre.PayloadID); err != nil {
return nil, fmt.Errorf("failed to get payload %v, %d time after instructing engine to build it: %w", pre.PayloadID, settings.BuildTime, err) return nil, fmt.Errorf("failed to get payload %v, %d time after instructing engine to build it: %w", pre.PayloadID, settings.BuildTime, err)
} }
...@@ -149,7 +149,7 @@ func Auto(ctx context.Context, metrics Metricer, client client.RPC, log log.Logg ...@@ -149,7 +149,7 @@ func Auto(ctx context.Context, metrics Metricer, client client.RPC, log log.Logg
ticker := time.NewTicker(time.Millisecond * 100) ticker := time.NewTicker(time.Millisecond * 100)
defer ticker.Stop() defer ticker.Stop()
var lastPayload *beacon.ExecutableDataV1 var lastPayload *engine.ExecutableData
var buildErr error var buildErr error
for { for {
select { select {
...@@ -264,10 +264,11 @@ func Copy(ctx context.Context, copyFrom client.RPC, copyTo client.RPC) error { ...@@ -264,10 +264,11 @@ func Copy(ctx context.Context, copyFrom client.RPC, copyTo client.RPC) error {
if err != nil { if err != nil {
return err return err
} }
payload := beacon.BlockToExecutableData(copyHead) payloadEnv := engine.BlockToExecutableData(copyHead, nil)
if err := updateForkchoice(ctx, copyTo, copyHead.ParentHash(), copySafe.Hash(), copyFinalized.Hash()); err != nil { if err := updateForkchoice(ctx, copyTo, copyHead.ParentHash(), copySafe.Hash(), copyFinalized.Hash()); err != nil {
return err return err
} }
payload := payloadEnv.ExecutionPayload
if err := insertBlock(ctx, copyTo, payload); err != nil { if err := insertBlock(ctx, copyTo, payload); err != nil {
return err return err
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment