diff --git a/README.md b/README.md index 748388c..ed6925f 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,8 @@ abstraction infrastructure (a bundler and a paymaster). The current version of simple-op-stack-rollup deploys software pinned to the following releases: -- Optimism Monorepo: [`op-node/v1.3.1 `](https://github.com/ethereum-optimism/optimism/releases/tag/op-node%2Fv1.3.1) (+ [a few patches](setup.py)) -- op-geth: [`v1.101304.1`](https://github.com/ethereum-optimism/op-geth/releases/tag/v1.101304.1) +- Optimism Monorepo: [`v1.9.3`](https://github.com/ethereum-optimism/optimism/releases/tag/v1.9.3) +- op-geth: [`v1.101408.0`](https://github.com/ethereum-optimism/op-geth/releases/tag/v1.101408.0) ## Prerequisites @@ -29,7 +29,7 @@ The current version of simple-op-stack-rollup deploys software pinned to the fol You also need the following installed, `rollop` will warn you if these are missing: -- Some common command line utilities: `make`, `curl`, `tar`, `awk` and `grep`. +- Some common command line utilities: `make`, `curl`, `tar`, `awk`, `just` and `grep`. - [`logrotate`](https://github.com/logrotate/logrotate) - `sudo apt install logrotate` on Debian-based systems - `brew install logrotate` on macOS with Homebrew diff --git a/deploy_config.py b/deploy_config.py index a339ddb..e80126d 100644 --- a/deploy_config.py +++ b/deploy_config.py @@ -87,7 +87,7 @@ def generate_deploy_config(config: Config, pre_l1_genesis=False): deploy_config["proxyAdminOwner"] = config.admin_account deploy_config["finalSystemOwner"] = config.admin_account - deploy_config["portalGuardian"] = config.admin_account + deploy_config["superchainConfigGuardian"] = config.admin_account deploy_config["baseFeeVaultRecipient"] = config.admin_account deploy_config["l1FeeVaultRecipient"] = config.admin_account diff --git a/deploy_config_templates.py b/deploy_config_templates.py index bb3ad80..67a3481 100644 --- a/deploy_config_templates.py +++ b/deploy_config_templates.py @@ -139,7 +139,6 @@ "proxyAdminOwner": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720", "finalSystemOwner": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720", - "portalGuardian": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720", "baseFeeVaultRecipient": "0x14dC79964da2C08b23698B3D3cc7Ca32193d9955", "l1FeeVaultRecipient": "0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f", @@ -165,9 +164,9 @@ "baseFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", "l1FeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", "sequencerFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", - "baseFeeVaultWithdrawalNetwork": "remote", - "l1FeeVaultWithdrawalNetwork": "remote", - "sequencerFeeVaultWithdrawalNetwork": "remote", + "baseFeeVaultWithdrawalNetwork": 0, + "l1FeeVaultWithdrawalNetwork": 0, + "sequencerFeeVaultWithdrawalNetwork": 0, "fundDevAccounts": True, @@ -179,13 +178,20 @@ "eip1559Elasticity": 6, "l2GenesisRegolithTimeOffset": "0x0", - "l2GenesisSpanBatchTimeOffset": "0x0", "l2GenesisCanyonTimeOffset": "0x40", "faultGameAbsolutePrestate": "0x03c7ae758795765c6664a5d39bf63841c71ff191e9189522bad8ebff5d4eca98", - "faultGameMaxDepth": 30, - "faultGameMaxDuration": 1200, + "faultGameMaxDepth": 50, + "faultGameClockExtension": 0, + "faultGameMaxClockDuration": 1200, + "faultGameGenesisBlock": 0, + "faultGameGenesisOutputRoot": "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF", + "faultGameSplitDepth": 14, + "faultGameWithdrawalDelay": 604800, + + "preimageOracleMinProposalSize": 10000, + "preimageOracleChallengePeriod": 120, "systemConfigStartBlock": 0, "requiredProtocolVersion": diff --git a/deps.py b/deps.py index cdc2f91..45e163b 100644 --- a/deps.py +++ b/deps.py @@ -137,6 +137,11 @@ def _check_basic_prerequisites(): "logrotate is not installed. Please install it from your package manager.\n" "e.g. `brew install logrotate` or `sudo apt install logrotate`") + if shutil.which("just") is None: + raise Exception( + "just is not installed. Please install it from your package manager.\n" + "e.g. `brew install just` or see https://github.com/casey/just for more installation options") + #################################################################################################### @@ -408,20 +413,24 @@ def get_foundry_version(): It's possible to have multiple releases on the same day, but these are commit-tagged, so we can't compare them. """ - version_blob = lib.run("get forge version", "forge --version") + try: + version_blob = lib.run("get forge version", "forge --version") + except Exception as e: + print(e) + version_blob = "" match = re.search(r"^forge \d+\.\d+\.\d+ \([0-9a-fA-F]+ (\d{4}-\d\d-\d\d)", version_blob) return None if match is None else match.group(1) #################################################################################################### -FOUNDRY_VERSION = "2023-11-02" +FOUNDRY_VERSION = "2024-06-02" """ Required version of forge. We're locking down foundry to a specific version, as new versions can introduce serious regressions, and have done so in the past. """ -FOUNDRY_INSTALL_TAG = "nightly-09fe3e041369a816365a020f715ad6f94dbce9f2" +FOUNDRY_INSTALL_TAG = "nightly-5ac78a9cd4b94dc53d1fe5e0f42372b28b5a7559" """ The tag of the foundry release to install if needed. """ diff --git a/devenv.sh b/devenv.sh index e7d251a..2b0d412 100755 --- a/devenv.sh +++ b/devenv.sh @@ -65,6 +65,15 @@ install_dev_dependencies() { else echo "autopep8 version $autopep8_version" fi + + # Check if rust-just==1.36.0 is installed, otherwise install it + just_version=$(just --version | awk '{print $2}') + if [ "$just_version" = "1.36.0" ]; then + echo "just version is $just_version" + else + echo "just version is $just_version, but 1.36.0 is required" + pip3 install rust-just==1.36.0 + fi } if check_python_version; then diff --git a/l1.py b/l1.py index 6b1f09a..9bd85e3 100644 --- a/l1.py +++ b/l1.py @@ -3,7 +3,6 @@ on an L1 blockchain (for now only devnet, but in the future, any kind of L1). """ -import json import os from subprocess import Popen @@ -70,14 +69,6 @@ def _create_devnet_l1_genesis_allocs(config: Config): geth = _start_temporary_geth_node(config) try: l2_deploy.deploy_contracts_on_l1(config, tmp_l1=True) - - # dump latest block to get the allocs - host = f"127.0.0.1:{config.temp_l1_rpc_listen_port}" - print(f"Fetch debug_dumpBlock from {host}") - res = lib.send_json_rpc_request(host, 3, "debug_dumpBlock", ["latest"]) - response = json.loads(res) - allocs = response['result'] - lib.write_json_file(config.l1_allocs_path, allocs) finally: PROCESS_MGR.kill(geth, ensure=True) @@ -113,7 +104,8 @@ def early_exit_handler(): # Mine a block every second — without this the L2 contracts deployment can hang because # the basefees climbed too high and geth doesn't mine any blocks so it never goes down. "--dev.period 1", - "--rpc.allow-unprotected-txs" + "--rpc.allow-unprotected-txs", + "--state.scheme=path" ], file=log_file, on_exit=early_exit_handler) diff --git a/l2_deploy.py b/l2_deploy.py index 293f02e..a4e8580 100644 --- a/l2_deploy.py +++ b/l2_deploy.py @@ -46,10 +46,7 @@ def deploy_contracts_on_l1(config: Config, tmp_l1=False): # Copy the deploy config to where the deploy script can find it. shutil.copy(config.deploy_config_path, config.op_deploy_config_path) - try: - _deploy_contracts_on_l1(config, tmp_l1) - finally: - os.remove(config.op_deploy_config_path) + _deploy_contracts_on_l1(config, tmp_l1) def _deploy_contracts_on_l1(config: Config, tmp_l1: bool): @@ -110,14 +107,15 @@ def _deploy_contracts_on_l1(config: Config, tmp_l1: bool): create2_deployer_deploy_tx ]) - deploy_script = "scripts/Deploy.s.sol:Deploy" + deploy_script = "scripts/deploy/Deploy.s.sol:Deploy" log_file = f"{config.logs_dir}/deploy_l1_contracts.log" print(f"Deploying contracts to L1 with {deployer_account}. Logging to {log_file}\n" f"Using deploy salt: '{config.deploy_salt}'") env = {**os.environ, - "DEPLOYMENT_CONTEXT": config.deployment_name, + "DEPLOYMENT_OUTFILE": config.op_rollup_l1_contracts_addresses_path, + "DEPLOY_CONFIG_PATH": config.op_deploy_config_path, "ETH_RPC_URL": l1_rpc_url, "IMPL_SALT": f"'{config.deploy_salt}'"} @@ -132,6 +130,7 @@ def _deploy_contracts_on_l1(config: Config, tmp_l1: bool): "deploy the L2 contracts on L1", [ "forge script", deploy_script, + "--sig", "'runWithStateDump()'", "--sender", deployer_account, private_key_arg, f"--gas-estimate-multiplier {config.l1_deployment_gas_multiplier} " @@ -144,25 +143,12 @@ def _deploy_contracts_on_l1(config: Config, tmp_l1: bool): env=env, log_file=log_file) - # copy now because the sync() invocation will delete the file + shutil.move(src=os.path.join(config.op_contracts_dir, + f'state-dump-{config.l1_chain_id}.json'), dst=config.l1_allocs_path) + shutil.copy(config.op_rollup_l1_contracts_addresses_path, config.addresses_path) - log_file = f"{config.logs_dir}/create_l1_artifacts.log" - print(f"Creating L1 deployment artifacts. Logging to {log_file}") - lib.run_roll_log( - "create L1 deployment artifacts", [ - "forge script", - deploy_script, - "--sig 'sync()'", - f"--rpc-url {l1_rpc_url}", - ], - cwd=config.op_contracts_dir, - env=env, - log_file=log_file) - - shutil.move(config.op_deployment_artifacts_dir, config.abi_dir) - #################################################################################################### @@ -173,18 +159,43 @@ def _generate_l2_genesis(config: Config): if os.path.exists(config.l2_genesis_path): print("L2 genesis and rollup configs already generated.") else: - print("Generating L2 genesis and rollup configs.") + print("Generating L2 genesis allocs.") + try: + log_file = f"{config.logs_dir}/generate_l2_genesis_allocs.log" + print('Generating L2 genesis allocs, with L1 addresses: '+config.addresses_path) + script = 'scripts/L2Genesis.s.sol:L2Genesis' + env = {**os.environ, + 'CONTRACT_ADDRESSES_PATH': config.addresses_path, + 'DEPLOY_CONFIG_PATH': config.op_deploy_config_path, } + lib.run_roll_log("generate l2 genesis allocs", [ + 'forge', 'script', script, "--sig", "'runWithAllUpgrades()'" + ], env=env, cwd=config.op_contracts_dir, + log_file=log_file) + + # For each fork move the forge-dumps into place as .devnet allocs. + for suffix in ["-delta", "-ecotone", "-fjord", "-granite"]: + input_path = os.path.join(config.op_contracts_dir, + f"state-dump-{config.l2_chain_id}{suffix}.json") + output_path = os.path.join(config.artifacts_dir, f'allocs-l2{suffix}.json') + shutil.move(src=input_path, dst=output_path) + print("Generated L2 allocs: "+output_path) + except Exception as err: + raise lib.extend_exception( + err, prefix="Failed to generate L2 genesis and rollup configs: ") from None + + print("Generating L2 genesis and rollup configs") try: - lib.run( - "generate L2 genesis and rollup configs", [ - "go run cmd/main.go genesis l2", - f"--l1-rpc={config.l1_rpc_url}", - f"--deploy-config={config.deploy_config_path}", - f"--deployment-dir={config.abi_dir}", - f"--outfile.l2={config.l2_genesis_path}", - f"--outfile.rollup={config.rollup_config_path}" - ], - cwd=config.op_node_dir) + log_file = f"{config.logs_dir}/generate_l2_genesis.log" + l2_allocs_path = os.path.join(config.artifacts_dir, 'allocs-l2.json') + lib.run_roll_log("generate l2 genesis and rollup configs", [ + 'go', 'run', 'cmd/main.go', 'genesis', 'l2', + '--l1-rpc', 'http://localhost:8545', + '--deploy-config', config.deploy_config_path, + '--l2-allocs', l2_allocs_path, + '--l1-deployments', config.addresses_path, + '--outfile.l2', config.l2_genesis_path, + '--outfile.rollup', config.rollup_config_path + ], cwd=config.op_node_dir, log_file=log_file) except Exception as err: raise lib.extend_exception( err, prefix="Failed to generate L2 genesis and rollup configs: ") from None diff --git a/l2_engine.py b/l2_engine.py index d19264d..62f45a0 100644 --- a/l2_engine.py +++ b/l2_engine.py @@ -34,6 +34,7 @@ def start(config: Config): f"--verbosity={config.l2_engine_verbosity}", "init", f"--datadir={config.l2_engine_data_dir}", + "--state.scheme=hash", config.l2_genesis_path ], file=log_file) @@ -91,7 +92,8 @@ def start(config: Config): f"--rollup.disabletxpoolgossip={config.l2_engine_disable_tx_gossip}", # Other geth options - f"--txlookuplimit={config.l2_engine_history_transactions}" + f"--history.transactions={config.l2_engine_history_transactions}", + "--state.scheme=hash" # TODO: investigate why state.scheme=path is not working ] config.log_l2_command("\n".join(command)) diff --git a/ruff.toml b/ruff.toml index 6c7385e..543cada 100644 --- a/ruff.toml +++ b/ruff.toml @@ -1,4 +1,4 @@ line-length = 110 [lint.per-file-ignores] -"l1.py" = ["E402"] \ No newline at end of file +"l1.py" = ["E402"] diff --git a/setup.py b/setup.py index d1b2a4d..14a1346 100644 --- a/setup.py +++ b/setup.py @@ -28,10 +28,7 @@ def setup(config: Config): def setup_optimism_repo(config: Config): github_url = "https://github.com/ethereum-optimism/optimism.git" - git_tag = "op-node/v1.3.1" - git_fix1_tag = "2e57472890f9fea39cde72537935393b068d3e0f" - git_fix2_tag = "5252c82f607af81f6cb741a370425eaf26280892" - git_custom_tag = "roll-op/v1.3.1" + git_tag = "v1.9.3" if os.path.isfile("optimism"): raise Exception("Error: 'optimism' exists as a file and not a directory.") @@ -39,27 +36,9 @@ def setup_optimism_repo(config: Config): print("Cloning the optimism repository. This may take a while...") lib.clone_repo(github_url, "clone the optimism repository") - head_tag = lib.run( - "get head tag", - "git tag --contains HEAD", - cwd="optimism").strip() - - if head_tag != git_custom_tag: - lib.run("[optimism] fetch", - "git fetch", - cwd="optimism") - lib.run("[optimism] checkout stable version", - f"git checkout --detach {git_tag}", - cwd="optimism") - lib.run("[optimism] install devnet fix", - f"git cherry-pick {git_fix1_tag}", - cwd="optimism") - lib.run("[optimism] install submodules fix", - f"git cherry-pick {git_fix2_tag}", - cwd="optimism") - lib.run("[optimism] tag custom version", - f"git tag {git_custom_tag}", - cwd="optimism") + lib.run("[optimism] checkout stable version", + f"git checkout --detach {git_tag}", + cwd="optimism") log_file = f"{config.logs_dir}/build_optimism.log" print( @@ -98,7 +77,7 @@ def setup_op_geth_repo(config: Config): Clone the op-geth repository and build it. """ github_url = "https://github.com/ethereum-optimism/op-geth.git" - git_tag = "v1.101304.1" + git_tag = "v1.101408.0" if os.path.isfile("op-geth"): raise Exception("Error: 'op-geth' exists as a file and not a directory.")