From 8f7a4fc04c255a869d7030544d0e4f1b05b2c8cf Mon Sep 17 00:00:00 2001 From: tserg <8017125+tserg@users.noreply.github.com> Date: Wed, 8 May 2024 22:51:12 +0800 Subject: [PATCH 1/4] add source map for deployable --- vyper/cli/vyper_compile.py | 4 +++- vyper/cli/vyper_json.py | 24 +++++++++++++++--------- vyper/compiler/__init__.py | 2 ++ vyper/compiler/output.py | 19 +++++++++++++++---- 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/vyper/cli/vyper_compile.py b/vyper/cli/vyper_compile.py index d390e3bb8a..cdcb498de3 100755 --- a/vyper/cli/vyper_compile.py +++ b/vyper/cli/vyper_compile.py @@ -22,7 +22,8 @@ blueprint_bytecode - Deployment bytecode for an ERC-5202 compatible blueprint abi - ABI in JSON format abi_python - ABI in python format -source_map - Vyper source map +source_map - Vyper source map of deployable bytecode +source_map_runtime - Vyper source map of runtime bytecode method_identifiers - Dictionary of method signature to method identifier userdoc - Natspec user documentation devdoc - Natspec developer documentation @@ -48,6 +49,7 @@ "abi", "layout", "source_map", + "source_map_runtime", "method_identifiers", "userdoc", "devdoc", diff --git a/vyper/cli/vyper_json.py b/vyper/cli/vyper_json.py index 71b0c6a1b3..0e5a4bd21f 100755 --- a/vyper/cli/vyper_json.py +++ b/vyper/cli/vyper_json.py @@ -22,10 +22,12 @@ "evm.methodIdentifiers": "method_identifiers", "evm.bytecode.object": "bytecode", "evm.bytecode.opcodes": "opcodes", + "evm.bytecode.sourceMap": "source_map", + "evm.bytecode.sourceMapFull": "source_map_full", "evm.deployedBytecode.object": "bytecode_runtime", "evm.deployedBytecode.opcodes": "opcodes_runtime", - "evm.deployedBytecode.sourceMap": "source_map", - "evm.deployedBytecode.sourceMapFull": "source_map_full", + "evm.deployedBytecode.sourceMap": "source_map_runtime", + "evm.deployedBytecode.sourceMapFull": "source_map_full_runtime", "interface": "interface", "ir": "ir_dict", "ir_runtime": "ir_runtime_dict", @@ -341,24 +343,28 @@ def format_to_output_dict(compiler_data: dict) -> dict: output_contracts["evm"] = {"methodIdentifiers": data["method_identifiers"]} evm_keys = ("bytecode", "opcodes") - if any(i in data for i in evm_keys): + pc_maps_keys = ("source_map", "source_map_full") + if any(i in data for i in evm_keys) or any(i in data for i in pc_maps_keys): evm = output_contracts.setdefault("evm", {}).setdefault("bytecode", {}) if "bytecode" in data: evm["object"] = data["bytecode"] if "opcodes" in data: evm["opcodes"] = data["opcodes"] + if "source_map" in data: + evm["sourceMap"] = data["source_map"]["pc_pos_map_compressed"] + if "source_map_full" in data: + evm["sourceMapFull"] = data["source_map_full"] - pc_maps_keys = ("source_map", "source_map_full") - if any(i + "_runtime" in data for i in evm_keys) or any(i in data for i in pc_maps_keys): + if any(i + "_runtime" in data for i in evm_keys): evm = output_contracts.setdefault("evm", {}).setdefault("deployedBytecode", {}) if "bytecode_runtime" in data: evm["object"] = data["bytecode_runtime"] if "opcodes_runtime" in data: evm["opcodes"] = data["opcodes_runtime"] - if "source_map" in data: - evm["sourceMap"] = data["source_map"]["pc_pos_map_compressed"] - if "source_map_full" in data: - evm["sourceMapFull"] = data["source_map_full"] + if "source_map_runtime" in data: + evm["sourceMap"] = data["source_map_runtime"]["pc_pos_map_compressed"] + if "source_map_full_runtime" in data: + evm["sourceMapFull"] = data["source_map_full_runtime"] return output_dict diff --git a/vyper/compiler/__init__.py b/vyper/compiler/__init__.py index 47e2054bd8..328a16c3b2 100644 --- a/vyper/compiler/__init__.py +++ b/vyper/compiler/__init__.py @@ -35,6 +35,8 @@ "asm": output.build_asm_output, "source_map": output.build_source_map_output, "source_map_full": output.build_source_map_output, + "source_map_runtime": output.build_source_map_runtime_output, + "source_map_full_runtime": output.build_source_map_runtime_output, # requires bytecode "bytecode": output.build_bytecode_output, "bytecode_runtime": output.build_bytecode_runtime_output, diff --git a/vyper/compiler/output.py b/vyper/compiler/output.py index 9b3bd147ef..76f720f863 100644 --- a/vyper/compiler/output.py +++ b/vyper/compiler/output.py @@ -246,16 +246,13 @@ def _build_node_identifier(ast_node): return (ast_node.module_node.source_id, ast_node.node_id) -def build_source_map_output(compiler_data: CompilerData) -> dict: +def _build_source_map_output(compiler_data, bytecode, pc_maps): """ Generate source map output in various formats. Note that integrations are encouraged to use pc_ast_map since the information it provides is a superset of the other formats, and the other types are included for legacy reasons. """ - bytecode, pc_maps = compile_ir.assembly_to_evm( - compiler_data.assembly_runtime, insert_compiler_metadata=False - ) # sort the pc maps alphabetically # CMC 2024-03-09 is this really necessary? out = {} @@ -280,6 +277,20 @@ def build_source_map_output(compiler_data: CompilerData) -> dict: return out +def build_source_map_output(compiler_data: CompilerData) -> dict: + bytecode, pc_maps = compile_ir.assembly_to_evm( + compiler_data.assembly, insert_compiler_metadata=False + ) + return _build_source_map_output(compiler_data, bytecode, pc_maps) + + +def build_source_map_runtime_output(compiler_data: CompilerData) -> dict: + bytecode, pc_maps = compile_ir.assembly_to_evm( + compiler_data.assembly_runtime, insert_compiler_metadata=False + ) + return _build_source_map_output(compiler_data, bytecode, pc_maps) + + # generate a solidity-style source map. this functionality is deprecated # in favor of pc_ast_map, and may not be maintained to the same level # as pc_ast_map. From aa341c12235524ed1f4411159448500f33544ee0 Mon Sep 17 00:00:00 2001 From: tserg <8017125+tserg@users.noreply.github.com> Date: Thu, 9 May 2024 11:45:01 +0800 Subject: [PATCH 2/4] fix format to output dict --- tests/unit/cli/vyper_json/test_compile_json.py | 11 ++++++++--- vyper/cli/vyper_json.py | 4 ++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/tests/unit/cli/vyper_json/test_compile_json.py b/tests/unit/cli/vyper_json/test_compile_json.py index f4c93c08bf..ba6b3ac4aa 100644 --- a/tests/unit/cli/vyper_json/test_compile_json.py +++ b/tests/unit/cli/vyper_json/test_compile_json.py @@ -171,12 +171,17 @@ def test_compile_json(input_json, input_bundle): "userdoc": data["userdoc"], "metadata": data["metadata"], "evm": { - "bytecode": {"object": data["bytecode"], "opcodes": data["opcodes"]}, + "bytecode": { + "object": data["bytecode"], + "opcodes": data["opcodes"], + "sourceMap": data["source_map"]["pc_pos_map_compressed"], + "sourceMapFull": data["source_map_full"], + }, "deployedBytecode": { "object": data["bytecode_runtime"], "opcodes": data["opcodes_runtime"], - "sourceMap": data["source_map"]["pc_pos_map_compressed"], - "sourceMapFull": data["source_map_full"], + "sourceMap": data["source_map_runtime"]["pc_pos_map_compressed"], + "sourceMapFull": data["source_map_full_runtime"], }, "methodIdentifiers": data["method_identifiers"], }, diff --git a/vyper/cli/vyper_json.py b/vyper/cli/vyper_json.py index fb84a51c05..ebb86a37b7 100755 --- a/vyper/cli/vyper_json.py +++ b/vyper/cli/vyper_json.py @@ -344,7 +344,7 @@ def format_to_output_dict(compiler_data: dict) -> dict: evm_keys = ("bytecode", "opcodes") pc_maps_keys = ("source_map", "source_map_full") - if any(i in data for i in evm_keys) or any(i in data for i in pc_maps_keys): + if any(i in data for i in evm_keys + pc_maps_keys): evm = output_contracts.setdefault("evm", {}).setdefault("bytecode", {}) if "bytecode" in data: evm["object"] = data["bytecode"] @@ -355,7 +355,7 @@ def format_to_output_dict(compiler_data: dict) -> dict: if "source_map_full" in data: evm["sourceMapFull"] = data["source_map_full"] - if any(i + "_runtime" in data for i in evm_keys): + if any(i + "_runtime" in data for i in evm_keys + pc_maps_keys): evm = output_contracts.setdefault("evm", {}).setdefault("deployedBytecode", {}) if "bytecode_runtime" in data: evm["object"] = data["bytecode_runtime"] From bcd6832ba0a2a23948c531ad061dfb3c95aa7e2f Mon Sep 17 00:00:00 2001 From: tserg <8017125+tserg@users.noreply.github.com> Date: Thu, 9 May 2024 11:53:16 +0800 Subject: [PATCH 3/4] fix vyper compile tests --- tests/unit/cli/vyper_compile/test_compile_files.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit/cli/vyper_compile/test_compile_files.py b/tests/unit/cli/vyper_compile/test_compile_files.py index 6467ff6dc9..3856aa3362 100644 --- a/tests/unit/cli/vyper_compile/test_compile_files.py +++ b/tests/unit/cli/vyper_compile/test_compile_files.py @@ -22,6 +22,7 @@ def test_combined_json_keys(chdir_tmp_path, make_file): "blueprint_bytecode", "abi", "source_map", + "source_map_runtime", "layout", "method_identifiers", "userdoc", From f7c8bc4cf4bd42d0d37e5a61db2845fbe49c9bba Mon Sep 17 00:00:00 2001 From: tserg <8017125+tserg@users.noreply.github.com> Date: Thu, 9 May 2024 22:02:38 +0800 Subject: [PATCH 4/4] remove compressed source map --- tests/unit/cli/vyper_json/test_compile_json.py | 10 ++++------ vyper/cli/vyper_json.py | 12 +++--------- vyper/compiler/__init__.py | 2 -- 3 files changed, 7 insertions(+), 17 deletions(-) diff --git a/tests/unit/cli/vyper_json/test_compile_json.py b/tests/unit/cli/vyper_json/test_compile_json.py index ba6b3ac4aa..ef3284cd15 100644 --- a/tests/unit/cli/vyper_json/test_compile_json.py +++ b/tests/unit/cli/vyper_json/test_compile_json.py @@ -174,14 +174,12 @@ def test_compile_json(input_json, input_bundle): "bytecode": { "object": data["bytecode"], "opcodes": data["opcodes"], - "sourceMap": data["source_map"]["pc_pos_map_compressed"], - "sourceMapFull": data["source_map_full"], + "sourceMap": data["source_map"], }, "deployedBytecode": { "object": data["bytecode_runtime"], "opcodes": data["opcodes_runtime"], - "sourceMap": data["source_map_runtime"]["pc_pos_map_compressed"], - "sourceMapFull": data["source_map_full_runtime"], + "sourceMap": data["source_map_runtime"], }, "methodIdentifiers": data["method_identifiers"], }, @@ -271,7 +269,7 @@ def test_exc_handler_to_dict_compiler(input_json): def test_source_ids_increment(input_json): - input_json["settings"]["outputSelection"] = {"*": ["ast", "evm.deployedBytecode.sourceMapFull"]} + input_json["settings"]["outputSelection"] = {"*": ["ast", "evm.deployedBytecode.sourceMap"]} result = compile_json(input_json) def get(filename, contractname): @@ -280,7 +278,7 @@ def get(filename, contractname): # grab it via source map to sanity check contract_info = result["contracts"][filename][contractname]["evm"] - pc_ast_map = contract_info["deployedBytecode"]["sourceMapFull"]["pc_ast_map"] + pc_ast_map = contract_info["deployedBytecode"]["sourceMap"]["pc_ast_map"] pc_item = next(iter(pc_ast_map.values())) source_id, node_id = pc_item assert ret == source_id diff --git a/vyper/cli/vyper_json.py b/vyper/cli/vyper_json.py index ebb86a37b7..4f73732687 100755 --- a/vyper/cli/vyper_json.py +++ b/vyper/cli/vyper_json.py @@ -23,11 +23,9 @@ "evm.bytecode.object": "bytecode", "evm.bytecode.opcodes": "opcodes", "evm.bytecode.sourceMap": "source_map", - "evm.bytecode.sourceMapFull": "source_map_full", "evm.deployedBytecode.object": "bytecode_runtime", "evm.deployedBytecode.opcodes": "opcodes_runtime", "evm.deployedBytecode.sourceMap": "source_map_runtime", - "evm.deployedBytecode.sourceMapFull": "source_map_full_runtime", "interface": "interface", "ir": "ir_dict", "ir_runtime": "ir_runtime_dict", @@ -343,7 +341,7 @@ def format_to_output_dict(compiler_data: dict) -> dict: output_contracts["evm"] = {"methodIdentifiers": data["method_identifiers"]} evm_keys = ("bytecode", "opcodes") - pc_maps_keys = ("source_map", "source_map_full") + pc_maps_keys = ("source_map",) if any(i in data for i in evm_keys + pc_maps_keys): evm = output_contracts.setdefault("evm", {}).setdefault("bytecode", {}) if "bytecode" in data: @@ -351,9 +349,7 @@ def format_to_output_dict(compiler_data: dict) -> dict: if "opcodes" in data: evm["opcodes"] = data["opcodes"] if "source_map" in data: - evm["sourceMap"] = data["source_map"]["pc_pos_map_compressed"] - if "source_map_full" in data: - evm["sourceMapFull"] = data["source_map_full"] + evm["sourceMap"] = data["source_map"] if any(i + "_runtime" in data for i in evm_keys + pc_maps_keys): evm = output_contracts.setdefault("evm", {}).setdefault("deployedBytecode", {}) @@ -362,9 +358,7 @@ def format_to_output_dict(compiler_data: dict) -> dict: if "opcodes_runtime" in data: evm["opcodes"] = data["opcodes_runtime"] if "source_map_runtime" in data: - evm["sourceMap"] = data["source_map_runtime"]["pc_pos_map_compressed"] - if "source_map_full_runtime" in data: - evm["sourceMapFull"] = data["source_map_full_runtime"] + evm["sourceMap"] = data["source_map_runtime"] return output_dict diff --git a/vyper/compiler/__init__.py b/vyper/compiler/__init__.py index 1c58b4421f..9ed38885b4 100644 --- a/vyper/compiler/__init__.py +++ b/vyper/compiler/__init__.py @@ -37,9 +37,7 @@ "abi": output.build_abi_output, "asm": output.build_asm_output, "source_map": output.build_source_map_output, - "source_map_full": output.build_source_map_output, "source_map_runtime": output.build_source_map_runtime_output, - "source_map_full_runtime": output.build_source_map_runtime_output, # requires bytecode "bytecode": output.build_bytecode_output, "bytecode_runtime": output.build_bytecode_runtime_output,