diff --git a/.dockerignore b/.dockerignore index 4048e8d5e..0ec45acbf 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,6 +1,9 @@ prover/ .git/ contracts/node_modules/ +gas-oracle/app/target/ +node/build/ +ops/docker/.devnet/ ops/reth-cross-test/ ops/publicnode/ docs/ diff --git a/contracts/tasks/deploy.ts b/contracts/tasks/deploy.ts index d8236d8ea..6b6d3ddaf 100644 --- a/contracts/tasks/deploy.ts +++ b/contracts/tasks/deploy.ts @@ -181,7 +181,10 @@ task("register") const storagePath = taskArgs.storagepath const config = hre.deployConfig const owner = await hre.ethers.provider.getSigner(); - const configuredAddresses: string[] = config.batchSubmitterAddresses; + const batchSubmitterPkList: string[] = JSON.parse(process.env.batchSubmitterPks || "[]"); + const configuredAddresses: string[] = batchSubmitterPkList.length > 0 + ? batchSubmitterPkList.map((privateKey) => new ethers.Wallet(privateKey).address) + : config.batchSubmitterAddresses; if (configuredAddresses.length === 0) { throw new Error("batchSubmitterAddresses must contain at least one work or backup submitter") } diff --git a/ops/devnet-morph/devnet/__init__.py b/ops/devnet-morph/devnet/__init__.py index c3d659785..530e52c59 100644 --- a/ops/devnet-morph/devnet/__init__.py +++ b/ops/devnet-morph/devnet/__init__.py @@ -60,6 +60,7 @@ GWEI = 1e9 ETH = GWEI * GWEI +LEGACY_GENESIS_L1_STAKING_PROXY = '0x000000000000000000000000000000000000dEaD' def compose_file_args(execution_client, cluster=False): @@ -142,7 +143,7 @@ def devnet_l1(paths, result=None): # Start layer1 services log.info('Starting layer1 services (layer1-el, layer1-cl, layer1-vc)...') run_command(['docker', 'compose', '-f', 'docker-compose-devnet.yml', 'up', '-d', - 'layer1-el', 'layer1-cl', 'layer1-vc'], check=False, cwd=paths.ops_dir, env={ + 'layer1-el', 'layer1-cl', 'layer1-vc'], cwd=paths.ops_dir, env={ 'PWD': paths.ops_dir }) @@ -202,6 +203,11 @@ def devnet_deploy(paths, args): deploy_config = read_json(devnet_cfg_orig) deploy_config['l1GenesisBlockTimestamp'] = "0x{:x}".format(int(time.time())) deploy_config['l1StartingBlockTag'] = 'earliest' + # L2Staking still has the historical OTHER_STAKING immutable, but the live + # L1Staking contract has been retired. Keep this compatibility address + # separate from Proxy__Submitter so it cannot grant staking authority to + # the batch submitter contract. + deploy_config['l1StakingProxy'] = LEGACY_GENESIS_L1_STAKING_PROXY temp_deploy_config = pjoin(paths.devnet_dir, 'deploy-config.json') write_json(temp_deploy_config, deploy_config) @@ -251,9 +257,16 @@ def devnet_deploy(paths, args): run_command([ 'npx', 'hardhat', 'initialize', '--network', 'l1', '--storagepath', paths.deployment_dir, '--concurrent', 'true' ], env={}, cwd=paths.contracts_dir) + batch_submitter_env = { + 'batchSubmitterPks': json.dumps([args.batch_submitter_private_key]), + 'DEPLOYER_PRIVATE_KEY': args.deployer_private_key, + } + run_command([ + 'npx', 'hardhat', 'fund', '--network', 'l1' + ], env=batch_submitter_env, cwd=paths.contracts_dir) run_command([ 'npx', 'hardhat', 'register', '--network', 'l1', '--storagepath', paths.deployment_dir - ], env={'batchSubmitterPks': json.dumps([args.batch_submitter_private_key])}, cwd=paths.contracts_dir) + ], env=batch_submitter_env, cwd=paths.contracts_dir) # run_command([ # 'npx', 'hardhat', 'staking', '--network', 'l1', '--storagepath', paths.deployment_dir @@ -266,21 +279,6 @@ def devnet_deploy(paths, args): addresses[d['name']] = d['address'] log.info('Passing L1 contracts address:', addresses) - log.info('Do Staking Sequencer...') - deploy_config['l2StakingAddresses'] - deploy_config['l2StakingPks'] - deploy_config['l2StakingTmKeys'] - deploy_config['l2StakingBlsKeys'] - for i in range(4): - run_command(['cast', 'send', addresses['Proxy__L1Staking'], - 'register(bytes32,bytes memory)', - deploy_config['l2StakingTmKeys'][i], - deploy_config['l2StakingBlsKeys'][i], - '--rpc-url', 'http://127.0.0.1:9545', - '--value', '1ether', - '--private-key', deploy_config['l2StakingPks'][i] - ]) - configure_l1_sequencer(paths, args, addresses, deploy_config) sequencer_upgrade_time = int((time.time() + args.sequencer_upgrade_offset_seconds) * 1000) active_sequencer_private_key = '' if args.cluster else args.sequencer_private_key @@ -310,7 +308,8 @@ def devnet_deploy(paths, args): env_data['BATCH_TIMEOUT'] = str(deploy_config['govBatchTimeout']) env_data['BATCH_SUBMITTER_PRIVATE_KEY'] = args.batch_submitter_private_key env_data['RUST_LOG'] = rust_log_level - env_data['Proxy__L1Staking'] = addresses['Proxy__L1Staking'] + env_data.pop('Proxy__L1Staking', None) + env_data.pop('MORPH_L1STAKING', None) env_data['L1_SEQUENCER_CONTRACT'] = addresses.get('Proxy__L1Sequencer', '') env_data['SEQUENCER_PRIVATE_KEY'] = args.sequencer_private_key env_data['ACTIVE_SEQUENCER_PRIVATE_KEY'] = active_sequencer_private_key @@ -326,7 +325,7 @@ def devnet_deploy(paths, args): - run_command(['docker', 'compose', *compose_file_args(args.execution_client, args.cluster), 'up', '-d'], check=False, cwd=paths.ops_dir, + run_command(['docker', 'compose', *compose_file_args(args.execution_client, args.cluster), 'up', '-d'], cwd=paths.ops_dir, env={ 'MORPH_PORTAL': addresses['Proxy__L1MessageQueueWithGasPriceOracle'], 'MORPH_ROLLUP': addresses['Proxy__Rollup'], diff --git a/ops/devnet-morph/tests/test_devnet_config.py b/ops/devnet-morph/tests/test_devnet_config.py index f18ee7dc9..7881fe7b9 100644 --- a/ops/devnet-morph/tests/test_devnet_config.py +++ b/ops/devnet-morph/tests/test_devnet_config.py @@ -10,6 +10,16 @@ class DevnetConfigTest(unittest.TestCase): + def test_root_dockerignore_excludes_generated_build_outputs(self): + dockerignore = (REPO_ROOT / ".dockerignore").read_text().splitlines() + + for generated_path in ( + "gas-oracle/app/target/", + "node/build/", + "ops/docker/.devnet/", + ): + self.assertIn(generated_path, dockerignore) + def test_node_dockerfile_caches_go_dependencies_before_source_copy(self): dockerfile = (DOCKER_DIR / "Dockerfile.l2-node").read_text() @@ -59,6 +69,7 @@ def test_tx_submitter_uses_submitter_contract_and_explicit_batch_settings(self): self.assertIn("TX_SUBMITTER_BATCH_BLOCK_INTERVAL=${BATCH_BLOCK_INTERVAL}", compose) self.assertIn("TX_SUBMITTER_BATCH_TIMEOUT=${BATCH_TIMEOUT}", compose) self.assertIn("TX_SUBMITTER_L1_PRIVATE_KEY=${BATCH_SUBMITTER_PRIVATE_KEY}", compose) + self.assertIn("until (true > /dev/tcp/morph-el-0/8545)", compose) for removed_setting in ( "TX_SUBMITTER_PRIORITY_ROLLUP", "TX_SUBMITTER_L1_STAKING_ADDRESS", @@ -72,7 +83,35 @@ def test_tx_submitter_uses_submitter_contract_and_explicit_batch_settings(self): self.assertIn("deploy_config['govBatchTimeout']", launcher) self.assertIn("batchSubmitterPks", launcher) self.assertIn("args.batch_submitter_private_key", launcher) - self.assertNotIn("MORPH_L1STAKING", launcher) + fund_command = "'npx', 'hardhat', 'fund', '--network', 'l1'" + register_command = "'npx', 'hardhat', 'register', '--network', 'l1'" + self.assertIn(fund_command, launcher) + self.assertLess(launcher.index(fund_command), launcher.index(register_command)) + self.assertIn( + "deploy_config['l1StakingProxy'] = LEGACY_GENESIS_L1_STAKING_PROXY", + launcher, + ) + self.assertIn( + "LEGACY_GENESIS_L1_STAKING_PROXY = '0x000000000000000000000000000000000000dEaD'", + launcher, + ) + self.assertNotIn("addresses['Proxy__L1Staking']", launcher) + self.assertIn("env_data.pop('Proxy__L1Staking', None)", launcher) + self.assertIn("env_data.pop('MORPH_L1STAKING', None)", launcher) + self.assertNotIn("Proxy__L1Staking", (DOCKER_DIR / ".env").read_text()) + self.assertNotIn( + "'layer1-el', 'layer1-cl', 'layer1-vc'], check=False", + launcher, + ) + self.assertNotIn( + "'up', '-d'], check=False", + launcher, + ) + + deploy_task = (REPO_ROOT / "contracts" / "tasks" / "deploy.ts").read_text() + register_task = deploy_task[deploy_task.index('task("register")'):] + self.assertIn('JSON.parse(process.env.batchSubmitterPks || "[]")', register_task) + self.assertIn("new ethers.Wallet(privateKey).address", register_task) def test_cluster_compose_defines_ha_services(self): cluster_compose = DOCKER_DIR / "docker-compose-cluster.yml" diff --git a/ops/docker/.env b/ops/docker/.env index 96de76213..9ca56d6cb 100644 --- a/ops/docker/.env +++ b/ops/docker/.env @@ -13,6 +13,5 @@ BATCH_TIMEOUT=600 BATCH_SUBMITTER_PRIVATE_KEY=0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d BUILD_GETH=l2-geth RUST_LOG=info -Proxy__L1Staking=0x5fc8d32690cc91d4c39d9d3abcbd16989f875707 BATCH_UPGRADE_TIME=0 L1_SEQUENCER_CONTRACT=0x0165878a594ca255338adfa4d48449f69242eb8f diff --git a/ops/docker/docker-compose-devnet.yml b/ops/docker/docker-compose-devnet.yml index e05d06146..f875a5bc4 100644 --- a/ops/docker/docker-compose-devnet.yml +++ b/ops/docker/docker-compose-devnet.yml @@ -271,8 +271,12 @@ services: restart: unless-stopped ports: - "6070:6060" - command: > - ./app + command: + - /bin/bash + - -c + - | + until (true > /dev/tcp/morph-el-0/8545) 2>/dev/null; do sleep 1; done + exec ./app environment: - GAS_ORACLE_L1_RPC=${L1_ETH_RPC} - GAS_ORACLE_L1_BEACON_RPC=${L1_BEACON_CHAIN_RPC}