Commit 6242cf30 authored by Boyuan-Chen's avatar Boyuan-Chen Committed by GitHub

Merge branch 'develop' into support-external-client-in-op-geth-tests

parents 1be5226f 99d0ef1b
......@@ -8,8 +8,8 @@ require (
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3
github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20230920213331-413695cf7906
github.com/ethereum/go-ethereum v1.12.0
github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20230921190252-f29074de9e36
github.com/ethereum/go-ethereum v1.12.2
github.com/fsnotify/fsnotify v1.6.0
github.com/go-chi/chi/v5 v5.0.10
github.com/go-chi/docgen v1.2.0
......@@ -68,8 +68,8 @@ require (
github.com/containerd/cgroups v1.1.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/crate-crypto/go-ipa v0.0.0-20220523130400-f11357ae11c7 // indirect
github.com/crate-crypto/go-kzg-4844 v0.2.0 // indirect
github.com/crate-crypto/go-ipa v0.0.0-20230601170251-1830d0757c80 // indirect
github.com/crate-crypto/go-kzg-4844 v0.3.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
github.com/deckarep/golang-set/v2 v2.1.0 // indirect
......@@ -78,16 +78,16 @@ require (
github.com/dlclark/regexp2 v1.7.0 // indirect
github.com/docker/docker v20.10.24+incompatible // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dop251/goja v0.0.0-20230122112309-96b1610dd4f7 // indirect
github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect
github.com/elastic/gosigar v0.14.2 // indirect
github.com/ethereum/c-kzg-4844 v0.2.0 // indirect
github.com/ethereum/c-kzg-4844 v0.3.1 // indirect
github.com/fatih/color v1.7.0 // indirect
github.com/felixge/fgprof v0.9.3 // indirect
github.com/fjl/memsize v0.0.1 // indirect
github.com/flynn/noise v1.0.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect
github.com/gballet/go-verkle v0.0.0-20220902153445-097bd83b7732 // indirect
github.com/gballet/go-verkle v0.0.0-20230607174250-df487255f46b // indirect
github.com/getsentry/sentry-go v0.18.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
......@@ -106,6 +106,7 @@ require (
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-bexpr v0.1.11 // indirect
github.com/hashicorp/golang-lru/arc/v2 v2.0.5 // indirect
github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 // indirect
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
github.com/huin/goupnp v1.2.0 // indirect
github.com/influxdata/influxdb-client-go/v2 v2.4.0 // indirect
......@@ -122,7 +123,7 @@ require (
github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/karalabe/usb v0.0.2 // indirect
github.com/karalabe/usb v0.0.3-0.20230711191512-61db3e06439c // indirect
github.com/klauspost/compress v1.16.7 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/koron/go-ssdp v0.0.4 // indirect
......@@ -189,6 +190,7 @@ require (
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.uber.org/automaxprocs v1.5.2 // indirect
go.uber.org/dig v1.17.0 // indirect
go.uber.org/fx v1.20.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
......@@ -207,6 +209,6 @@ require (
rsc.io/tmplfunc v0.0.3 // indirect
)
replace github.com/ethereum/go-ethereum v1.12.0 => github.com/ethereum-optimism/op-geth v1.101200.2-rc.1.0.20230914224024-b84ba11915a0
replace github.com/ethereum/go-ethereum v1.12.2 => github.com/ethereum-optimism/op-geth v1.101200.2-rc.1.0.20230922185314-7997a6fed17c
//replace github.com/ethereum/go-ethereum v1.12.0 => ../go-ethereum
//replace github.com/ethereum/go-ethereum v1.12.2 => ../go-ethereum
This diff is collapsed.
......@@ -38,7 +38,10 @@ type DB struct {
func NewDB(dbConfig config.DBConfig) (*DB, error) {
retryStrategy := &retry.ExponentialStrategy{Min: 1000, Max: 20_000, MaxJitter: 250}
dsn := fmt.Sprintf("host=%s port=%d dbname=%s sslmode=disable", dbConfig.Host, dbConfig.Port, dbConfig.Name)
dsn := fmt.Sprintf("host=%s dbname=%s sslmode=disable", dbConfig.Host, dbConfig.Name)
if dbConfig.Port != 0 {
dsn += fmt.Sprintf(" port=%d", dbConfig.Port)
}
if dbConfig.User != "" {
dsn += fmt.Sprintf(" user=%s", dbConfig.User)
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -28,7 +28,7 @@ type MemoryStateDB struct {
func NewMemoryStateDB(genesis *core.Genesis) *MemoryStateDB {
if genesis == nil {
genesis = core.DeveloperGenesisBlock(15, 15_000_000, common.Address{})
genesis = core.DeveloperGenesisBlock(15_000_000, common.Address{})
}
return &MemoryStateDB{
......@@ -235,12 +235,16 @@ func (db *MemoryStateDB) DeleteState(addr common.Address, key common.Hash) {
db.genesis.Alloc[addr] = account
}
func (db *MemoryStateDB) Suicide(common.Address) bool {
panic("Suicide unimplemented")
func (db *MemoryStateDB) SelfDestruct(common.Address) {
panic("SelfDestruct unimplemented")
}
func (db *MemoryStateDB) HasSuicided(common.Address) bool {
panic("HasSuicided unimplemented")
func (db *MemoryStateDB) HasSelfDestructed(common.Address) bool {
panic("HasSelfDestructed unimplemented")
}
func (db *MemoryStateDB) Selfdestruct6780(common.Address) {
panic("Selfdestruct6780 unimplemented")
}
// Exist reports whether the given account exists in state.
......
......@@ -4,7 +4,7 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
......@@ -67,7 +67,7 @@ func (s *L1Miner) ActL1StartBlock(timeDelta uint64) Action {
MixDigest: common.Hash{}, // TODO: maybe randomize this (prev-randao value)
}
if s.l1Cfg.Config.IsLondon(header.Number) {
header.BaseFee = misc.CalcBaseFee(s.l1Cfg.Config, parent)
header.BaseFee = eip1559.CalcBaseFee(s.l1Cfg.Config, parent)
// At the transition, double the gas limit so the gas target is equal to the old gas limit.
if !s.l1Cfg.Config.IsLondon(parent.Number) {
header.GasLimit = parent.GasLimit * s.l1Cfg.Config.ElasticityMultiplier()
......@@ -151,7 +151,7 @@ func (s *L1Miner) ActL1EndBlock(t Testing) {
}
// Write state changes to db
root, err := s.l1BuildingState.Commit(s.l1Cfg.Config.IsEIP158(s.l1BuildingHeader.Number))
root, err := s.l1BuildingState.Commit(s.l1BuildingHeader.Number.Uint64(), s.l1Cfg.Config.IsEIP158(s.l1BuildingHeader.Number))
if err != nil {
t.Fatalf("l1 state write error: %v", err)
}
......
......@@ -161,12 +161,12 @@ func (s *L1Replica) MockL1RPCErrors(fn func() error) {
}
func (s *L1Replica) EthClient() *ethclient.Client {
cl, _ := s.node.Attach() // never errors
cl := s.node.Attach()
return ethclient.NewClient(cl)
}
func (s *L1Replica) RPCClient() client.RPC {
cl, _ := s.node.Attach() // never errors
cl := s.node.Attach()
return testutils.RPCErrFaker{
RPC: client.NewBaseRPCClient(cl),
ErrFn: func() error {
......
......@@ -132,17 +132,17 @@ func (e *engineApiBackend) Genesis() *core.Genesis {
}
func (s *L2Engine) EthClient() *ethclient.Client {
cl, _ := s.node.Attach() // never errors
cl := s.node.Attach()
return ethclient.NewClient(cl)
}
func (s *L2Engine) GethClient() *gethclient.Client {
cl, _ := s.node.Attach() // never errors
cl := s.node.Attach()
return gethclient.New(cl)
}
func (e *L2Engine) RPCClient() client.RPC {
cl, _ := e.node.Attach() // never errors
cl := e.node.Attach()
return testutils.RPCErrFaker{
RPC: client.NewBaseRPCClient(cl),
ErrFn: func() error {
......
......@@ -7,6 +7,7 @@ import (
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/log"
......@@ -94,7 +95,7 @@ func TestReorgOrphanBlock(gt *testing.T) {
miner.ActL1SetFeeRecipient(common.Address{'C'})
// note: the geth tx pool reorgLoop is too slow (responds to chain head events, but async),
// and there's no way to manually trigger runReorg, so we re-insert it ourselves.
require.NoError(t, miner.eth.TxPool().AddLocal(batchTx))
require.NoError(t, miner.eth.TxPool().Add([]*txpool.Transaction{{Tx: batchTx}}, true, true)[0])
// need to re-insert previously included tx into the block
miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t)
miner.ActL1EndBlock(t)
......@@ -173,7 +174,7 @@ func TestReorgFlipFlop(gt *testing.T) {
// re-include the batch tx that submitted L2 chain data that pointed to A0, in the new block B1
miner.ActL1SetFeeRecipient(common.Address{'B', 1})
miner.ActL1StartBlock(12)(t)
require.NoError(t, miner.eth.TxPool().AddLocal(batchTxA))
require.NoError(t, miner.eth.TxPool().Add([]*txpool.Transaction{{Tx: batchTxA}}, true, true)[0])
miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t)
miner.ActL1EndBlock(t)
......@@ -229,7 +230,7 @@ func TestReorgFlipFlop(gt *testing.T) {
miner.ActL1SetFeeRecipient(common.Address{'A', 2})
miner.ActL1StartBlock(12)(t)
require.NoError(t, miner.eth.TxPool().AddLocal(batchTxA)) // replay chain A batches, but now in A2 instead of A1
require.NoError(t, miner.eth.TxPool().Add([]*txpool.Transaction{{Tx: batchTxA}}, true, true)[0]) // replay chain A batches, but now in A2 instead of A1
miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t)
miner.ActL1EndBlock(t)
......
......@@ -720,8 +720,7 @@ func TestSystemP2PAltSync(t *testing.T) {
_, err = sys.Mocknet.ConnectPeers(sys.RollupNodes["bob"].P2P().Host().ID(), syncerNode.P2P().Host().ID())
require.NoError(t, err)
rpc, err := syncerL2Engine.Attach()
require.NoError(t, err)
rpc := syncerL2Engine.Attach()
l2Verif := ethclient.NewClient(rpc)
// It may take a while to sync, but eventually we should see the sequenced data show up
......
......@@ -242,19 +242,16 @@ var (
"The superchain-registry is experimental, and the availability of configurations may change."+
"Available networks: %s", strings.Join(chaincfg.BetaAvailableNetworks(), ", ")),
EnvVars: prefixEnvVars("BETA_EXTRA_NETWORKS"),
Hidden: true,
}
BetaRollupHalt = &cli.StringFlag{
Name: "beta.rollup.halt",
Usage: "Beta feature: opt-in option to halt on incompatible protocol version requirements of the given level (major/minor/patch/none), as signaled onchain in L1",
EnvVars: prefixEnvVars("BETA_ROLLUP_HALT"),
Hidden: true,
}
BetaRollupLoadProtocolVersions = &cli.BoolFlag{
Name: "beta.rollup.load-protocol-versions",
Usage: "Beta feature: load protocol versions from the superchain L1 ProtocolVersions contract (if available), and report in logs and metrics",
EnvVars: prefixEnvVars("BETA_ROLLUP_LOAD_PROTOCOL_VERSIONS"),
Hidden: true,
}
CanyonOverrideFlag = &cli.Uint64Flag{
Name: "override.canyon",
......
......@@ -91,12 +91,12 @@ func (n *OpNode) init(ctx context.Context, cfg *Config, snapshotLog log.Logger)
if err := n.initL1(ctx, cfg); err != nil {
return fmt.Errorf("failed to init L1: %w", err)
}
if err := n.initRuntimeConfig(ctx, cfg); err != nil {
return fmt.Errorf("failed to init the runtime config: %w", err)
}
if err := n.initL2(ctx, cfg, snapshotLog); err != nil {
return fmt.Errorf("failed to init L2: %w", err)
}
if err := n.initRuntimeConfig(ctx, cfg); err != nil { // depends on L2, to signal initial runtime values to
return fmt.Errorf("failed to init the runtime config: %w", err)
}
if err := n.initRPCSync(ctx, cfg); err != nil {
return fmt.Errorf("failed to init RPC sync: %w", err)
}
......
......@@ -222,7 +222,7 @@ func FuzzUnmarshallLogEvent(f *testing.F) {
}
state.SetBalance(from, BytesToBigInt([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}))
state.SetCode(addr, common.FromHex(bindings.OptimismPortalDeployedBin))
_, err = state.Commit(false)
_, err = state.Commit(0, false)
if err != nil {
t.Fatal(err)
}
......
......@@ -24,6 +24,7 @@ const (
pgnSepolia = 58008
zoraGoerli = 999
zoraMainnet = 7777777
labsDevnet = 997
)
// LoadOPStackRollupConfig loads the rollup configuration of the requested chain ID from the superchain-registry.
......@@ -59,13 +60,15 @@ func LoadOPStackRollupConfig(chainID uint64) (*Config, error) {
}
regolithTime := uint64(0)
// two goerli testnets test-ran Bedrock and later upgraded to Regolith.
// three goerli testnets test-ran Bedrock and later upgraded to Regolith.
// All other OP-Stack chains have Regolith enabled from the start.
switch chainID {
case baseGoerli:
regolithTime = 1683219600
case opGoerli:
regolithTime = 1679079600
case labsDevnet:
regolithTime = 1677984480
}
cfg := &Config{
......@@ -96,5 +99,12 @@ func LoadOPStackRollupConfig(chainID uint64) (*Config, error) {
DepositContractAddress: depositContractAddress,
L1SystemConfigAddress: common.Address(chConfig.SystemConfigAddr),
}
if superChain.Config.ProtocolVersionsAddr != nil { // Set optional protocol versions address
cfg.ProtocolVersionsAddress = common.Address(*superChain.Config.ProtocolVersionsAddr)
}
if chainID == labsDevnet {
cfg.ChannelTimeout = 120
cfg.MaxSequencerDrift = 1200
}
return cfg, nil
}
......@@ -136,7 +136,7 @@ func TestUpdateState(t *testing.T) {
require.Equal(t, []byte{1}, statedb.GetCode(codeAccount))
// Changes should be available under the new state root after committing
newRoot, err := statedb.Commit(false)
newRoot, err := statedb.Commit(genesisBlock.NumberU64()+1, false)
require.NoError(t, err)
err = statedb.Database().TrieDB().Commit(newRoot, true)
require.NoError(t, err)
......
......@@ -8,7 +8,7 @@ import (
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
......@@ -68,7 +68,7 @@ func NewBlockProcessorFromHeader(provider BlockDataProvider, h *types.Header) (*
return nil, fmt.Errorf("get parent state: %w", err)
}
header.Number = new(big.Int).Add(parentHeader.Number, common.Big1)
header.BaseFee = misc.CalcBaseFee(provider.Config(), parentHeader)
header.BaseFee = eip1559.CalcBaseFee(provider.Config(), parentHeader)
header.GasUsed = 0
gasPool := new(core.GasPool).AddGas(header.GasLimit)
return &BlockProcessor{
......@@ -107,7 +107,7 @@ func (b *BlockProcessor) Assemble() (*types.Block, error) {
}
func (b *BlockProcessor) Commit() error {
root, err := b.state.Commit(b.dataProvider.Config().IsEIP158(b.header.Number))
root, err := b.state.Commit(b.header.Number.Uint64(), b.dataProvider.Config().IsEIP158(b.header.Number))
if err != nil {
return fmt.Errorf("state write error: %w", err)
}
......
......@@ -294,7 +294,7 @@ func (ea *L2EngineAPI) NewPayloadV1(ctx context.Context, payload *eth.ExecutionP
BaseFeePerGas: payload.BaseFeePerGas.ToBig(),
BlockHash: payload.BlockHash,
Transactions: txs,
})
}, nil)
if err != nil {
log.Debug("Invalid NewPayload params", "params", payload, "error", err)
return &eth.PayloadStatusV1{Status: eth.ExecutionInvalidBlockHash}, nil
......
......@@ -94,11 +94,11 @@ func (p *DB) ModifyAncients(f func(ethdb.AncientWriteOp) error) (int64, error) {
panic("not supported")
}
func (p *DB) TruncateHead(n uint64) error {
func (p *DB) TruncateHead(n uint64) (uint64, error) {
panic("not supported")
}
func (p *DB) TruncateTail(n uint64) error {
func (p *DB) TruncateTail(n uint64) (uint64, error) {
panic("not supported")
}
......@@ -114,4 +114,4 @@ func (p *DB) AncientDatadir() (string, error) {
panic("not supported")
}
var _ ethdb.KeyValueStore = (*DB)(nil)
var _ ethdb.Database = (*DB)(nil)
......@@ -51,7 +51,10 @@ func ReadTrie(root common.Hash, getPreimage func(key common.Hash) []byte) []hexu
if err != nil {
panic(err)
}
iter := tr.NodeIterator(nil)
iter, err := tr.NodeIterator(nil)
if err != nil {
panic(err)
}
// With small lists the iterator seems to use 0x80 (RLP empty string, unlike the others)
// as key for item 0, causing it to come last.
......
......@@ -78,7 +78,7 @@ func (ch *Cheater) Close() error {
return ch.DB.Close()
}
type HeadFn func(headState *state.StateDB) error
type HeadFn func(header *types.Header, headState *state.StateDB) error
// RunAndClose runs the given function on the head-state, and then persists any changes (if not ReadOnly),
// and updates the blockchain headers indexes to reflect the new state-root, so geth will believe the cheat
......@@ -93,7 +93,7 @@ func (ch *Cheater) RunAndClose(fn HeadFn) error {
_ = ch.Close()
return fmt.Errorf("failed to look up head state: %w", err)
}
if err := fn(state); err != nil {
if err := fn(preHeader, state); err != nil {
_ = ch.Close()
return fmt.Errorf("failed to run state change: %w", err)
}
......@@ -102,7 +102,7 @@ func (ch *Cheater) RunAndClose(fn HeadFn) error {
}
// commit the changes, and then update the state-root
stateRoot, err := state.Commit(true)
stateRoot, err := state.Commit(preHeader.Number.Uint64()+1, true)
if err != nil {
_ = ch.Close()
return fmt.Errorf("failed to commit state change: %w", err)
......@@ -171,7 +171,7 @@ func (ch *Cheater) RunAndClose(fn HeadFn) error {
// StorageSet modifies the storage of the given address at the given key to the given value.
func StorageSet(address common.Address, key common.Hash, value common.Hash) HeadFn {
return func(headState *state.StateDB) error {
return func(_ *types.Header, headState *state.StateDB) error {
headState.SetState(address, key, value)
return nil
}
......@@ -179,7 +179,7 @@ func StorageSet(address common.Address, key common.Hash, value common.Hash) Head
// StorageGet just reads the storage of the given address at the given key.
func StorageGet(address common.Address, key common.Hash, w io.Writer) HeadFn {
return func(headState *state.StateDB) error {
return func(_ *types.Header, headState *state.StateDB) error {
value := headState.GetState(address, key)
_, err := io.WriteString(w, value.Hex())
return err
......@@ -191,7 +191,7 @@ func StorageGet(address common.Address, key common.Hash, w io.Writer) HeadFn {
// Combined with StoragePatch this allows for quick surgery of 1 account in one database,
// to another account (maybe even in a different database!).
func StorageReadAll(address common.Address, w io.Writer) HeadFn {
return func(headState *state.StateDB) error {
return func(_ *types.Header, headState *state.StateDB) error {
storage, err := headState.StorageTrie(address)
if err != nil {
return fmt.Errorf("failed to open storage trie of addr %s: %w", address, err)
......@@ -199,7 +199,11 @@ func StorageReadAll(address common.Address, w io.Writer) HeadFn {
if storage == nil {
return fmt.Errorf("no storage trie in state for account %s", address)
}
iter := trie.NewIterator(storage.NodeIterator(nil))
nodeIter, err := storage.NodeIterator(nil)
if err != nil {
return fmt.Errorf("failed to create node iterator for storage of %s: %w", address, err)
}
iter := trie.NewIterator(nodeIter)
for iter.Next() {
if _, err := fmt.Fprintf(w, "+ %x = %x\n", iter.Key, dbValueToHash(iter.Value)); err != nil {
return err
......@@ -224,7 +228,7 @@ func dbValueToHash(enc []byte) common.Hash {
// StorageDiff compares the storage of two different accounts, and writes a patch with differences.
// 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 {
return func(headState *state.StateDB) error {
return func(_ *types.Header, headState *state.StateDB) error {
aStorage, err := headState.StorageTrie(addressA)
if err != nil {
return fmt.Errorf("failed to open storage trie of addr A %s: %w", addressA, err)
......@@ -239,8 +243,16 @@ func StorageDiff(out io.Writer, addressA, addressB common.Address) HeadFn {
if bStorage == nil {
return fmt.Errorf("no storage trie in state for account B %s", addressB)
}
aIter := trie.NewIterator(aStorage.NodeIterator(nil))
bIter := trie.NewIterator(bStorage.NodeIterator(nil))
aNodeIter, err := aStorage.NodeIterator(nil)
if err != nil {
return fmt.Errorf("failed to create node iterator for storage of %s (A): %w", addressA, err)
}
bNodeIter, err := bStorage.NodeIterator(nil)
if err != nil {
return fmt.Errorf("failed to create node iterator for storage of %s (b): %w", addressB, err)
}
aIter := trie.NewIterator(aNodeIter)
bIter := trie.NewIterator(bNodeIter)
hasA := aIter.Next()
hasB := bIter.Next()
for {
......@@ -284,7 +296,7 @@ func StorageDiff(out io.Writer, addressA, addressB common.Address) HeadFn {
// Deletions are prefixed with (-) and overwrite it to a zero value.
// Comments (#) and empty lines are ignored.
func StoragePatch(patch io.Reader, address common.Address) HeadFn {
return func(headState *state.StateDB) error {
return func(head *types.Header, headState *state.StateDB) error {
s := bufio.NewScanner(patch)
i := 0
for s.Scan() {
......@@ -312,7 +324,7 @@ func StoragePatch(patch io.Reader, address common.Address) HeadFn {
}
i += 1
if i%1000 == 0 { // for every 1000 values, commit to disk
if _, err := headState.Commit(true); err != nil {
if _, err := headState.Commit(head.Number.Uint64(), true); err != nil {
return fmt.Errorf("failed to commit state to disk after patching %d entries: %w", i, err)
}
}
......@@ -329,7 +341,7 @@ type OvmOwnersConfig struct {
}
func OvmOwners(conf *OvmOwnersConfig) HeadFn {
return func(headState *state.StateDB) error {
return func(_ *types.Header, headState *state.StateDB) error {
var addressManager common.Address // Lib_AddressManager
var l1SBProxy common.Address // Proxy__OVM_L1StandardBridge
var l1XDMProxy common.Address // Proxy__OVM_L1CrossDomainMessenger
......@@ -374,21 +386,21 @@ func OvmOwners(conf *OvmOwnersConfig) HeadFn {
}
func SetBalance(addr common.Address, amount *big.Int) HeadFn {
return func(headState *state.StateDB) error {
return func(_ *types.Header, headState *state.StateDB) error {
headState.SetBalance(addr, amount)
return nil
}
}
func SetCode(addr common.Address, code hexutil.Bytes) HeadFn {
return func(headState *state.StateDB) error {
return func(_ *types.Header, headState *state.StateDB) error {
headState.SetCode(addr, code)
return nil
}
}
func SetNonce(addr common.Address, nonce uint64) HeadFn {
return func(headState *state.StateDB) error {
return func(_ *types.Header, headState *state.StateDB) error {
headState.SetNonce(addr, nonce)
return nil
}
......
......@@ -296,7 +296,7 @@ func Copy(ctx context.Context, copyFrom client.RPC, copyTo client.RPC) error {
if err != nil {
return err
}
payloadEnv := engine.BlockToExecutableData(copyHead, nil)
payloadEnv := engine.BlockToExecutableData(copyHead, nil, nil, nil, nil)
if err := updateForkchoice(ctx, copyTo, copyHead.ParentHash(), copySafe.Hash(), copyFinalized.Hash()); err != nil {
return err
}
......
......@@ -14,6 +14,7 @@ MIN_VERSIONS = {
'indexer': '0.5.0',
'op-node': '0.10.14',
'op-batcher': '0.10.14',
'op-challenger': '0.0.4',
'op-proposer': '0.10.14',
'op-ufm': '0.1.0',
'proxyd': '3.16.0'
......
......@@ -103,10 +103,10 @@ FaultDisputeGame_ResolvesCorrectly_IncorrectRoot4:test_resolvesCorrectly_succeed
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot5:test_resolvesCorrectly_succeeds() (gas: 656332)
FaultDisputeGame_Test:test_addLocalData_static_succeeds() (gas: 640567)
FaultDisputeGame_Test:test_createdAt_succeeds() (gas: 10342)
FaultDisputeGame_Test:test_extraData_succeeds() (gas: 32355)
FaultDisputeGame_Test:test_gameData_succeeds() (gas: 32782)
FaultDisputeGame_Test:test_extraData_succeeds() (gas: 32328)
FaultDisputeGame_Test:test_gameData_succeeds() (gas: 32755)
FaultDisputeGame_Test:test_gameType_succeeds() (gas: 8265)
FaultDisputeGame_Test:test_initialize_correctData_succeeds() (gas: 57739)
FaultDisputeGame_Test:test_initialize_correctData_succeeds() (gas: 57712)
FaultDisputeGame_Test:test_initialize_firstOutput_reverts() (gas: 210563)
FaultDisputeGame_Test:test_initialize_l1HeadTooOld_reverts() (gas: 228368)
FaultDisputeGame_Test:test_move_clockCorrectness_succeeds() (gas: 594268)
......
......@@ -30,6 +30,7 @@ fs_permissions = [
{ access='read-write', path='./.resource-metering.csv' },
{ access='read-write', path='./deployments/' },
{ access='read', path='./deploy-config/' },
{ access='read', path='./periphery-deploy-config/' },
{ access='read', path='./broadcast/' },
{ access='read', path = './forge-artifacts/' },
{ access='write', path='./semver-lock.json' },
......
{
"faucetAdmin": "0xf2C22a95bBA6F35545269183D8d1751a27F047F6"
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { console2 as console } from "forge-std/console2.sol";
import { Deployer } from "./Deployer.sol";
import { PeripheryDeployConfig } from "./PeripheryDeployConfig.s.sol";
import { ProxyAdmin } from "src/universal/ProxyAdmin.sol";
import { Proxy } from "src/universal/Proxy.sol";
import { Faucet } from "src/periphery/faucet/Faucet.sol";
/// @title DeployPeriphery
/// @notice Script used to deploy periphery contracts.
contract DeployPeriphery is Deployer {
PeripheryDeployConfig cfg;
/// @notice The name of the script, used to ensure the right deploy artifacts
/// are used.
function name() public pure override returns (string memory) {
return "DeployPeriphery";
}
function setUp() public override {
super.setUp();
string memory path = string.concat(vm.projectRoot(), "/periphery-deploy-config/", deploymentContext, ".json");
cfg = new PeripheryDeployConfig(path);
console.log("Deploying from %s", deployScript);
console.log("Deployment context: %s", deploymentContext);
}
/// @notice Deploy all of the periphery contracts
function run() public {
console.log("Deploying all periphery contracts");
deployProxies();
deployImplementations();
initializeFaucet();
}
/// @notice Deploy all of the proxies
function deployProxies() public {
deployProxyAdmin();
deployFaucetProxy();
}
/// @notice Deploy all of the implementations
function deployImplementations() public {
deployFaucet();
}
/// @notice Modifier that wraps a function in broadcasting.
modifier broadcast() {
vm.startBroadcast();
_;
vm.stopBroadcast();
}
/// @notice Deploy the ProxyAdmin
function deployProxyAdmin() public broadcast returns (address addr_) {
bytes32 salt = keccak256(bytes("ProxyAdmin"));
bytes32 initCodeHash = keccak256(abi.encodePacked(type(ProxyAdmin).creationCode, abi.encode(msg.sender)));
address preComputedAddress = computeCreate2Address(salt, initCodeHash);
if (preComputedAddress.code.length > 0) {
console.log("ProxyAdmin already deployed at %s", preComputedAddress);
save("ProxyAdmin", preComputedAddress);
addr_ = preComputedAddress;
} else {
ProxyAdmin admin = new ProxyAdmin{ salt: salt }({
_owner: msg.sender
});
require(admin.owner() == msg.sender);
save("ProxyAdmin", address(admin));
console.log("ProxyAdmin deployed at %s", address(admin));
addr_ = address(admin);
}
}
/// @notice Deploy the FaucetProxy
function deployFaucetProxy() public broadcast returns (address addr_) {
bytes32 salt = keccak256(bytes("FaucetProxy"));
address proxyAdmin = mustGetAddress("ProxyAdmin");
bytes32 initCodeHash = keccak256(abi.encodePacked(type(Proxy).creationCode, abi.encode(proxyAdmin)));
address preComputedAddress = computeCreate2Address(salt, initCodeHash);
if (preComputedAddress.code.length > 0) {
console.log("FaucetProxy already deployed at %s", preComputedAddress);
save("FaucetProxy", preComputedAddress);
addr_ = preComputedAddress;
} else {
Proxy proxy = new Proxy{ salt: salt }({
_admin: proxyAdmin
});
address admin = address(uint160(uint256(vm.load(address(proxy), OWNER_KEY))));
require(admin == proxyAdmin);
save("FaucetProxy", address(proxy));
console.log("FaucetProxy deployed at %s", address(proxy));
addr_ = address(proxy);
}
}
/// @notice Deploy the faucet contract.
function deployFaucet() public broadcast returns (address addr_) {
bytes32 salt = keccak256(bytes("Faucet"));
bytes32 initCodeHash = keccak256(abi.encodePacked(type(Faucet).creationCode, abi.encode(cfg.faucetAdmin())));
address preComputedAddress = computeCreate2Address(salt, initCodeHash);
if (preComputedAddress.code.length > 0) {
console.log("Faucet already deployed at %s", preComputedAddress);
save("Faucet", preComputedAddress);
addr_ = preComputedAddress;
} else {
Faucet faucet = new Faucet{ salt: salt }(cfg.faucetAdmin());
require(faucet.ADMIN() == cfg.faucetAdmin());
save("Faucet", address(faucet));
console.log("Faucet deployed at %s", address(faucet));
addr_ = address(faucet);
}
}
/// @notice Initialize the Faucet
function initializeFaucet() public broadcast {
ProxyAdmin proxyAdmin = ProxyAdmin(mustGetAddress("ProxyAdmin"));
address faucetProxy = mustGetAddress("FaucetProxy");
address faucet = mustGetAddress("Faucet");
address implementationAddress = proxyAdmin.getProxyImplementation(faucetProxy);
if (implementationAddress == faucet) {
console.log("Faucet proxy implementation already set");
} else {
proxyAdmin.upgrade({ _proxy: payable(faucetProxy), _implementation: faucet });
}
require(Faucet(payable(faucetProxy)).ADMIN() == Faucet(payable(faucet)).ADMIN());
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { Script } from "forge-std/Script.sol";
import { console2 as console } from "forge-std/console2.sol";
import { stdJson } from "forge-std/StdJson.sol";
/// @title PeripheryDeployConfig
/// @notice Represents the configuration required to deploy the periphery contracts. It is expected
/// to read the file from JSON. A future improvement would be to have fallback
/// values if they are not defined in the JSON themselves.
contract PeripheryDeployConfig is Script {
string internal _json;
address public faucetAdmin;
constructor(string memory _path) {
console.log("PeripheryDeployConfig: reading file %s", _path);
try vm.readFile(_path) returns (string memory data) {
_json = data;
} catch {
console.log("Warning: unable to read config. Do not deploy unless you are not using config.");
return;
}
faucetAdmin = stdJson.readAddress(_json, "$.faucetAdmin");
}
}
......@@ -2,6 +2,7 @@
pragma solidity 0.8.15;
import { Script } from "forge-std/Script.sol";
import { stdJson } from "forge-std/StdJson.sol";
import { console2 as console } from "forge-std/console2.sol";
contract SemverLock is Script {
......@@ -34,14 +35,23 @@ contract SemverLock is Script {
commands[2] = string.concat("echo \"", _files[i], "\"| sed -E \'s|src/.*/(.+)\\.sol|\\1|\'");
string memory contractName = string(vm.ffi(commands));
commands[0] = "bash";
commands[1] = "-c";
commands[2] = "forge config --json | jq -r .out";
string memory artifactsDir = string(vm.ffi(commands));
// Handle the case where there are multiple artifacts for a contract. This happens
// when the same contract is compiled with multiple compiler versions.
string memory contractArtifactDir = string.concat(artifactsDir, "/", contractName, ".sol");
commands[2] = string.concat(
"ls -1 --color=never ", contractArtifactDir, " | jq -R -s -c 'split(\"\n\") | map(select(length > 0))'"
);
string memory artifactFiles = string(vm.ffi(commands));
string[] memory files = stdJson.readStringArray(artifactFiles, "");
require(files.length > 0, string.concat("No artifacts found for ", contractName));
string memory fileName = files[0];
// Parse the artifact to get the contract's initcode hash.
bytes memory initCode =
vm.getCode(string.concat(artifactsDir, "/", contractName, ".sol/", contractName, ".json"));
bytes memory initCode = vm.getCode(string.concat(artifactsDir, "/", contractName, ".sol/", fileName));
// Serialize the source hash in JSON.
string memory j = vm.serializeBytes32(out, _files[i], keccak256(abi.encodePacked(fileContents, initCode)));
......
......@@ -300,7 +300,7 @@ func main() {
// Get the proof
var proof proofList
checkErr(state.Prove(predeploys.L2ToL1MessagePasserAddr.Bytes(), 0, &proof), "Error getting proof")
checkErr(state.Prove(predeploys.L2ToL1MessagePasserAddr.Bytes(), &proof), "Error getting proof")
// Get the output root
outputRoot, err := hashOutputRootProof(common.Hash{}, world.Hash(), state.Hash(), common.Hash{})
......
......@@ -18,7 +18,8 @@
"src/L2/L2StandardBridge.sol": "0xfe01bcb1ddc947b9b8a7093d0971854b9fa8d49da5bd933a3dd106167907f882",
"src/L2/L2ToL1MessagePasser.sol": "0xafc710b4d320ef450586d96a61cbd58cac814cb3b0c4fdc280eace3efdcdf321",
"src/L2/SequencerFeeVault.sol": "0xc2f733c1128d06ad60bf1e1d98c8f684a4825b11875ccdf2376ede33f5aad4e6",
"src/dispute/FaultDisputeGame.sol": "0x76e7c16431faa32e2074e6abdfe3e86f5ec90b4ac8a6b662edba8c3ce791ad80",
"src/dispute/DisputeGameFactory.sol": "0xfdfa141408d7f8de7e230ff4bef088e30d0e4d569ca743d60d292abdd21ff270",
"src/dispute/FaultDisputeGame.sol": "0xfdf4be4d6ed4bcbf6492c43fdbfd04d0c62ebee11b8fe9ee2e7757bde8f7383d",
"src/legacy/DeployerWhitelist.sol": "0xf2129ec3da75307ba8e21bc943c332bb04704642e6e263149b5c8ee92dbcb7a8",
"src/legacy/L1BlockNumber.sol": "0x30aae1fc85103476af0226b6e98c71c01feebbdc35d93401390b1ad438a37be6",
"src/legacy/LegacyMessagePasser.sol": "0x5c08b0a663cc49d30e4e38540f6aefab19ef287c3ecd31c8d8c3decd5f5bd497",
......
......@@ -3,10 +3,10 @@ pragma solidity ^0.8.15;
import { ClonesWithImmutableArgs } from "@cwia/ClonesWithImmutableArgs.sol";
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { Semver } from "src/universal/Semver.sol";
import { ISemver } from "src/universal/ISemver.sol";
import { IDisputeGame } from "./interfaces/IDisputeGame.sol";
import { IDisputeGameFactory } from "./interfaces/IDisputeGameFactory.sol";
import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol";
import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol";
import { LibGameId } from "src/dispute/lib/LibGameId.sol";
......@@ -19,7 +19,7 @@ import "src/libraries/DisputeErrors.sol";
/// time of the dispute game is packed tightly into the storage slot with the address of
/// the dispute game. This is to make offchain discoverability of playable dispute games
/// easier.
contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, Semver {
contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, ISemver {
/// @dev Allows for the creation of clone proxies with immutable arguments.
using ClonesWithImmutableArgs for address;
......@@ -36,8 +36,12 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, Semver {
/// track dispute games
GameId[] internal _disputeGameList;
/// @notice Semantic version.
/// @custom:semver 0.0.6
string public constant version = "0.0.6";
/// @notice constructs a new DisputeGameFactory contract.
constructor() OwnableUpgradeable() Semver(0, 0, 5) {
constructor() OwnableUpgradeable() {
initialize(address(0));
}
......
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
import { IDisputeGame } from "./interfaces/IDisputeGame.sol";
import { IFaultDisputeGame } from "./interfaces/IFaultDisputeGame.sol";
import { IInitializable } from "./interfaces/IInitializable.sol";
import { IBondManager } from "./interfaces/IBondManager.sol";
import { IBigStepper, IPreimageOracle } from "./interfaces/IBigStepper.sol";
import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol";
import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol";
import { IInitializable } from "src/dispute/interfaces/IInitializable.sol";
import { IBondManager } from "src/dispute/interfaces/IBondManager.sol";
import { IBigStepper, IPreimageOracle } from "src/dispute/interfaces/IBigStepper.sol";
import { L2OutputOracle } from "src/L1/L2OutputOracle.sol";
import { BlockOracle } from "./BlockOracle.sol";
import { BlockOracle } from "src/dispute/BlockOracle.sol";
import { Clone } from "src/libraries/Clone.sol";
import { Types } from "src/libraries/Types.sol";
import { Semver } from "src/universal/Semver.sol";
import { LibHashing } from "./lib/LibHashing.sol";
import { LibPosition } from "./lib/LibPosition.sol";
import { LibClock } from "./lib/LibClock.sol";
import { ISemver } from "src/universal/ISemver.sol";
import { LibHashing } from "src/dispute/lib/LibHashing.sol";
import { LibPosition } from "src/dispute/lib/LibPosition.sol";
import { LibClock } from "src/dispute/lib/LibClock.sol";
import "src/libraries/DisputeTypes.sol";
import "src/libraries/DisputeErrors.sol";
/// @title FaultDisputeGame
/// @notice An implementation of the `IFaultDisputeGame` interface.
contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver {
////////////////////////////////////////////////////////////////
// State Vars //
////////////////////////////////////////////////////////////////
......@@ -81,6 +81,10 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
/// @notice Indicates whether the subgame rooted at the root claim has been resolved.
bool internal subgameAtRootResolved;
/// @notice Semantic version.
/// @custom:semver 0.0.10
string public constant version = "0.0.10";
/// @param _gameType The type ID of the game.
/// @param _absolutePrestate The absolute prestate of the instruction trace.
/// @param _maxGameDepth The maximum depth of bisection.
......@@ -91,7 +95,6 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
/// @param _blockOracle The block oracle, used for loading block hashes further back
/// than the `BLOCKHASH` opcode allows as well as their estimated
/// timestamps.
/// @custom:semver 0.0.9
constructor(
GameType _gameType,
Claim _absolutePrestate,
......@@ -100,9 +103,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
IBigStepper _vm,
L2OutputOracle _l2oo,
BlockOracle _blockOracle
)
Semver(0, 0, 9)
{
) {
GAME_TYPE = _gameType;
ABSOLUTE_PRESTATE = _absolutePrestate;
MAX_GAME_DEPTH = _maxGameDepth;
......
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