Commit f7a591cd authored by Matthew Slipper's avatar Matthew Slipper Committed by GitHub

op-e2e: Adopt op-chain-ops (#3649)

* op-e2e: Start adopting op-chain-ops

This PR starts the process of adopting op-chain-ops in op-e2e by porting over the `Secrets` struct we use in Hive. This lets us share wallet generation code among different projects.

Adopting op-chain-ops in op-e2e improves the following:

1. Transactions now route through the correct proxy contracts.
2. There's no need to wait for a contract deployment since conracts exist in genesis.
3. We can export the test helpers in op-e2e to enable us to run similar end-to-end tests in other applications like the indexer

This is the first in a series of stacked PRs.

* op-e2e: Migrate tests to op-chain-ops

* Updates from code review

* remove unnecessary method

* Update op-e2e/setup.go
Co-authored-by: default avatarJoshua Gutow <jgutow@optimism.io>

* CR updates

* Update op-e2e/e2eutils/secrets.go
Co-authored-by: default avatarJoshua Gutow <jgutow@optimism.io>

* Update op-e2e/e2eutils/secrets.go
Co-authored-by: default avatarJoshua Gutow <jgutow@optimism.io>

* try to fix test timeout

* fix deadlock

* fix similar case
Co-authored-by: default avatarJoshua Gutow <jgutow@optimism.io>
parent b979d861
......@@ -15,9 +15,9 @@ import (
// We prefer a mnemonic rather than direct private keys to make it easier
// to export all testing keys in external tooling for use during debugging.
var DefaultMnemonicConfig = &MnemonicConfig{
Mnemonic: "test test test test test test test test test test test junk",
Deployer: "m/44'/60'/0'/0/1",
// clique signer: removed, use engine API instead
Mnemonic: "test test test test test test test test test test test junk",
Deployer: "m/44'/60'/0'/0/1",
CliqueSigner: "m/44'/60'/0'/0/2",
Proposer: "m/44'/60'/0'/0/3",
Batcher: "m/44'/60'/0'/0/4",
SequencerP2P: "m/44'/60'/0'/0/5",
......@@ -26,11 +26,13 @@ var DefaultMnemonicConfig = &MnemonicConfig{
Mallory: "m/44'/60'/0'/0/8",
}
// MnemonicConfig configures the private keys for testing purposes.
// MnemonicConfig configures the private keys for the hive testnet.
// It's json-serializable, so we can ship it to e.g. the hardhat script client.
type MnemonicConfig struct {
Mnemonic string
Deployer string
Deployer string
CliqueSigner string
// rollup actors
Proposer string
......@@ -58,6 +60,10 @@ func (m *MnemonicConfig) Secrets() (*Secrets, error) {
if err != nil {
return nil, err
}
cliqueSigner, err := wallet.PrivateKey(account(m.CliqueSigner))
if err != nil {
return nil, err
}
proposer, err := wallet.PrivateKey(account(m.Proposer))
if err != nil {
return nil, err
......@@ -85,6 +91,7 @@ func (m *MnemonicConfig) Secrets() (*Secrets, error) {
return &Secrets{
Deployer: deployer,
CliqueSigner: cliqueSigner,
Proposer: proposer,
Batcher: batcher,
SequencerP2P: sequencerP2P,
......@@ -96,7 +103,8 @@ func (m *MnemonicConfig) Secrets() (*Secrets, error) {
// Secrets bundles secp256k1 private keys for all common rollup actors for testing purposes.
type Secrets struct {
Deployer *ecdsa.PrivateKey
Deployer *ecdsa.PrivateKey
CliqueSigner *ecdsa.PrivateKey
// rollup actors
Proposer *ecdsa.PrivateKey
......@@ -122,6 +130,7 @@ func EncodePrivKey(priv *ecdsa.PrivateKey) hexutil.Bytes {
func (s *Secrets) Addresses() *Addresses {
return &Addresses{
Deployer: crypto.PubkeyToAddress(s.Deployer.PublicKey),
CliqueSigner: crypto.PubkeyToAddress(s.CliqueSigner.PublicKey),
Proposer: crypto.PubkeyToAddress(s.Proposer.PublicKey),
Batcher: crypto.PubkeyToAddress(s.Batcher.PublicKey),
SequencerP2P: crypto.PubkeyToAddress(s.SequencerP2P.PublicKey),
......@@ -133,7 +142,8 @@ func (s *Secrets) Addresses() *Addresses {
// Addresses bundles the addresses for all common rollup addresses for testing purposes.
type Addresses struct {
Deployer common.Address
Deployer common.Address
CliqueSigner common.Address
// rollup actors
Proposer common.Address
......@@ -148,8 +158,8 @@ type Addresses struct {
func (a *Addresses) All() []common.Address {
return []common.Address{
a.Batcher,
a.Deployer,
a.CliqueSigner,
a.Proposer,
a.Batcher,
a.SequencerP2P,
......
......@@ -10,7 +10,6 @@ import (
"github.com/ethereum/go-ethereum/cmd/utils"
rollupEth "github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
......@@ -23,8 +22,6 @@ import (
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/node"
hdwallet "github.com/miguelmota/go-ethereum-hdwallet"
)
func waitForTransaction(hash common.Hash, client *ethclient.Client, timeout time.Duration) (*types.Receipt, error) {
......@@ -75,25 +72,9 @@ func waitForBlock(number *big.Int, client *ethclient.Client, timeout time.Durati
}
}
func getGenesisInfo(client *ethclient.Client) (id rollupEth.BlockID, timestamp uint64) {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
block, err := client.BlockByNumber(ctx, common.Big0)
if err != nil {
panic(err)
}
return rollupEth.BlockID{Hash: block.Hash(), Number: block.NumberU64()}, block.Time()
}
func initL1Geth(cfg *SystemConfig, wallet *hdwallet.Wallet, genesis *core.Genesis) (*node.Node, *eth.Ethereum, error) {
signer := deriveAccount(wallet, cfg.CliqueSignerDerivationPath)
pk, err := wallet.PrivateKey(signer)
if err != nil {
return nil, nil, fmt.Errorf("failed to locate private key in wallet: %w", err)
}
func initL1Geth(cfg *SystemConfig, genesis *core.Genesis) (*node.Node, *eth.Ethereum, error) {
ethConfig := &ethconfig.Config{
NetworkId: cfg.L1ChainID.Uint64(),
NetworkId: cfg.DeployConfig.L1ChainID,
Genesis: genesis,
}
nodeConfig := &node.Config{
......@@ -106,7 +87,7 @@ func initL1Geth(cfg *SystemConfig, wallet *hdwallet.Wallet, genesis *core.Genesi
HTTPModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal", "engine"},
}
l1Node, l1Eth, err := createGethNode(false, nodeConfig, ethConfig, []*ecdsa.PrivateKey{pk})
l1Node, l1Eth, err := createGethNode(false, nodeConfig, ethConfig, []*ecdsa.PrivateKey{cfg.Secrets.CliqueSigner})
if err != nil {
return nil, nil, err
}
......
......@@ -2,52 +2,155 @@ package op_e2e
import (
"context"
"crypto/ecdsa"
"fmt"
"math/big"
"os"
"path"
"strings"
"testing"
"time"
bss "github.com/ethereum-optimism/optimism/op-batcher"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/metrics"
rollupNode "github.com/ethereum-optimism/optimism/op-node/node"
"github.com/ethereum-optimism/optimism/op-node/p2p"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/rollup/driver"
"github.com/ethereum-optimism/optimism/op-node/testlog"
l2os "github.com/ethereum-optimism/optimism/op-proposer"
oplog "github.com/ethereum-optimism/optimism/op-service/log"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
geth_eth "github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
mocknet "github.com/libp2p/go-libp2p/p2p/net/mock"
hdwallet "github.com/miguelmota/go-ethereum-hdwallet"
"github.com/stretchr/testify/require"
)
// deriveAddress returns the address associated derivation path for the wallet.
// It will panic if the derivation path is not correctly formatted.
func deriveAddress(w accounts.Wallet, path string) common.Address {
return deriveAccount(w, path).Address
var (
testingJWTSecret = [32]byte{123}
)
func DefaultSystemConfig(t *testing.T) SystemConfig {
secrets, err := e2eutils.DefaultMnemonicConfig.Secrets()
require.NoError(t, err)
addresses := secrets.Addresses()
return SystemConfig{
Secrets: secrets,
Premine: make(map[common.Address]*big.Int),
DeployConfig: &genesis.DeployConfig{
L1ChainID: 900,
L2ChainID: 901,
L2BlockTime: 2,
FinalizationPeriodSeconds: 60 * 60 * 24,
MaxSequencerDrift: 10,
SequencerWindowSize: 30,
ChannelTimeout: 10,
P2PSequencerAddress: addresses.SequencerP2P,
BatchInboxAddress: common.Address{0: 0x52, 19: 0xff}, // tbd
BatchSenderAddress: addresses.Batcher,
L2OutputOracleSubmissionInterval: 4,
L2OutputOracleStartingTimestamp: -1,
L2OutputOracleProposer: addresses.Proposer,
L2OutputOracleOwner: common.Address{}, // tbd
L1BlockTime: 2,
L1GenesisBlockNonce: 4660,
CliqueSignerAddress: addresses.CliqueSigner,
L1GenesisBlockTimestamp: hexutil.Uint64(time.Now().Unix()),
L1GenesisBlockGasLimit: 5_000_000,
L1GenesisBlockDifficulty: uint642big(1),
L1GenesisBlockMixHash: common.Hash{},
L1GenesisBlockCoinbase: common.Address{},
L1GenesisBlockNumber: 0,
L1GenesisBlockGasUsed: 0,
L1GenesisBlockParentHash: common.Hash{},
L1GenesisBlockBaseFeePerGas: uint642big(7),
L2GenesisBlockNonce: 0,
L2GenesisBlockExtraData: []byte{},
L2GenesisBlockGasLimit: 5_000_000,
L2GenesisBlockDifficulty: uint642big(1),
L2GenesisBlockMixHash: common.Hash{},
L2GenesisBlockCoinbase: common.Address{0: 0x12},
L2GenesisBlockNumber: 0,
L2GenesisBlockGasUsed: 0,
L2GenesisBlockParentHash: common.Hash{},
L2GenesisBlockBaseFeePerGas: uint642big(7),
OptimismBaseFeeRecipient: common.Address{0: 0x52, 19: 0xf0}, // tbd
OptimismL1FeeRecipient: common.Address{0: 0x52, 19: 0xf1},
OptimismL2FeeRecipient: common.Address{0: 0x52, 19: 0xf2}, // tbd
L2CrossDomainMessengerOwner: common.Address{0: 0x52, 19: 0xf3}, // tbd
GasPriceOracleOwner: addresses.Alice, // tbd
GasPriceOracleOverhead: 0,
GasPriceOracleScalar: 0,
GasPriceOracleDecimals: 0,
DeploymentWaitConfirmations: 1,
EIP1559Elasticity: 2,
EIP1559Denominator: 8,
FundDevAccounts: true,
},
L1InfoPredeployAddress: predeploys.L1BlockAddr,
JWTFilePath: writeDefaultJWT(t),
JWTSecret: testingJWTSecret,
Nodes: map[string]*rollupNode.Config{
"verifier": {
Driver: driver.Config{
VerifierConfDepth: 0,
SequencerConfDepth: 0,
SequencerEnabled: false,
},
L1EpochPollInterval: time.Second * 4,
},
"sequencer": {
Driver: driver.Config{
VerifierConfDepth: 0,
SequencerConfDepth: 0,
SequencerEnabled: true,
},
// Submitter PrivKey is set in system start for rollup nodes where sequencer = true
RPC: rollupNode.RPCConfig{
ListenAddr: "127.0.0.1",
ListenPort: 0,
EnableAdmin: true,
},
L1EpochPollInterval: time.Second * 4,
},
},
Loggers: map[string]log.Logger{
"verifier": testlog.Logger(t, log.LvlInfo).New("role", "verifier"),
"sequencer": testlog.Logger(t, log.LvlInfo).New("role", "sequencer"),
"batcher": testlog.Logger(t, log.LvlInfo).New("role", "batcher"),
"proposer": testlog.Logger(t, log.LvlCrit).New("role", "proposer"),
},
P2PTopology: nil, // no P2P connectivity by default
}
}
// deriveAccount returns the account associated derivation path for the wallet.
// It will panic if the derivation path is not correctly formatted.
func deriveAccount(w accounts.Wallet, path string) accounts.Account {
derivPath := hdwallet.MustParseDerivationPath(path)
account, err := w.Derive(derivPath, true)
if err != nil {
panic(err)
func writeDefaultJWT(t *testing.T) string {
// Sadly the geth node config cannot load JWT secret from memory, it has to be a file
jwtPath := path.Join(t.TempDir(), "jwt_secret")
if err := os.WriteFile(jwtPath, []byte(hexutil.Encode(testingJWTSecret[:])), 0600); err != nil {
t.Fatalf("failed to prepare jwt file for geth: %v", err)
}
return account
return jwtPath
}
type L2OOContractConfig struct {
......@@ -61,84 +164,39 @@ type DepositContractConfig struct {
}
type SystemConfig struct {
Mnemonic string
Premine map[string]int // Derivation path -> amount in ETH (not wei)
CliqueSignerDerivationPath string
L2OutputHDPath string
BatchSubmitterHDPath string
P2PSignerHDPath string
DeployerHDPath string
L1InfoPredeployAddress common.Address
Secrets *e2eutils.Secrets
L1InfoPredeployAddress common.Address
L2OOCfg L2OOContractConfig
DepositCFG DepositContractConfig
L1ChainID *big.Int
L2ChainID *big.Int
DeployConfig *genesis.DeployConfig
JWTFilePath string
JWTSecret [32]byte
Premine map[common.Address]*big.Int
Nodes map[string]*rollupNode.Config // Per node config. Don't use populate rollup.Config
Loggers map[string]log.Logger
ProposerLogger log.Logger
BatcherLogger log.Logger
RollupConfig rollup.Config // Shared rollup configs
L1BlockTime uint64
// map of outbound connections to other nodes. Node names prefixed with "~" are unconnected but linked.
// A nil map disables P2P completely.
// Any node name not in the topology will not have p2p enabled.
P2PTopology map[string][]string
BaseFeeRecipient common.Address
L1FeeRecipient common.Address
}
type System struct {
cfg SystemConfig
// Retain wallet
wallet *hdwallet.Wallet
RollupConfig *rollup.Config
// Connections to running nodes
nodes map[string]*node.Node
backends map[string]*eth.Ethereum
Clients map[string]*ethclient.Client
RolupGenesis rollup.Genesis
rollupNodes map[string]*rollupNode.OpNode
l2OutputSubmitter *l2os.L2OutputSubmitter
batchSubmitter *bss.BatchSubmitter
L2OOContractAddr common.Address
DepositContractAddr common.Address
Mocknet mocknet.Mocknet
}
func precompileAlloc() core.GenesisAlloc {
alloc := make(map[common.Address]core.GenesisAccount)
var addr [common.AddressLength]byte
for i := 0; i < 256; i++ {
addr[common.AddressLength-1] = byte(i)
alloc[addr] = core.GenesisAccount{Balance: common.Big1}
}
return alloc
}
func cliqueExtraData(w accounts.Wallet, signers []string) []byte {
// 32 Empty bytes
ret := make([]byte, 32)
// Signer addresses
for _, signer := range signers {
address := deriveAddress(w, signer)
// Was not able to automatically do this
for i := 0; i < len(address); i++ {
ret = append(ret, address[i])
}
}
// 65 Empty bytes
t := make([]byte, 65)
return append(ret, t...)
nodes map[string]*node.Node
backends map[string]*geth_eth.Ethereum
Clients map[string]*ethclient.Client
rollupNodes map[string]*rollupNode.OpNode
l2OutputSubmitter *l2os.L2OutputSubmitter
batchSubmitter *bss.BatchSubmitter
Mocknet mocknet.Mocknet
}
func (sys *System) Close() {
......@@ -158,11 +216,11 @@ func (sys *System) Close() {
sys.Mocknet.Close()
}
func (cfg SystemConfig) start() (*System, error) {
func (cfg SystemConfig) Start() (*System, error) {
sys := &System{
cfg: cfg,
nodes: make(map[string]*node.Node),
backends: make(map[string]*eth.Ethereum),
backends: make(map[string]*geth_eth.Ethereum),
Clients: make(map[string]*ethclient.Client),
rollupNodes: make(map[string]*rollupNode.OpNode),
}
......@@ -178,127 +236,69 @@ func (cfg SystemConfig) start() (*System, error) {
}
}()
// Wallet
wallet, err := hdwallet.NewFromMnemonic(cfg.Mnemonic)
if err != nil {
return nil, fmt.Errorf("Failed to create wallet: %w", err)
}
sys.wallet = wallet
// Create the BSS and set it's config here because it needs to be derived from the accounts
bssPrivKey, err := wallet.PrivateKey(accounts.Account{
URL: accounts.URL{
Path: cfg.BatchSubmitterHDPath,
},
})
l1Genesis, err := genesis.BuildL1DeveloperGenesis(cfg.DeployConfig)
if err != nil {
return nil, err
}
batchSubmitterAddr := crypto.PubkeyToAddress(bssPrivKey.PublicKey)
p2pSignerPrivKey, err := wallet.PrivateKey(accounts.Account{
URL: accounts.URL{
Path: cfg.P2PSignerHDPath,
},
})
if err != nil {
return nil, err
for addr, amount := range cfg.Premine {
if existing, ok := l1Genesis.Alloc[addr]; ok {
l1Genesis.Alloc[addr] = core.GenesisAccount{
Code: existing.Code,
Storage: existing.Storage,
Balance: amount,
Nonce: existing.Nonce,
}
} else {
l1Genesis.Alloc[addr] = core.GenesisAccount{
Balance: amount,
Nonce: 0,
}
}
}
p2pSignerAddr := crypto.PubkeyToAddress(p2pSignerPrivKey.PublicKey)
// Create the L2 Outputsubmitter Address and set it here because it needs to be derived from the accounts
l2OOSubmitter, err := wallet.PrivateKey(accounts.Account{
URL: accounts.URL{
Path: cfg.L2OutputHDPath,
},
})
l1Block := l1Genesis.ToBlock()
l2Addrs := &genesis.L2Addresses{
ProxyAdmin: predeploys.DevProxyAdminAddr,
L1StandardBridgeProxy: predeploys.DevL1StandardBridgeAddr,
L1CrossDomainMessengerProxy: predeploys.DevL1CrossDomainMessengerAddr,
}
l2Genesis, err := genesis.BuildL2DeveloperGenesis(cfg.DeployConfig, l1Block, l2Addrs)
if err != nil {
return nil, err
}
l2OutputSubmitterAddr := crypto.PubkeyToAddress(l2OOSubmitter.PublicKey)
// Genesis
eth := new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)
l1Alloc := precompileAlloc()
l2Alloc := precompileAlloc()
for path, amt := range cfg.Premine {
balance := big.NewInt(int64(amt))
balance.Mul(balance, eth)
addr := deriveAddress(wallet, path)
l1Alloc[addr] = core.GenesisAccount{Balance: balance}
l2Alloc[addr] = core.GenesisAccount{Balance: balance}
}
l2Alloc[cfg.L1InfoPredeployAddress] = core.GenesisAccount{Code: common.FromHex(bindings.L1BlockDeployedBin), Balance: common.Big0}
l2Alloc[predeploys.L2ToL1MessagePasserAddr] = core.GenesisAccount{Code: common.FromHex(bindings.L2ToL1MessagePasserDeployedBin), Balance: common.Big0}
l2Alloc[predeploys.GasPriceOracleAddr] = core.GenesisAccount{Code: common.FromHex(bindings.GasPriceOracleDeployedBin), Balance: common.Big0, Storage: map[common.Hash]common.Hash{
// storage for GasPriceOracle to have transctorPath wallet as owner
common.BigToHash(big.NewInt(0)): common.HexToHash("0x8A0A996b22B103B500Cd0F20d62dF2Ba3364D295"),
}}
genesisTimestamp := uint64(time.Now().Unix())
l1Genesis := &core.Genesis{
Config: &params.ChainConfig{
ChainID: cfg.L1ChainID,
HomesteadBlock: common.Big0,
EIP150Block: common.Big0,
EIP155Block: common.Big0,
EIP158Block: common.Big0,
ByzantiumBlock: common.Big0,
ConstantinopleBlock: common.Big0,
PetersburgBlock: common.Big0,
IstanbulBlock: common.Big0,
BerlinBlock: common.Big0,
LondonBlock: common.Big0,
Clique: &params.CliqueConfig{
Period: cfg.L1BlockTime,
Epoch: 30000,
makeRollupConfig := func() rollup.Config {
return rollup.Config{
Genesis: rollup.Genesis{
L1: eth.BlockID{
Hash: l1Block.Hash(),
Number: 0,
},
L2: eth.BlockID{
Hash: l2Genesis.ToBlock().Hash(),
Number: 0,
},
L2Time: uint64(cfg.DeployConfig.L1GenesisBlockTimestamp),
},
},
Alloc: l1Alloc,
Difficulty: common.Big1,
ExtraData: cliqueExtraData(wallet, []string{cfg.CliqueSignerDerivationPath}),
GasLimit: 5000000,
Nonce: 4660,
Timestamp: genesisTimestamp,
BaseFee: big.NewInt(7),
}
l2Genesis := &core.Genesis{
Config: &params.ChainConfig{
ChainID: cfg.L2ChainID,
HomesteadBlock: common.Big0,
EIP150Block: common.Big0,
EIP155Block: common.Big0,
EIP158Block: common.Big0,
ByzantiumBlock: common.Big0,
ConstantinopleBlock: common.Big0,
PetersburgBlock: common.Big0,
IstanbulBlock: common.Big0,
BerlinBlock: common.Big0,
LondonBlock: common.Big0,
MergeNetsplitBlock: common.Big0,
TerminalTotalDifficulty: common.Big0,
Optimism: &params.OptimismConfig{
BaseFeeRecipient: cfg.BaseFeeRecipient,
L1FeeRecipient: cfg.L1FeeRecipient,
EIP1559Elasticity: 2,
EIP1559Denominator: 8,
},
},
Alloc: l2Alloc,
Difficulty: common.Big1,
GasLimit: 5000000,
Nonce: 0,
// must be equal (or higher, while within bounds) as the L1 anchor point of the rollup
Timestamp: genesisTimestamp,
BaseFee: big.NewInt(7),
BlockTime: cfg.DeployConfig.L2BlockTime,
MaxSequencerDrift: cfg.DeployConfig.MaxSequencerDrift,
SeqWindowSize: cfg.DeployConfig.SequencerWindowSize,
ChannelTimeout: cfg.DeployConfig.ChannelTimeout,
L1ChainID: cfg.L1ChainIDBig(),
L2ChainID: cfg.L2ChainIDBig(),
P2PSequencerAddress: cfg.DeployConfig.P2PSequencerAddress,
FeeRecipientAddress: l2Genesis.Coinbase,
BatchInboxAddress: cfg.DeployConfig.BatchInboxAddress,
BatchSenderAddress: cfg.DeployConfig.BatchSenderAddress,
DepositContractAddress: predeploys.DevOptimismPortalAddr,
}
}
defaultConfig := makeRollupConfig()
sys.RollupConfig = &defaultConfig
// Initialize nodes
l1Node, l1Backend, err := initL1Geth(&cfg, wallet, l1Genesis)
l1Node, l1Backend, err := initL1Geth(&cfg, l1Genesis)
if err != nil {
return nil, err
}
......@@ -306,7 +306,7 @@ func (cfg SystemConfig) start() (*System, error) {
sys.backends["l1"] = l1Backend
for name := range cfg.Nodes {
node, backend, err := initL2Geth(name, cfg.L2ChainID, l2Genesis, cfg.JWTFilePath)
node, backend, err := initL2Geth(name, big.NewInt(int64(cfg.DeployConfig.L2ChainID)), l2Genesis, cfg.JWTFilePath)
if err != nil {
return nil, err
}
......@@ -380,79 +380,9 @@ func (cfg SystemConfig) start() (*System, error) {
sys.Clients[name] = client
}
// Rollup Genesis
l1GenesisID, _ := getGenesisInfo(l1Client)
var l2Client *ethclient.Client
for name, client := range sys.Clients {
if name != "l1" {
l2Client = client
break
}
}
l2GenesisID, l2GenesisTime := getGenesisInfo(l2Client)
sys.RolupGenesis = rollup.Genesis{
L1: l1GenesisID,
L2: l2GenesisID,
L2Time: l2GenesisTime,
}
sys.cfg.RollupConfig.Genesis = sys.RolupGenesis
sys.cfg.RollupConfig.BatchSenderAddress = batchSubmitterAddr
sys.cfg.RollupConfig.P2PSequencerAddress = p2pSignerAddr
// Deploy Deposit Contract
deployerPrivKey, err := sys.wallet.PrivateKey(accounts.Account{
URL: accounts.URL{
Path: cfg.DeployerHDPath,
},
})
_, err = waitForBlock(big.NewInt(2), l1Client, 6*time.Second*time.Duration(cfg.DeployConfig.L1BlockTime))
if err != nil {
return nil, err
}
opts, err := bind.NewKeyedTransactorWithChainID(deployerPrivKey, cfg.L1ChainID)
if err != nil {
return nil, err
}
// empty genesis L2 output.
// Technically this may need to be computed with l2.ComputeL2OutputRoot(...),
// but there are no fraud proofs active in the test.
genesisL2Output := [32]byte{}
// Deploy contracts
sys.L2OOContractAddr, _, _, err = bindings.DeployL2OutputOracle(
opts,
l1Client,
sys.cfg.L2OOCfg.SubmissionFrequency,
genesisL2Output,
sys.cfg.L2OOCfg.HistoricalTotalBlocks,
new(big.Int).SetUint64(l2GenesisID.Number),
new(big.Int).SetUint64(l2Genesis.Timestamp),
new(big.Int).SetUint64(sys.cfg.RollupConfig.BlockTime),
l2OutputSubmitterAddr,
crypto.PubkeyToAddress(deployerPrivKey.PublicKey),
)
sys.cfg.DepositCFG.L2Oracle = sys.L2OOContractAddr
if err != nil {
return nil, err
}
var tx *types.Transaction
sys.DepositContractAddr, tx, _, err = bindings.DeployOptimismPortal(
opts,
l1Client,
sys.cfg.DepositCFG.L2Oracle,
sys.cfg.DepositCFG.FinalizationPeriod,
)
if err != nil {
return nil, err
}
// Wait up to 6 blocks to deploy the Optimism portal
_, err = waitForTransaction(tx.Hash(), l1Client, 6*time.Second*time.Duration(cfg.L1BlockTime))
if err != nil {
return nil, fmt.Errorf("waiting for OptimismPortal: %w", err)
return nil, fmt.Errorf("waiting for blocks: %w", err)
}
sys.Mocknet = mocknet.New()
......@@ -509,14 +439,13 @@ func (cfg SystemConfig) start() (*System, error) {
// Rollup nodes
for name, nodeConfig := range cfg.Nodes {
c := *nodeConfig // copy
c.Rollup = sys.cfg.RollupConfig
c.Rollup.DepositContractAddress = sys.DepositContractAddr
c.Rollup = makeRollupConfig()
if p, ok := p2pNodes[name]; ok {
c.P2P = p
if c.Driver.SequencerEnabled {
c.P2PSigner = &p2p.PreparedSigner{Signer: p2p.NewLocalSigner(p2pSignerPrivKey)}
c.P2PSigner = &p2p.PreparedSigner{Signer: p2p.NewLocalSigner(cfg.Secrets.SequencerP2P)}
}
}
......@@ -559,7 +488,7 @@ func (cfg SystemConfig) start() (*System, error) {
L1EthRpc: sys.nodes["l1"].WSEndpoint(),
L2EthRpc: sys.nodes["sequencer"].WSEndpoint(),
RollupRpc: sys.rollupNodes["sequencer"].HTTPEndpoint(),
L2OOAddress: sys.L2OOContractAddr.String(),
L2OOAddress: predeploys.DevL2OutputOracleAddr.String(),
PollInterval: 50 * time.Millisecond,
NumConfirmations: 1,
ResubmissionTimeout: 3 * time.Second,
......@@ -568,8 +497,7 @@ func (cfg SystemConfig) start() (*System, error) {
Level: "info",
Format: "text",
},
Mnemonic: sys.cfg.Mnemonic,
L2OutputHDPath: sys.cfg.L2OutputHDPath,
PrivateKey: hexPriv(cfg.Secrets.Proposer),
}, "", sys.cfg.Loggers["proposer"])
if err != nil {
return nil, fmt.Errorf("unable to setup l2 output submitter: %w", err)
......@@ -586,7 +514,7 @@ func (cfg SystemConfig) start() (*System, error) {
RollupRpc: sys.rollupNodes["sequencer"].HTTPEndpoint(),
MinL1TxSize: 1,
MaxL1TxSize: 120000,
ChannelTimeout: sys.cfg.RollupConfig.ChannelTimeout,
ChannelTimeout: cfg.DeployConfig.ChannelTimeout,
PollInterval: 50 * time.Millisecond,
NumConfirmations: 1,
ResubmissionTimeout: 5 * time.Second,
......@@ -595,9 +523,8 @@ func (cfg SystemConfig) start() (*System, error) {
Level: "info",
Format: "text",
},
Mnemonic: sys.cfg.Mnemonic,
SequencerHDPath: sys.cfg.BatchSubmitterHDPath,
SequencerBatchInboxAddress: sys.cfg.RollupConfig.BatchInboxAddress.String(),
PrivateKey: hexPriv(cfg.Secrets.Batcher),
SequencerBatchInboxAddress: cfg.DeployConfig.BatchInboxAddress.String(),
}, sys.cfg.Loggers["batcher"])
if err != nil {
return nil, fmt.Errorf("failed to setup batch submitter: %w", err)
......@@ -609,3 +536,22 @@ func (cfg SystemConfig) start() (*System, error) {
return sys, nil
}
func (cfg SystemConfig) L1ChainIDBig() *big.Int {
return new(big.Int).SetUint64(cfg.DeployConfig.L1ChainID)
}
func (cfg SystemConfig) L2ChainIDBig() *big.Int {
return new(big.Int).SetUint64(cfg.DeployConfig.L2ChainID)
}
func uint642big(in uint64) *hexutil.Big {
b := new(big.Int).SetUint64(in)
hu := hexutil.Big(*b)
return &hu
}
func hexPriv(in *ecdsa.PrivateKey) string {
b := e2eutils.EncodePrivKey(in)
return hexutil.Encode(b)
}
......@@ -5,28 +5,20 @@ import (
"flag"
"fmt"
"math/big"
"os"
"path"
"testing"
"time"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/node"
rollupNode "github.com/ethereum-optimism/optimism/op-node/node"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-node/rollup/driver"
"github.com/ethereum-optimism/optimism/op-node/sources"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum-optimism/optimism/op-node/withdrawals"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
......@@ -49,119 +41,15 @@ func init() {
flag.Parse()
}
// Temporary until the contract is deployed properly instead of as a pre-deploy to a specific address
var MockDepositContractAddr = common.HexToAddress("0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001")
const (
cliqueSignerHDPath = "m/44'/60'/0'/0/0"
transactorHDPath = "m/44'/60'/0'/0/1"
l2OutputHDPath = "m/44'/60'/0'/0/3"
bssHDPath = "m/44'/60'/0'/0/4"
p2pSignerHDPath = "m/44'/60'/0'/0/5"
deployerHDPath = "m/44'/60'/0'/0/6"
)
var (
batchInboxAddress = common.Address{0xff, 0x02}
testingJWTSecret = [32]byte{123}
)
func writeDefaultJWT(t *testing.T) string {
// Sadly the geth node config cannot load JWT secret from memory, it has to be a file
jwtPath := path.Join(t.TempDir(), "jwt_secret")
if err := os.WriteFile(jwtPath, []byte(hexutil.Encode(testingJWTSecret[:])), 0600); err != nil {
t.Fatalf("failed to prepare jwt file for geth: %v", err)
}
return jwtPath
}
func defaultSystemConfig(t *testing.T) SystemConfig {
return SystemConfig{
Mnemonic: "squirrel green gallery layer logic title habit chase clog actress language enrich body plate fun pledge gap abuse mansion define either blast alien witness",
Premine: map[string]int{
cliqueSignerHDPath: 10000000,
transactorHDPath: 10000000,
l2OutputHDPath: 10000000,
bssHDPath: 10000000,
deployerHDPath: 10000000,
},
DepositCFG: DepositContractConfig{
FinalizationPeriod: big.NewInt(60 * 60 * 24),
},
L2OOCfg: L2OOContractConfig{
SubmissionFrequency: big.NewInt(4),
HistoricalTotalBlocks: big.NewInt(0),
},
L2OutputHDPath: l2OutputHDPath,
BatchSubmitterHDPath: bssHDPath,
P2PSignerHDPath: p2pSignerHDPath,
DeployerHDPath: deployerHDPath,
CliqueSignerDerivationPath: cliqueSignerHDPath,
L1InfoPredeployAddress: predeploys.L1BlockAddr,
L1BlockTime: 2,
L1ChainID: big.NewInt(900),
L2ChainID: big.NewInt(901),
JWTFilePath: writeDefaultJWT(t),
JWTSecret: testingJWTSecret,
Nodes: map[string]*rollupNode.Config{
"verifier": {
Driver: driver.Config{
VerifierConfDepth: 0,
SequencerConfDepth: 0,
SequencerEnabled: false,
},
L1EpochPollInterval: time.Second * 4,
},
"sequencer": {
Driver: driver.Config{
VerifierConfDepth: 0,
SequencerConfDepth: 0,
SequencerEnabled: true,
},
// Submitter PrivKey is set in system start for rollup nodes where sequencer = true
RPC: node.RPCConfig{
ListenAddr: "127.0.0.1",
ListenPort: 0,
EnableAdmin: true,
},
L1EpochPollInterval: time.Second * 4,
},
},
Loggers: map[string]log.Logger{
"verifier": testlog.Logger(t, log.LvlInfo).New("role", "verifier"),
"sequencer": testlog.Logger(t, log.LvlInfo).New("role", "sequencer"),
"batcher": testlog.Logger(t, log.LvlInfo).New("role", "batcher"),
"proposer": testlog.Logger(t, log.LvlCrit).New("role", "proposer"),
},
RollupConfig: rollup.Config{
BlockTime: 1,
MaxSequencerDrift: 10,
SeqWindowSize: 30,
ChannelTimeout: 10,
L1ChainID: big.NewInt(900),
L2ChainID: big.NewInt(901),
// TODO pick defaults
P2PSequencerAddress: common.Address{}, // TODO configure sequencer p2p key
FeeRecipientAddress: common.Address{0xff, 0x01},
BatchInboxAddress: batchInboxAddress,
// Batch Sender address is filled out in system start
DepositContractAddress: MockDepositContractAddr,
},
P2PTopology: nil, // no P2P connectivity by default
BaseFeeRecipient: common.HexToAddress("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"),
L1FeeRecipient: common.HexToAddress("0xDe3829A23DF1479438622a08a116E8Eb3f620BB5"),
}
}
func TestL2OutputSubmitter(t *testing.T) {
t.Parallel()
if !verboseGethNodes {
log.Root().SetHandler(log.DiscardHandler())
}
cfg := defaultSystemConfig(t)
cfg := DefaultSystemConfig(t)
sys, err := cfg.start()
sys, err := cfg.Start()
require.Nil(t, err, "Error starting up system")
defer sys.Close()
......@@ -172,7 +60,7 @@ func TestL2OutputSubmitter(t *testing.T) {
rollupClient := sources.NewRollupClient(rollupRPCClient)
// OutputOracle is already deployed
l2OutputOracle, err := bindings.NewL2OutputOracleCaller(sys.L2OOContractAddr, l1Client)
l2OutputOracle, err := bindings.NewL2OutputOracleCaller(predeploys.DevL2OutputOracleAddr, l1Client)
require.Nil(t, err)
initialOutputBlockNumber, err := l2OutputOracle.LatestBlockNumber(&bind.CallOpts{})
......@@ -184,7 +72,7 @@ func TestL2OutputSubmitter(t *testing.T) {
// for that block and subsequently reorgs to match what the verifier derives when running the
// reconcillation process.
l2Verif := sys.Clients["verifier"]
_, err = waitForBlock(big.NewInt(6), l2Verif, 10*time.Duration(cfg.RollupConfig.BlockTime)*time.Second)
_, err = waitForBlock(big.NewInt(6), l2Verif, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second)
require.Nil(t, err)
// Wait for batch submitter to update L2 output oracle.
......@@ -224,7 +112,6 @@ func TestL2OutputSubmitter(t *testing.T) {
case <-ticker.C:
}
}
}
// TestSystemE2E sets up a L1 Geth node, a rollup node, and a L2 geth node and then confirms that L1 deposits are reflected on L2.
......@@ -235,38 +122,31 @@ func TestSystemE2E(t *testing.T) {
log.Root().SetHandler(log.DiscardHandler())
}
cfg := defaultSystemConfig(t)
cfg := DefaultSystemConfig(t)
sys, err := cfg.start()
sys, err := cfg.Start()
require.Nil(t, err, "Error starting up system")
defer sys.Close()
log := testlog.Logger(t, log.LvlInfo)
log.Info("genesis", "l2", sys.cfg.RollupConfig.Genesis.L2, "l1", sys.cfg.RollupConfig.Genesis.L1, "l2_time", sys.cfg.RollupConfig.Genesis.L2Time)
log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time)
l1Client := sys.Clients["l1"]
l2Seq := sys.Clients["sequencer"]
l2Verif := sys.Clients["verifier"]
// Transactor Account
ethPrivKey, err := sys.wallet.PrivateKey(accounts.Account{
URL: accounts.URL{
Path: "m/44'/60'/0'/0/0",
},
})
require.Nil(t, err)
ethPrivKey := sys.cfg.Secrets.Alice
// Send Transaction & wait for success
fromAddr := common.HexToAddress("0x30ec912c5b1d14aa6d1cb9aa7a6682415c4f7eb0")
fromAddr := sys.cfg.Secrets.Addresses().Alice
// Find deposit contract
depositContract, err := bindings.NewOptimismPortal(sys.DepositContractAddr, l1Client)
depositContract, err := bindings.NewOptimismPortal(predeploys.DevOptimismPortalAddr, l1Client)
require.Nil(t, err)
l1Node := sys.nodes["l1"]
// Create signer
ks := l1Node.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
opts, err := bind.NewKeyStoreTransactorWithChainID(ks, ks.Accounts()[0], cfg.L1ChainID)
opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L1ChainIDBig())
require.Nil(t, err)
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
......@@ -280,13 +160,13 @@ func TestSystemE2E(t *testing.T) {
tx, err := depositContract.DepositTransaction(opts, fromAddr, common.Big0, 1_000_000, false, nil)
require.Nil(t, err, "with deposit tx")
receipt, err := waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.L1BlockTime)*time.Second)
receipt, err := waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.Nil(t, err, "Waiting for deposit tx on L1")
reconstructedDep, err := derive.UnmarshalDepositLogEvent(receipt.Logs[0])
require.NoError(t, err, "Could not reconstruct L2 Deposit")
tx = types.NewTx(reconstructedDep)
receipt, err = waitForTransaction(tx.Hash(), l2Verif, 6*time.Duration(cfg.L1BlockTime)*time.Second)
receipt, err = waitForTransaction(tx.Hash(), l2Verif, 6*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.NoError(t, err)
require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful)
......@@ -298,12 +178,12 @@ func TestSystemE2E(t *testing.T) {
diff := new(big.Int)
diff = diff.Sub(endBalance, startBalance)
require.Equal(t, diff, mintAmount, "Did not get expected balance change")
require.Equal(t, mintAmount, diff, "Did not get expected balance change")
// Submit TX to L2 sequencer node
toAddr := common.Address{0xff, 0xff}
tx = types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainID), &types.DynamicFeeTx{
ChainID: cfg.L2ChainID,
tx = types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainIDBig()), &types.DynamicFeeTx{
ChainID: cfg.L2ChainIDBig(),
Nonce: 1, // Already have deposit
To: &toAddr,
Value: big.NewInt(1_000_000_000),
......@@ -314,10 +194,10 @@ func TestSystemE2E(t *testing.T) {
err = l2Seq.SendTransaction(context.Background(), tx)
require.Nil(t, err, "Sending L2 tx to sequencer")
_, err = waitForTransaction(tx.Hash(), l2Seq, 3*time.Duration(cfg.L1BlockTime)*time.Second)
_, err = waitForTransaction(tx.Hash(), l2Seq, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.Nil(t, err, "Waiting for L2 tx on sequencer")
receipt, err = waitForTransaction(tx.Hash(), l2Verif, 10*time.Duration(cfg.L1BlockTime)*time.Second)
receipt, err = waitForTransaction(tx.Hash(), l2Verif, 10*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.Nil(t, err, "Waiting for L2 tx on verifier")
require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status, "TX should have succeeded")
......@@ -350,21 +230,21 @@ func TestConfirmationDepth(t *testing.T) {
log.Root().SetHandler(log.DiscardHandler())
}
cfg := defaultSystemConfig(t)
cfg.RollupConfig.SeqWindowSize = 4
cfg.RollupConfig.MaxSequencerDrift = 3 * cfg.L1BlockTime
cfg := DefaultSystemConfig(t)
cfg.DeployConfig.SequencerWindowSize = 4
cfg.DeployConfig.MaxSequencerDrift = 3 * cfg.DeployConfig.L1BlockTime
seqConfDepth := uint64(2)
verConfDepth := uint64(5)
cfg.Nodes["sequencer"].Driver.SequencerConfDepth = seqConfDepth
cfg.Nodes["sequencer"].Driver.VerifierConfDepth = 0
cfg.Nodes["verifier"].Driver.VerifierConfDepth = verConfDepth
sys, err := cfg.start()
sys, err := cfg.Start()
require.Nil(t, err, "Error starting up system")
defer sys.Close()
log := testlog.Logger(t, log.LvlInfo)
log.Info("genesis", "l2", sys.cfg.RollupConfig.Genesis.L2, "l1", sys.cfg.RollupConfig.Genesis.L1, "l2_time", sys.cfg.RollupConfig.Genesis.L2Time)
log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time)
l1Client := sys.Clients["l1"]
l2Seq := sys.Clients["sequencer"]
......@@ -372,7 +252,7 @@ func TestConfirmationDepth(t *testing.T) {
// Wait enough time for the sequencer to submit a block with distance from L1 head, submit it,
// and for the slower verifier to read a full sequence window and cover confirmation depth for reading and some margin
<-time.After(time.Duration((cfg.RollupConfig.SeqWindowSize+verConfDepth+3)*cfg.L1BlockTime) * time.Second)
<-time.After(time.Duration((cfg.DeployConfig.SequencerWindowSize+verConfDepth+3)*cfg.DeployConfig.L1BlockTime) * time.Second)
// within a second, get both L1 and L2 verifier and sequencer block heads
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
......@@ -388,7 +268,7 @@ func TestConfirmationDepth(t *testing.T) {
require.NoError(t, err)
require.LessOrEqual(t, info.Number+seqConfDepth, l1Head.NumberU64(), "the L2 head block should have an origin older than the L1 head block by at least the sequencer conf depth")
require.LessOrEqual(t, l2VerHead.Time()+cfg.L1BlockTime*verConfDepth, l2SeqHead.Time(), "the L2 verifier head should lag behind the sequencer without delay by at least the verifier conf depth")
require.LessOrEqual(t, l2VerHead.Time()+cfg.DeployConfig.L1BlockTime*verConfDepth, l2SeqHead.Time(), "the L2 verifier head should lag behind the sequencer without delay by at least the verifier conf depth")
}
// TestFinalize tests if L2 finalizes after sufficient time after L1 finalizes
......@@ -398,9 +278,9 @@ func TestFinalize(t *testing.T) {
log.Root().SetHandler(log.DiscardHandler())
}
cfg := defaultSystemConfig(t)
cfg := DefaultSystemConfig(t)
sys, err := cfg.start()
sys, err := cfg.Start()
require.Nil(t, err, "Error starting up system")
defer sys.Close()
......@@ -409,7 +289,7 @@ func TestFinalize(t *testing.T) {
// as configured in the extra geth lifecycle in testing setup
finalizedDistance := uint64(8)
// Wait enough time for L1 to finalize and L2 to confirm its data in finalized L1 blocks
<-time.After(time.Duration((finalizedDistance+4)*cfg.L1BlockTime) * time.Second)
<-time.After(time.Duration((finalizedDistance+4)*cfg.DeployConfig.L1BlockTime) * time.Second)
// fetch the finalizes head of geth
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
......@@ -425,9 +305,9 @@ func TestMintOnRevertedDeposit(t *testing.T) {
if !verboseGethNodes {
log.Root().SetHandler(log.DiscardHandler())
}
cfg := defaultSystemConfig(t)
cfg := DefaultSystemConfig(t)
sys, err := cfg.start()
sys, err := cfg.Start()
require.Nil(t, err, "Error starting up system")
defer sys.Close()
......@@ -435,13 +315,13 @@ func TestMintOnRevertedDeposit(t *testing.T) {
l2Verif := sys.Clients["verifier"]
// Find deposit contract
depositContract, err := bindings.NewOptimismPortal(sys.DepositContractAddr, l1Client)
depositContract, err := bindings.NewOptimismPortal(predeploys.DevOptimismPortalAddr, l1Client)
require.Nil(t, err)
l1Node := sys.nodes["l1"]
// create signer
ks := l1Node.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
opts, err := bind.NewKeyStoreTransactorWithChainID(ks, ks.Accounts()[0], cfg.L1ChainID)
opts, err := bind.NewKeyStoreTransactorWithChainID(ks, ks.Accounts()[0], cfg.L1ChainIDBig())
require.Nil(t, err)
fromAddr := opts.From
......@@ -462,13 +342,13 @@ func TestMintOnRevertedDeposit(t *testing.T) {
tx, err := depositContract.DepositTransaction(opts, toAddr, value, 1_000_000, false, nil)
require.Nil(t, err, "with deposit tx")
receipt, err := waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.L1BlockTime)*time.Second)
receipt, err := waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.Nil(t, err, "Waiting for deposit tx on L1")
reconstructedDep, err := derive.UnmarshalDepositLogEvent(receipt.Logs[0])
require.NoError(t, err, "Could not reconstruct L2 Deposit")
tx = types.NewTx(reconstructedDep)
receipt, err = waitForTransaction(tx.Hash(), l2Verif, 3*time.Duration(cfg.L1BlockTime)*time.Second)
receipt, err = waitForTransaction(tx.Hash(), l2Verif, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.NoError(t, err)
require.Equal(t, receipt.Status, types.ReceiptStatusFailed)
......@@ -503,14 +383,14 @@ func TestMissingBatchE2E(t *testing.T) {
// The test logs may look scary, but this is expected:
// 'batcher unable to publish transaction role=batcher err="insufficient funds for gas * price + value"'
cfg := defaultSystemConfig(t)
cfg := DefaultSystemConfig(t)
// small sequence window size so the test does not take as long
cfg.RollupConfig.SeqWindowSize = 4
cfg.DeployConfig.SequencerWindowSize = 4
// Specifically set batch submitter balance to stop batches from being included
cfg.Premine[bssHDPath] = 0
cfg.Premine[cfg.Secrets.Addresses().Batcher] = big.NewInt(0)
sys, err := cfg.start()
sys, err := cfg.Start()
require.Nil(t, err, "Error starting up system")
defer sys.Close()
......@@ -518,17 +398,12 @@ func TestMissingBatchE2E(t *testing.T) {
l2Verif := sys.Clients["verifier"]
// Transactor Account
ethPrivKey, err := sys.wallet.PrivateKey(accounts.Account{
URL: accounts.URL{
Path: transactorHDPath,
},
})
require.Nil(t, err)
ethPrivKey := cfg.Secrets.Alice
// Submit TX to L2 sequencer node
toAddr := common.Address{0xff, 0xff}
tx := types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainID), &types.DynamicFeeTx{
ChainID: cfg.L2ChainID,
tx := types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainIDBig()), &types.DynamicFeeTx{
ChainID: cfg.L2ChainIDBig(),
Nonce: 0,
To: &toAddr,
Value: big.NewInt(1_000_000_000),
......@@ -540,11 +415,11 @@ func TestMissingBatchE2E(t *testing.T) {
require.Nil(t, err, "Sending L2 tx to sequencer")
// Let it show up on the unsafe chain
receipt, err := waitForTransaction(tx.Hash(), l2Seq, 3*time.Duration(cfg.L1BlockTime)*time.Second)
receipt, err := waitForTransaction(tx.Hash(), l2Seq, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.Nil(t, err, "Waiting for L2 tx on sequencer")
// Wait until the block it was first included in shows up in the safe chain on the verifier
_, err = waitForBlock(receipt.BlockNumber, l2Verif, time.Duration(cfg.RollupConfig.SeqWindowSize*cfg.L1BlockTime)*time.Second)
_, err = waitForBlock(receipt.BlockNumber, l2Verif, time.Duration(sys.RollupConfig.SeqWindowSize*cfg.DeployConfig.L1BlockTime)*time.Second)
require.Nil(t, err, "Waiting for block on verifier")
// Assert that the transaction is not found on the verifier
......@@ -610,10 +485,10 @@ func TestSystemMockP2P(t *testing.T) {
log.Root().SetHandler(log.DiscardHandler())
}
cfg := defaultSystemConfig(t)
cfg := DefaultSystemConfig(t)
// slow down L1 blocks so we can see the L2 blocks arrive well before the L1 blocks do.
// Keep the seq window small so the L2 chain is started quick
cfg.L1BlockTime = 10
cfg.DeployConfig.L1BlockTime = 10
// connect the nodes
cfg.P2PTopology = map[string][]string{
......@@ -631,7 +506,7 @@ func TestSystemMockP2P(t *testing.T) {
cfg.Nodes["sequencer"].Tracer = seqTracer
cfg.Nodes["verifier"].Tracer = verifTracer
sys, err := cfg.start()
sys, err := cfg.Start()
require.Nil(t, err, "Error starting up system")
defer sys.Close()
......@@ -639,17 +514,12 @@ func TestSystemMockP2P(t *testing.T) {
l2Verif := sys.Clients["verifier"]
// Transactor Account
ethPrivKey, err := sys.wallet.PrivateKey(accounts.Account{
URL: accounts.URL{
Path: transactorHDPath,
},
})
require.Nil(t, err)
ethPrivKey := cfg.Secrets.Alice
// Submit TX to L2 sequencer node
toAddr := common.Address{0xff, 0xff}
tx := types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainID), &types.DynamicFeeTx{
ChainID: cfg.L2ChainID,
tx := types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainIDBig()), &types.DynamicFeeTx{
ChainID: cfg.L2ChainIDBig(),
Nonce: 0,
To: &toAddr,
Value: big.NewInt(1_000_000_000),
......@@ -661,11 +531,11 @@ func TestSystemMockP2P(t *testing.T) {
require.Nil(t, err, "Sending L2 tx to sequencer")
// Wait for tx to be mined on the L2 sequencer chain
receiptSeq, err := waitForTransaction(tx.Hash(), l2Seq, 3*time.Duration(cfg.RollupConfig.BlockTime)*time.Second)
receiptSeq, err := waitForTransaction(tx.Hash(), l2Seq, 3*time.Duration(sys.RollupConfig.BlockTime)*time.Second)
require.Nil(t, err, "Waiting for L2 tx on sequencer")
// Wait until the block it was first included in shows up in the safe chain on the verifier
receiptVerif, err := waitForTransaction(tx.Hash(), l2Verif, 6*time.Duration(cfg.RollupConfig.BlockTime)*time.Second)
receiptVerif, err := waitForTransaction(tx.Hash(), l2Verif, 6*time.Duration(sys.RollupConfig.BlockTime)*time.Second)
require.Nil(t, err, "Waiting for L2 tx on verifier")
require.Equal(t, receiptSeq, receiptVerif)
......@@ -684,9 +554,9 @@ func TestL1InfoContract(t *testing.T) {
log.Root().SetHandler(log.DiscardHandler())
}
cfg := defaultSystemConfig(t)
cfg := DefaultSystemConfig(t)
sys, err := cfg.start()
sys, err := cfg.Start()
require.Nil(t, err, "Error starting up system")
defer sys.Close()
......@@ -808,10 +678,10 @@ func TestWithdrawals(t *testing.T) {
log.Root().SetHandler(log.DiscardHandler())
}
cfg := defaultSystemConfig(t)
cfg.DepositCFG.FinalizationPeriod = big.NewInt(2) // 2s finalization period
cfg := DefaultSystemConfig(t)
cfg.DeployConfig.FinalizationPeriodSeconds = 2 // 2s finalization period
sys, err := cfg.start()
sys, err := cfg.Start()
require.Nil(t, err, "Error starting up system")
defer sys.Close()
......@@ -820,20 +690,15 @@ func TestWithdrawals(t *testing.T) {
l2Verif := sys.Clients["verifier"]
// Transactor Account
ethPrivKey, err := sys.wallet.PrivateKey(accounts.Account{
URL: accounts.URL{
Path: transactorHDPath,
},
})
require.Nil(t, err)
ethPrivKey := cfg.Secrets.Alice
fromAddr := crypto.PubkeyToAddress(ethPrivKey.PublicKey)
// Find deposit contract
depositContract, err := bindings.NewOptimismPortal(sys.DepositContractAddr, l1Client)
depositContract, err := bindings.NewOptimismPortal(predeploys.DevOptimismPortalAddr, l1Client)
require.Nil(t, err)
// Create L1 signer
opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L1ChainID)
opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L1ChainIDBig())
require.Nil(t, err)
// Start L2 balance
......@@ -848,7 +713,7 @@ func TestWithdrawals(t *testing.T) {
tx, err := depositContract.DepositTransaction(opts, fromAddr, common.Big0, 1_000_000, false, nil)
require.Nil(t, err, "with deposit tx")
receipt, err := waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.L1BlockTime)*time.Second)
receipt, err := waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.Nil(t, err, "Waiting for deposit tx on L1")
// Bind L2 Withdrawer Contract
......@@ -859,7 +724,7 @@ func TestWithdrawals(t *testing.T) {
reconstructedDep, err := derive.UnmarshalDepositLogEvent(receipt.Logs[0])
require.NoError(t, err, "Could not reconstruct L2 Deposit")
tx = types.NewTx(reconstructedDep)
receipt, err = waitForTransaction(tx.Hash(), l2Verif, 3*time.Duration(cfg.L1BlockTime)*time.Second)
receipt, err = waitForTransaction(tx.Hash(), l2Verif, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.NoError(t, err)
require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful)
......@@ -881,13 +746,13 @@ func TestWithdrawals(t *testing.T) {
// Intiate Withdrawal
withdrawAmount := big.NewInt(500_000_000_000)
l2opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L2ChainID)
l2opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L2ChainIDBig())
require.Nil(t, err)
l2opts.Value = withdrawAmount
tx, err = l2withdrawer.InitiateWithdrawal(l2opts, fromAddr, big.NewInt(21000), nil)
require.Nil(t, err, "sending initiate withdraw tx")
receipt, err = waitForTransaction(tx.Hash(), l2Verif, 10*time.Duration(cfg.L1BlockTime)*time.Second)
receipt, err = waitForTransaction(tx.Hash(), l2Verif, 10*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.Nil(t, err, "withdrawal initiated on L2 sequencer")
require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful, "transaction failed")
......@@ -915,9 +780,9 @@ func TestWithdrawals(t *testing.T) {
require.Nil(t, err)
// Wait for finalization and then create the Finalized Withdrawal Transaction
ctx, cancel = context.WithTimeout(context.Background(), 20*time.Duration(cfg.L1BlockTime)*time.Second)
ctx, cancel = context.WithTimeout(context.Background(), 20*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
defer cancel()
blockNumber, err := withdrawals.WaitForFinalizationPeriod(ctx, l1Client, sys.DepositContractAddr, receipt.BlockNumber)
blockNumber, err := withdrawals.WaitForFinalizationPeriod(ctx, l1Client, predeploys.DevOptimismPortalAddr, receipt.BlockNumber)
require.Nil(t, err)
ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second)
......@@ -933,7 +798,7 @@ func TestWithdrawals(t *testing.T) {
params, err := withdrawals.FinalizeWithdrawalParameters(context.Background(), l2client, tx.Hash(), header)
require.Nil(t, err)
portal, err := bindings.NewOptimismPortal(sys.DepositContractAddr, l1Client)
portal, err := bindings.NewOptimismPortal(predeploys.DevOptimismPortalAddr, l1Client)
require.Nil(t, err)
opts.Value = nil
......@@ -954,7 +819,7 @@ func TestWithdrawals(t *testing.T) {
require.Nil(t, err)
receipt, err = waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.L1BlockTime)*time.Second)
receipt, err = waitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.Nil(t, err, "finalize withdrawal")
require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status)
......@@ -984,9 +849,9 @@ func TestFees(t *testing.T) {
log.Root().SetHandler(log.DiscardHandler())
}
cfg := defaultSystemConfig(t)
cfg := DefaultSystemConfig(t)
sys, err := cfg.start()
sys, err := cfg.Start()
require.Nil(t, err, "Error starting up system")
defer sys.Close()
......@@ -994,12 +859,7 @@ func TestFees(t *testing.T) {
l2Verif := sys.Clients["verifier"]
// Transactor Account
ethPrivKey, err := sys.wallet.PrivateKey(accounts.Account{
URL: accounts.URL{
Path: transactorHDPath,
},
})
require.Nil(t, err)
ethPrivKey := cfg.Secrets.Alice
fromAddr := crypto.PubkeyToAddress(ethPrivKey.PublicKey)
// Find gaspriceoracle contract
......@@ -1007,14 +867,14 @@ func TestFees(t *testing.T) {
require.Nil(t, err)
// GPO signer
l2opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L2ChainID)
l2opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L2ChainIDBig())
require.Nil(t, err)
// Update overhead
tx, err := gpoContract.SetOverhead(l2opts, big.NewInt(2100))
require.Nil(t, err, "sending overhead update tx")
receipt, err := waitForTransaction(tx.Hash(), l2Verif, 10*time.Duration(cfg.L1BlockTime)*time.Second)
receipt, err := waitForTransaction(tx.Hash(), l2Verif, 10*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.Nil(t, err, "waiting for overhead update tx")
require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful, "transaction failed")
......@@ -1022,7 +882,7 @@ func TestFees(t *testing.T) {
tx, err = gpoContract.SetDecimals(l2opts, big.NewInt(6))
require.Nil(t, err, "sending gpo update tx")
receipt, err = waitForTransaction(tx.Hash(), l2Verif, 10*time.Duration(cfg.L1BlockTime)*time.Second)
receipt, err = waitForTransaction(tx.Hash(), l2Verif, 10*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.Nil(t, err, "waiting for gpo decimals update tx")
require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful, "transaction failed")
......@@ -1030,7 +890,7 @@ func TestFees(t *testing.T) {
tx, err = gpoContract.SetScalar(l2opts, big.NewInt(1_000_000))
require.Nil(t, err, "sending gpo update tx")
receipt, err = waitForTransaction(tx.Hash(), l2Verif, 10*time.Duration(cfg.L1BlockTime)*time.Second)
receipt, err = waitForTransaction(tx.Hash(), l2Verif, 10*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.Nil(t, err, "waiting for gpo scalar update tx")
require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful, "transaction failed")
......@@ -1048,13 +908,13 @@ func TestFees(t *testing.T) {
// BaseFee Recipient
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
baseFeeRecipientStartBalance, err := l2Seq.BalanceAt(ctx, cfg.BaseFeeRecipient, nil)
baseFeeRecipientStartBalance, err := l2Seq.BalanceAt(ctx, cfg.DeployConfig.OptimismBaseFeeRecipient, nil)
require.Nil(t, err)
// L1Fee Recipient
ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
l1FeeRecipientStartBalance, err := l2Seq.BalanceAt(ctx, cfg.L1FeeRecipient, nil)
l1FeeRecipientStartBalance, err := l2Seq.BalanceAt(ctx, cfg.DeployConfig.OptimismL2FeeRecipient, nil)
require.Nil(t, err)
// Simple transfer from signer to random account
......@@ -1066,8 +926,8 @@ func TestFees(t *testing.T) {
toAddr := common.Address{0xff, 0xff}
transferAmount := big.NewInt(1_000_000_000)
gasTip := big.NewInt(10)
tx = types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainID), &types.DynamicFeeTx{
ChainID: cfg.L2ChainID,
tx = types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L2ChainIDBig()), &types.DynamicFeeTx{
ChainID: cfg.L2ChainIDBig(),
Nonce: 3, // Already have deposit
To: &toAddr,
Value: transferAmount,
......@@ -1078,10 +938,10 @@ func TestFees(t *testing.T) {
err = l2Seq.SendTransaction(context.Background(), tx)
require.Nil(t, err, "Sending L2 tx to sequencer")
_, err = waitForTransaction(tx.Hash(), l2Seq, 3*time.Duration(cfg.L1BlockTime)*time.Second)
_, err = waitForTransaction(tx.Hash(), l2Seq, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.Nil(t, err, "Waiting for L2 tx on sequencer")
receipt, err = waitForTransaction(tx.Hash(), l2Verif, 3*time.Duration(cfg.L1BlockTime)*time.Second)
receipt, err = waitForTransaction(tx.Hash(), l2Verif, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second)
require.Nil(t, err, "Waiting for L2 tx on verifier")
require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status, "TX should have succeeded")
......@@ -1107,7 +967,7 @@ func TestFees(t *testing.T) {
ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
baseFeeRecipientEndBalance, err := l2Seq.BalanceAt(ctx, cfg.BaseFeeRecipient, header.Number)
baseFeeRecipientEndBalance, err := l2Seq.BalanceAt(ctx, cfg.DeployConfig.OptimismBaseFeeRecipient, header.Number)
require.Nil(t, err)
l1Header, err := sys.Clients["l1"].HeaderByNumber(ctx, nil)
......@@ -1115,7 +975,7 @@ func TestFees(t *testing.T) {
ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
l1FeeRecipientEndBalance, err := l2Seq.BalanceAt(ctx, cfg.L1FeeRecipient, nil)
l1FeeRecipientEndBalance, err := l2Seq.BalanceAt(ctx, cfg.DeployConfig.OptimismL2FeeRecipient, nil)
require.Nil(t, err)
// Diff fee recipient + coinbase balances
......
......@@ -477,7 +477,7 @@ func (s *state) eventLoop() {
// It waits for the reset to occur. It simply unblocks the caller rather
// than fully cancelling the reset request upon a context cancellation.
func (s *state) ResetDerivationPipeline(ctx context.Context) error {
respCh := make(chan struct{})
respCh := make(chan struct{}, 1)
select {
case <-ctx.Done():
return ctx.Err()
......@@ -492,7 +492,7 @@ func (s *state) ResetDerivationPipeline(ctx context.Context) error {
}
func (s *state) SyncStatus(ctx context.Context) (*eth.SyncStatus, error) {
respCh := make(chan eth.SyncStatus)
respCh := make(chan eth.SyncStatus, 1)
select {
case <-ctx.Done():
return nil, ctx.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