diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 7a8b53c233..4515265a93 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -54,6 +54,10 @@ jobs: - uses: Chia-Network/actions/git-mark-workspace-safe@main + - name: disable git autocrlf + run: | + git config --global core.autocrlf false + - uses: actions/checkout@v3 - uses: Chia-Network/actions/setup-python@main diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1b479c0523..f67381b4c1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -29,6 +29,13 @@ repos: - id: check-merge-conflict - id: check-ast - id: debug-statements +- repo: local + hooks: + - id: clvm_hex + name: .clvm.hex files + entry: ./activated.py python tests/check_clvm.py + language: python + pass_filenames: false - repo: local hooks: - id: mypy diff --git a/activated.ps1 b/activated.ps1 index 3a7f70f42e..eb63e32c9a 100644 --- a/activated.ps1 +++ b/activated.ps1 @@ -2,7 +2,11 @@ $ErrorActionPreference = "Stop" $script_directory = Split-Path $MyInvocation.MyCommand.Path -Parent +$command = $args[0] +$parameters = [System.Collections.ArrayList]$args +$parameters.RemoveAt(0) + & $script_directory/venv/Scripts/Activate.ps1 -& @args +& $command @parameters exit $LASTEXITCODE diff --git a/chia/wallet/puzzles/condition_codes.clvm.hex b/chia/wallet/puzzles/condition_codes.clvm.hex deleted file mode 100644 index ec0643a65a..0000000000 --- a/chia/wallet/puzzles/condition_codes.clvm.hex +++ /dev/null @@ -1 +0,0 @@ -can't compile ("defconstant" "AGG_SIG_UNSAFE" 49), unknown operator diff --git a/chia/wallet/puzzles/counter.clvm.hex b/chia/wallet/puzzles/counter.clvm.hex deleted file mode 100644 index 8c126e9e42..0000000000 --- a/chia/wallet/puzzles/counter.clvm.hex +++ /dev/null @@ -1 +0,0 @@ -ff02ffff01ff04ffff04ff38ffff04ffff02ff3affff04ff02ffff04ff05ffff04ffff02ff2effff04ff02ffff04ff17ffff04ffff02ff26ffff04ff02ffff04ff2fff80808080ff8080808080ff8080808080ffff04ff27ff80808080ffff02ff32ffff04ff02ffff04ff0bffff04ff2fffff01ff01808080808080ffff04ffff01ffffff32ff0233ffff0401ff0102ffffffff02ffff03ff05ffff01ff02ff22ffff04ff02ffff04ff0dffff04ffff0bff3cffff0bff34ff2480ffff0bff3cffff0bff3cffff0bff34ff2c80ff0980ffff0bff3cff0bffff0bff34ff8080808080ff8080808080ffff010b80ff0180ff02ffff03ff0bffff01ff04ffff04ff38ffff04ffff02ff2affff04ff02ffff04ff05ffff04ffff04ffff04ff17ff1380ff8080ff8080808080ffff01ff80808080ffff04ffff04ff10ffff04ff23ffff04ffff02ff3effff04ff02ffff04ffff04ff13ffff04ff17ff808080ff80808080ff80808080ffff02ff32ffff04ff02ffff04ff05ffff04ff1bffff04ffff10ff17ffff010180ff8080808080808080ff8080ff0180ffff02ff36ffff04ff02ffff04ff05ffff04ffff02ff3effff04ff02ffff04ff0bff80808080ff8080808080ff02ff36ffff04ff02ffff04ff05ffff04ffff02ff3effff04ff02ffff04ff0bff80808080ffff04ffff02ff3effff04ff02ffff04ff05ff80808080ff808080808080ffffff02ffff03ffff07ff0580ffff01ff04ff29ffff02ff26ffff04ff02ffff04ff0dff8080808080ff8080ff0180ff0bff3cffff0bff34ff2880ffff0bff3cffff0bff3cffff0bff34ff2c80ff0580ffff0bff3cffff02ff22ffff04ff02ffff04ff07ffff04ffff0bff34ff3480ff8080808080ffff0bff34ff8080808080ffff02ffff03ffff07ff0b80ffff01ff10ff13ffff02ff2effff04ff02ffff04ff05ffff04ff1bff808080808080ffff011580ff0180ff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff3effff04ff02ffff04ff09ff80808080ffff02ff3effff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ff018080 \ No newline at end of file diff --git a/chia/wallet/puzzles/create-lock-puzzlehash.clvm.hex b/chia/wallet/puzzles/create-lock-puzzlehash.clvm.hex deleted file mode 100644 index 06c984069f..0000000000 --- a/chia/wallet/puzzles/create-lock-puzzlehash.clvm.hex +++ /dev/null @@ -1 +0,0 @@ -can't compile ("my-id"), unknown operator diff --git a/chia/wallet/puzzles/create-lock-puzzlehash.clvm.hex.sha256tree b/chia/wallet/puzzles/create-lock-puzzlehash.clvm.hex.sha256tree deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/chia/wallet/puzzles/decompress_block_spends.clvm.hex.sha256tree b/chia/wallet/puzzles/decompress_block_spends.clvm.hex.sha256tree index 0ac556edf0..799cfbd6aa 100644 --- a/chia/wallet/puzzles/decompress_block_spends.clvm.hex.sha256tree +++ b/chia/wallet/puzzles/decompress_block_spends.clvm.hex.sha256tree @@ -1 +1 @@ -f890a7866079009517ae0b652d530268d2531bbac99670aaba461d604bc0ff0c \ No newline at end of file +f890a7866079009517ae0b652d530268d2531bbac99670aaba461d604bc0ff0c diff --git a/chia/wallet/puzzles/everything_with_signature.clvm.hex.sha256tree b/chia/wallet/puzzles/everything_with_signature.clvm.hex.sha256tree index 375a544097..8dea922f4e 100644 --- a/chia/wallet/puzzles/everything_with_signature.clvm.hex.sha256tree +++ b/chia/wallet/puzzles/everything_with_signature.clvm.hex.sha256tree @@ -1 +1 @@ -1720d13250a7c16988eaf530331cefa9dd57a76b2c82236bec8bbbff91499b89 \ No newline at end of file +1720d13250a7c16988eaf530331cefa9dd57a76b2c82236bec8bbbff91499b89 diff --git a/chia/wallet/puzzles/genesis_by_coin_id.clvm.hex.sha256tree b/chia/wallet/puzzles/genesis_by_coin_id.clvm.hex.sha256tree index f240ff9417..0ca0e4e61e 100644 --- a/chia/wallet/puzzles/genesis_by_coin_id.clvm.hex.sha256tree +++ b/chia/wallet/puzzles/genesis_by_coin_id.clvm.hex.sha256tree @@ -1 +1 @@ -493afb89eed93ab86741b2aa61b8f5de495d33ff9b781dfc8919e602b2afa150 \ No newline at end of file +493afb89eed93ab86741b2aa61b8f5de495d33ff9b781dfc8919e602b2afa150 diff --git a/chia/wallet/puzzles/genesis_by_puzzle_hash.clvm.hex.sha256tree b/chia/wallet/puzzles/genesis_by_puzzle_hash.clvm.hex.sha256tree index 69cdc4bce6..800a02c7b3 100644 --- a/chia/wallet/puzzles/genesis_by_puzzle_hash.clvm.hex.sha256tree +++ b/chia/wallet/puzzles/genesis_by_puzzle_hash.clvm.hex.sha256tree @@ -1 +1 @@ -de5a6e06d41518be97ff6365694f4f89475dda773dede267caa33da63b434e36 \ No newline at end of file +de5a6e06d41518be97ff6365694f4f89475dda773dede267caa33da63b434e36 diff --git a/chia/wallet/puzzles/graftroot_dl_offers.clvm.hex.sha256tree b/chia/wallet/puzzles/graftroot_dl_offers.clvm.hex.sha256tree index f05a2031a7..3bcfde7e54 100644 --- a/chia/wallet/puzzles/graftroot_dl_offers.clvm.hex.sha256tree +++ b/chia/wallet/puzzles/graftroot_dl_offers.clvm.hex.sha256tree @@ -1 +1 @@ -0893e36a88c064fddfa6f8abdb42c044584a98cb4273b80cccc83b4867b701a1 \ No newline at end of file +0893e36a88c064fddfa6f8abdb42c044584a98cb4273b80cccc83b4867b701a1 diff --git a/chia/wallet/puzzles/index_lock.clvm.hex b/chia/wallet/puzzles/index_lock.clvm.hex deleted file mode 100644 index 1de3969ea5..0000000000 --- a/chia/wallet/puzzles/index_lock.clvm.hex +++ /dev/null @@ -1 +0,0 @@ -ff02ffff01ff04ffff04ffff013effff04ffff02ff02ffff04ff02ffff04ff05ff80808080ff808080ff8080ffff04ffff01ff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff02ffff04ff02ffff04ff09ff80808080ffff02ff02ffff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ff018080 \ No newline at end of file diff --git a/chia/wallet/puzzles/nft_metadata_updater.clvm.hex.sha256tree b/chia/wallet/puzzles/nft_metadata_updater.clvm.hex.sha256tree deleted file mode 100644 index 33850df9e7..0000000000 --- a/chia/wallet/puzzles/nft_metadata_updater.clvm.hex.sha256tree +++ /dev/null @@ -1 +0,0 @@ -3df9de54667a96f32eba322635f14d3474edadf23f396ba5a3e2e077a89a682a diff --git a/chia/wallet/puzzles/nft_metadata_updater_default.clvm.hex b/chia/wallet/puzzles/nft_metadata_updater_default.clvm.hex index 554008d4bd..147d785fb6 100644 --- a/chia/wallet/puzzles/nft_metadata_updater_default.clvm.hex +++ b/chia/wallet/puzzles/nft_metadata_updater_default.clvm.hex @@ -1 +1 @@ -ff02ffff01ff04ffff04ffff02ffff03ffff22ff27ff3780ffff01ff02ffff03ffff21ffff09ff27ffff01826d7580ffff09ff27ffff01826c7580ffff09ff27ffff01758080ffff01ff02ff02ffff04ff02ffff04ff05ffff04ff27ffff04ff37ff808080808080ffff010580ff0180ffff010580ff0180ffff04ff0bff808080ffff01ff808080ffff04ffff01ff02ffff03ff05ffff01ff02ffff03ffff09ff11ff0b80ffff01ff04ffff04ff0bffff04ff17ff198080ff0d80ffff01ff04ff09ffff02ff02ffff04ff02ffff04ff0dffff04ff0bffff04ff17ff8080808080808080ff0180ff8080ff0180ff018080 +ff02ffff01ff04ffff04ffff02ffff03ffff22ff27ff3780ffff01ff02ffff03ffff21ffff09ff27ffff01826d7580ffff09ff27ffff01826c7580ffff09ff27ffff01758080ffff01ff02ff02ffff04ff02ffff04ff05ffff04ff27ffff04ff37ff808080808080ffff010580ff0180ffff010580ff0180ffff04ff0bff808080ffff01ff808080ffff04ffff01ff02ffff03ff05ffff01ff02ffff03ffff09ff11ff0b80ffff01ff04ffff04ff0bffff04ff17ff198080ff0d80ffff01ff04ff09ffff02ff02ffff04ff02ffff04ff0dffff04ff0bffff04ff17ff8080808080808080ff0180ff8080ff0180ff018080 \ No newline at end of file diff --git a/chia/wallet/puzzles/nft_metadata_updater_updateable.clvm.hex b/chia/wallet/puzzles/nft_metadata_updater_updateable.clvm.hex index 8f416cfdee..679a2e7e2b 100644 --- a/chia/wallet/puzzles/nft_metadata_updater_updateable.clvm.hex +++ b/chia/wallet/puzzles/nft_metadata_updater_updateable.clvm.hex @@ -1 +1 @@ -ff02ffff01ff04ffff04ffff02ffff03ff27ffff01ff02ff02ffff04ff02ffff04ff05ffff04ff27ff8080808080ffff010580ff0180ffff04ffff02ffff03ffff09ffff0dff5780ffff012080ffff0157ffff010b80ff0180ff808080ffff01ff808080ffff04ffff01ff02ffff03ff05ffff01ff02ffff03ffff09ff11ffff017580ffff01ff04ffff04ffff0175ffff04ff0bff198080ff0d80ffff01ff04ff09ffff02ff02ffff04ff02ffff04ff0dffff04ff0bff80808080808080ff0180ff8080ff0180ff018080 +ff02ffff01ff04ffff04ffff02ffff03ff27ffff01ff02ff02ffff04ff02ffff04ff05ffff04ff27ff8080808080ffff010580ff0180ffff04ffff02ffff03ffff09ffff0dff5780ffff012080ffff0157ffff010b80ff0180ff808080ffff01ff808080ffff04ffff01ff02ffff03ff05ffff01ff02ffff03ffff09ff11ffff017580ffff01ff04ffff04ffff0175ffff04ff0bff198080ff0d80ffff01ff04ff09ffff02ff02ffff04ff02ffff04ff0dffff04ff0bff80808080808080ff0180ff8080ff0180ff018080 \ No newline at end of file diff --git a/chia/wallet/puzzles/nft_ownership_layer.clvm.hex.sha256tree b/chia/wallet/puzzles/nft_ownership_layer.clvm.hex.sha256tree index 92fdd822e2..bf67047bf8 100644 --- a/chia/wallet/puzzles/nft_ownership_layer.clvm.hex.sha256tree +++ b/chia/wallet/puzzles/nft_ownership_layer.clvm.hex.sha256tree @@ -1 +1 @@ -c5abea79afaa001b5427dfa0c8cf42ca6f38f5841b78f9b3c252733eb2de2726 \ No newline at end of file +c5abea79afaa001b5427dfa0c8cf42ca6f38f5841b78f9b3c252733eb2de2726 diff --git a/chia/wallet/puzzles/p2_delegated_conditions.clvm.hex b/chia/wallet/puzzles/p2_delegated_conditions.clvm.hex index 46f9abe765..451d641315 100644 --- a/chia/wallet/puzzles/p2_delegated_conditions.clvm.hex +++ b/chia/wallet/puzzles/p2_delegated_conditions.clvm.hex @@ -1 +1 @@ -ff02ffff01ff04ffff04ff04ffff04ff05ffff04ffff02ff06ffff04ff02ffff04ff0bff80808080ff80808080ff0b80ffff04ffff01ff32ff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff06ffff04ff02ffff04ff09ff80808080ffff02ff06ffff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ff018080 +ff02ffff01ff04ffff04ff04ffff04ff05ffff04ffff02ff06ffff04ff02ffff04ff0bff80808080ff80808080ff0b80ffff04ffff01ff32ff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff06ffff04ff02ffff04ff09ff80808080ffff02ff06ffff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ff018080 \ No newline at end of file diff --git a/chia/wallet/puzzles/p2_parent.clvm.hex.sha256tree b/chia/wallet/puzzles/p2_parent.clvm.hex.sha256tree index 928010c406..9572b4f1d4 100644 --- a/chia/wallet/puzzles/p2_parent.clvm.hex.sha256tree +++ b/chia/wallet/puzzles/p2_parent.clvm.hex.sha256tree @@ -1 +1 @@ -b10ce2d0b18dcf8c21ddfaf55d9b9f0adcbf1e0beb55b1a8b9cad9bbff4e5f22 \ No newline at end of file +b10ce2d0b18dcf8c21ddfaf55d9b9f0adcbf1e0beb55b1a8b9cad9bbff4e5f22 diff --git a/chia/wallet/puzzles/rl.clvm.hex b/chia/wallet/puzzles/rl.clvm.hex index ef9e92acd9..ca8dab02c3 100644 --- a/chia/wallet/puzzles/rl.clvm.hex +++ b/chia/wallet/puzzles/rl.clvm.hex @@ -1 +1 @@ -ff02ffff01ff02ffff03ffff09ff81bfff2480ffff01ff04ffff04ff30ffff04ff5fffff04ffff02ff3effff04ff02ffff04ffff04ff81bfff81ff80ff80808080ff80808080ff81ff80ffff01ff04ffff04ff30ffff04ff05ffff04ffff02ff3effff04ff02ffff04ffff04ff81bfff81ff80ff80808080ff80808080ffff02ffff03ffff09ff81bfff3c80ffff01ff02ff2effff04ff02ffff04ff0bffff04ff17ffff04ff2fffff04ff81ffff80808080808080ffff01ff02ff22ffff04ff02ffff04ff2fffff04ff81ffff808080808080ff01808080ff0180ffff04ffff01ffffffffff02ffff03ffff15ff05ff0b80ffff01ff0101ffff01ff02ffff03ffff09ff05ff0b80ffff01ff0101ff8080ff018080ff018031ff5246ffff0333ff3c01ffffffff02ffff03ffff02ffff03ffff09ffff0bff820bfbff13ff8205fb80ff82017b80ffff01ff0101ffff01ff02ffff03ffff09ff05ff82017b80ffff01ff0101ff8080ff018080ff0180ffff01ff04ffff02ff26ffff04ff02ffff04ff82017bffff04ff13ffff04ff8202fbff808080808080ffff04ffff02ff2affff04ff02ffff04ff2bffff04ff5bffff04ff81bbff808080808080ffff04ffff02ff3affff04ff02ffff04ff13ffff04ffff10ff81bbff8202fb80ff8080808080ff80808080ffff01ffff08808080ff0180ff04ff34ffff04ff05ffff04ffff11ff0bffff10ff17ff2f8080ff80808080ffff04ff2cffff04ffff0bff05ff0bff1780ff808080ff04ff34ffff04ff05ffff04ff0bff80808080ffffff04ff38ffff04ffff0bff05ff0bff1780ff808080ff02ffff03ffff02ff20ffff04ff02ffff04ffff12ff05ff1780ffff04ffff12ff0bff2f80ff8080808080ffff01ff04ff28ffff04ff05ff808080ffff01ffff08808080ff0180ffff02ffff03ffff02ffff03ffff09ffff0bff8217efff81afff822fef80ff4f80ffff01ff0101ffff01ff02ffff03ffff09ff17ff4f80ffff01ff0101ff8080ff018080ff0180ffff01ff04ffff02ff36ffff04ff02ffff04ff820befffff04ff8205efffff04ff05ffff04ff0bff80808080808080ffff04ffff02ff32ffff04ff02ffff04ff81afffff04ff82016fffff04ff8205efffff04ff825fefff80808080808080ffff04ffff02ff26ffff04ff02ffff04ff4fffff04ff81afffff04ff82016fff808080808080ffff04ffff02ff3affff04ff02ffff04ff8202efffff04ff8205efff8080808080ff8080808080ffff01ffff08808080ff0180ff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff3effff04ff02ffff04ff09ff80808080ffff02ff3effff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ff018080 +ff02ffff01ff02ffff03ffff09ff81bfff2480ffff01ff04ffff04ff30ffff04ff5fffff04ffff02ff3effff04ff02ffff04ffff04ff81bfff81ff80ff80808080ff80808080ff81ff80ffff01ff04ffff04ff30ffff04ff05ffff04ffff02ff3effff04ff02ffff04ffff04ff81bfff81ff80ff80808080ff80808080ffff02ffff03ffff09ff81bfff3c80ffff01ff02ff2effff04ff02ffff04ff0bffff04ff17ffff04ff2fffff04ff81ffff80808080808080ffff01ff02ff22ffff04ff02ffff04ff2fffff04ff81ffff808080808080ff01808080ff0180ffff04ffff01ffffffffff02ffff03ffff15ff05ff0b80ffff01ff0101ffff01ff02ffff03ffff09ff05ff0b80ffff01ff0101ff8080ff018080ff018031ff5246ffff0333ff3c01ffffffff02ffff03ffff02ffff03ffff09ffff0bff820bfbff13ff8205fb80ff82017b80ffff01ff0101ffff01ff02ffff03ffff09ff05ff82017b80ffff01ff0101ff8080ff018080ff0180ffff01ff04ffff02ff26ffff04ff02ffff04ff82017bffff04ff13ffff04ff8202fbff808080808080ffff04ffff02ff2affff04ff02ffff04ff2bffff04ff5bffff04ff81bbff808080808080ffff04ffff02ff3affff04ff02ffff04ff13ffff04ffff10ff81bbff8202fb80ff8080808080ff80808080ffff01ffff08808080ff0180ff04ff34ffff04ff05ffff04ffff11ff0bffff10ff17ff2f8080ff80808080ffff04ff2cffff04ffff0bff05ff0bff1780ff808080ff04ff34ffff04ff05ffff04ff0bff80808080ffffff04ff38ffff04ffff0bff05ff0bff1780ff808080ff02ffff03ffff02ff20ffff04ff02ffff04ffff12ff05ff1780ffff04ffff12ff0bff2f80ff8080808080ffff01ff04ff28ffff04ff05ff808080ffff01ffff08808080ff0180ffff02ffff03ffff02ffff03ffff09ffff0bff8217efff81afff822fef80ff4f80ffff01ff0101ffff01ff02ffff03ffff09ff17ff4f80ffff01ff0101ff8080ff018080ff0180ffff01ff04ffff02ff36ffff04ff02ffff04ff820befffff04ff8205efffff04ff05ffff04ff0bff80808080808080ffff04ffff02ff32ffff04ff02ffff04ff81afffff04ff82016fffff04ff8205efffff04ff825fefff80808080808080ffff04ffff02ff26ffff04ff02ffff04ff4fffff04ff81afffff04ff82016fff808080808080ffff04ffff02ff3affff04ff02ffff04ff8202efffff04ff8205efff8080808080ff8080808080ffff01ffff08808080ff0180ff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff3effff04ff02ffff04ff09ff80808080ffff02ff3effff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ff018080 \ No newline at end of file diff --git a/tests/check_clvm.py b/tests/check_clvm.py new file mode 100644 index 0000000000..e705c13939 --- /dev/null +++ b/tests/check_clvm.py @@ -0,0 +1,167 @@ +from __future__ import annotations + +import dataclasses +import os +import pathlib +import sys +import tempfile +import traceback + +import typing_extensions + +here = pathlib.Path(__file__).parent.resolve() +root = here.parent + +# This is a work-around for fixing imports so they get the appropriate top level +# packages instead of those of the same name in the same directory as this program. +# This undoes the Python mis-feature meant to support 'scripts' that have not been +# installed by adding the script's directory to the import search path. This is why +# it is simpler to just have all code get installed and all things you run be +# accessible via entry points. +sys.path = [path for path in sys.path if path != os.fspath(here)] + +from clvm_tools_rs import compile_clvm # noqa: E402 + +from chia.types.blockchain_format.program import SerializedProgram # noqa: E402 + +clvm_suffix = ".clvm" +hex_suffix = ".clvm.hex" +hash_suffix = ".clvm.hex.sha256tree" + + +def generate_hash_bytes(hex_bytes: bytes) -> bytes: + cleaned_blob = bytes.fromhex(hex_bytes.decode("utf-8")) + serialize_program = SerializedProgram.from_bytes(cleaned_blob) + result = serialize_program.get_tree_hash().hex() + return (result + "\n").encode("utf-8") + + +@typing_extensions.final +@dataclasses.dataclass(frozen=True) +class ClvmPaths: + clvm: pathlib.Path + hex: pathlib.Path + hash: pathlib.Path + + @classmethod + def from_clvm(cls, clvm: pathlib.Path) -> ClvmPaths: + return cls( + clvm=clvm, + hex=clvm.with_name(clvm.name[: -len(clvm_suffix)] + hex_suffix), + hash=clvm.with_name(clvm.name[: -len(clvm_suffix)] + hash_suffix), + ) + + +@typing_extensions.final +@dataclasses.dataclass(frozen=True) +class ClvmBytes: + hex: bytes + hash: bytes + + @classmethod + def from_clvm_paths(cls, paths: ClvmPaths) -> ClvmBytes: + return cls( + hex=paths.hex.read_bytes(), + hash=paths.hash.read_bytes(), + ) + + @classmethod + def from_hex_bytes(cls, hex_bytes: bytes) -> ClvmBytes: + return cls( + hex=hex_bytes, + hash=generate_hash_bytes(hex_bytes=hex_bytes), + ) + + +# These files have the wrong extension for now so we'll just manually exclude them +excludes = {"condition_codes.clvm", "create-lock-puzzlehash.clvm"} + + +def main() -> int: + used_excludes = set() + overall_fail = False + + suffixes = {"clvm": clvm_suffix, "hex": hex_suffix, "hash": hash_suffix} + top_levels = {"chia"} + found_stems = { + name: { + path.with_name(path.name[: -len(suffix)]) + for top_level in top_levels + for path in root.joinpath(top_level).rglob(f"**/*{suffix}") + } + for name, suffix in suffixes.items() + } + for name in ["hex", "hash"]: + found = found_stems[name] + suffix = suffixes[name] + extra = found - found_stems["clvm"] + + print() + print(f"Extra {suffix} files:") + + if len(extra) == 0: + print(" -") + else: + overall_fail = True + for stem in extra: + print(f" {stem.with_name(stem.name + suffix)}") + + print() + print("Checking that all existing .clvm files compile to .clvm.hex that match existing caches:") + for stem_path in sorted(found_stems["clvm"]): + clvm_path = stem_path.with_name(stem_path.name + clvm_suffix) + if clvm_path.name in excludes: + used_excludes.add(clvm_path.name) + continue + + file_fail = False + error = None + + try: + reference_paths = ClvmPaths.from_clvm(clvm=clvm_path) + reference_bytes = ClvmBytes.from_clvm_paths(paths=reference_paths) + + with tempfile.TemporaryDirectory() as temporary_directory: + generated_paths = ClvmPaths.from_clvm( + clvm=pathlib.Path(temporary_directory).joinpath(f"generated{clvm_suffix}") + ) + + compile_clvm( + input_path=os.fspath(reference_paths.clvm), + output_path=os.fspath(generated_paths.hex), + search_paths=[os.fspath(reference_paths.clvm.parent)], + ) + + generated_bytes = ClvmBytes.from_hex_bytes(hex_bytes=generated_paths.hex.read_bytes()) + + if generated_bytes != reference_bytes: + file_fail = True + error = f" reference: {reference_bytes!r}\n" + error += f" generated: {generated_bytes!r}" + except Exception: + file_fail = True + error = traceback.format_exc() + + if file_fail: + print(f"FAIL : {clvm_path}") + if error is not None: + print(error) + else: + print(f" pass: {clvm_path}") + + if file_fail: + overall_fail = True + + unused_excludes = sorted(excludes - used_excludes) + if len(unused_excludes) > 0: + overall_fail = True + print() + print("Unused excludes:") + + for exclude in unused_excludes: + print(f" {exclude}") + + return 1 if overall_fail else 0 + + +sys.exit(main()) diff --git a/tests/clvm/test_clvm_compilation.py b/tests/clvm/test_clvm_compilation.py deleted file mode 100644 index c2a2d5d4eb..0000000000 --- a/tests/clvm/test_clvm_compilation.py +++ /dev/null @@ -1,187 +0,0 @@ -from os import remove -from pathlib import Path -from tempfile import NamedTemporaryFile -from unittest import TestCase - -import pytest -from clvm_tools.clvmc import compile_clvm - -from chia.types.blockchain_format.program import Program, SerializedProgram - -pytestmark = pytest.mark.data_layer - - -wallet_program_files = set( - [ - "chia/wallet/puzzles/calculate_synthetic_public_key.clvm", - "chia/wallet/puzzles/cat_v2.clvm", - "chia/wallet/puzzles/chialisp_deserialisation.clvm", - "chia/wallet/puzzles/rom_bootstrap_generator.clvm", - "chia/wallet/puzzles/lock.inner.puzzle.clvm", - "chia/wallet/puzzles/p2_conditions.clvm", - "chia/wallet/puzzles/p2_delegated_conditions.clvm", - "chia/wallet/puzzles/p2_delegated_puzzle.clvm", - "chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.clvm", - "chia/wallet/puzzles/p2_m_of_n_delegate_direct.clvm", - "chia/wallet/puzzles/p2_puzzle_hash.clvm", - "chia/wallet/puzzles/rl_aggregation.clvm", - "chia/wallet/puzzles/rl.clvm", - "chia/wallet/puzzles/sha256tree_module.clvm", - "chia/wallet/puzzles/singleton_top_layer.clvm", - "chia/wallet/puzzles/did_innerpuz.clvm", - "chia/wallet/puzzles/decompress_puzzle.clvm", - "chia/wallet/puzzles/decompress_coin_spend_entry_with_prefix.clvm", - "chia/wallet/puzzles/decompress_coin_spend_entry.clvm", - "chia/wallet/puzzles/block_program_zero.clvm", - "chia/wallet/puzzles/test_generator_deserialize.clvm", - "chia/wallet/puzzles/test_multiple_generator_input_arguments.clvm", - "chia/wallet/puzzles/p2_singleton.clvm", - "chia/wallet/puzzles/pool_waitingroom_innerpuz.clvm", - "chia/wallet/puzzles/pool_member_innerpuz.clvm", - "chia/wallet/puzzles/singleton_launcher.clvm", - "chia/wallet/puzzles/p2_singleton_or_delayed_puzhash.clvm", - "chia/wallet/puzzles/genesis_by_puzzle_hash.clvm", - "chia/wallet/puzzles/everything_with_signature.clvm", - "chia/wallet/puzzles/delegated_tail.clvm", - "chia/wallet/puzzles/settlement_payments.clvm", - "chia/wallet/puzzles/genesis_by_coin_id.clvm", - "chia/wallet/puzzles/singleton_top_layer_v1_1.clvm", - "chia/wallet/puzzles/nft_metadata_updater_default.clvm", - "chia/wallet/puzzles/nft_metadata_updater_updateable.clvm", - "chia/wallet/puzzles/nft_state_layer.clvm", - "chia/wallet/puzzles/nft_ownership_layer.clvm", - "chia/wallet/puzzles/nft_ownership_transfer_program_one_way_claim_with_royalties.clvm", - "chia/wallet/puzzles/graftroot_dl_offers.clvm", - "chia/wallet/puzzles/p2_parent.clvm", - "chia/wallet/puzzles/decompress_block_spends.clvm", - ] -) - -clvm_include_files = set( - ["chia/wallet/puzzles/create-lock-puzzlehash.clvm", "chia/wallet/puzzles/condition_codes.clvm"] -) - -CLVM_PROGRAM_ROOT = "chia/wallet/puzzles" - - -def list_files(dir, glob): - dir = Path(dir) - entries = dir.glob(glob) - files = [f for f in entries if f.is_file()] - return files - - -def read_file(path): - with open(path) as f: - return f.read() - - -def path_with_ext(path, ext): - return Path(str(path) + ext) - - -class TestClvmCompilation(TestCase): - """ - These are tests, and not just build scripts to regenerate the bytecode, because - the developer must be aware if the compiled output changes, for any reason. - """ - - def test_all_programs_listed(self): - """ - Checks to see if a new .clvm file was added to chia/wallet/puzzles, but not added to `wallet_program_files` - """ - existing_files = list_files(CLVM_PROGRAM_ROOT, "*.clvm") - existing_file_paths = set([Path(x).relative_to(CLVM_PROGRAM_ROOT) for x in existing_files]) - - expected_files = set(clvm_include_files).union(set(wallet_program_files)) - expected_file_paths = set([Path(x).relative_to(CLVM_PROGRAM_ROOT) for x in expected_files]) - - self.assertEqual( - expected_file_paths, - existing_file_paths, - msg="Please add your new program to `wallet_program_files` or `clvm_include_files.values`", - ) - - def test_include_and_source_files_separate(self): - self.assertEqual(clvm_include_files.intersection(wallet_program_files), set()) - - # TODO: Test recompilation with all available compiler configurations & implementations - def test_all_programs_are_compiled(self): - """Checks to see if a new .clvm file was added without its .hex file""" - all_compiled = True - msg = "Please compile your program with:\n" - - # Note that we cannot test all existing .clvm files - some are not - # meant to be run as a "module" with load_clvm; some are include files - # We test for inclusion in `test_all_programs_listed` - for prog_path in wallet_program_files: - try: - output_path = path_with_ext(prog_path, ".hex") - hex = output_path.read_text() - self.assertTrue(len(hex) > 0) - except Exception as ex: - all_compiled = False - msg += f" run -i {prog_path.parent} -d {prog_path} > {prog_path}.hex\n" - print(ex) - msg += "and check it in" - self.assertTrue(all_compiled, msg=msg) - - def test_recompilation_matches(self): - self.maxDiff = None - for f in wallet_program_files: - f = Path(f) - compile_clvm(f, path_with_ext(f, ".recompiled"), search_paths=[f.parent]) - orig_hex = path_with_ext(f, ".hex").read_text().strip() - new_hex = path_with_ext(f, ".recompiled").read_text().strip() - self.assertEqual(orig_hex, new_hex, msg=f"Compilation of {f} does not match {f}.hex") - pass - - def test_all_compiled_programs_are_hashed(self): - """Checks to see if a .hex file is missing its .sha256tree file""" - all_hashed = True - msg = "Please hash your program with:\n" - for prog_path in wallet_program_files: - try: - hex = path_with_ext(prog_path, ".hex.sha256tree").read_text() - self.assertTrue(len(hex) > 0) - except Exception as ex: - print(ex) - all_hashed = False - msg += f" opd -H {prog_path}.hex | head -1 > {prog_path}.hex.sha256tree\n" - msg += "and check it in" - self.assertTrue(all_hashed, msg) - - # TODO: Test all available shatree implementations on all progams - def test_shatrees_match(self): - """Checks to see that all .sha256tree files match their .hex files""" - for prog_path in wallet_program_files: - # load the .hex file as a program - hex_filename = path_with_ext(prog_path, ".hex") - clvm_hex = hex_filename.read_text() # .decode("utf8") - clvm_blob = bytes.fromhex(clvm_hex) - s = SerializedProgram.from_bytes(clvm_blob) - p = Program.from_bytes(clvm_blob) - - # load the checked-in shatree - existing_sha = path_with_ext(prog_path, ".hex.sha256tree").read_text().strip() - - self.assertEqual( - s.get_tree_hash().hex(), - existing_sha, - msg=f"Checked-in shatree hash file does not match hash of loaded SerializedProgram: {prog_path}", - ) - self.assertEqual( - p.get_tree_hash().hex(), - existing_sha, - msg=f"Checked-in shatree hash file does not match shatree hash of loaded Program: {prog_path}", - ) - - def test_017_encoding_bug_fixed(self): - with NamedTemporaryFile(delete=False) as tf: - tf.write(b"10000000") - hexname = tf.name + ".hex" - compile_clvm(tf.name, hexname, []) - with open(hexname) as f: - self.assertEqual(f.read().strip(), "8400989680") - remove(tf.name) - remove(hexname)