Add .clvm.hex pre-commit check (#12050)

* Add .clvm.hex pre-commit check

* report all results

* stuff

* maybe pass

* add todo

* explicitly define suffixes

* check for (and remove) extra hex and hash files

* remove garbage failure hex and hash files

* provide runner scripts

* matrix pre-commit checks

* maybe now

* more cross platform

* move it

* oops

* shell:

* maybe

* more configurable

* explicitly specify powershell

* tidy

* remove other stuff

* tidy

* remove existing pytest clvm hex etc checker

* add a trailing newline to decompress_block_spends.clvm.hex.sha256tree

* Update activated.ps1

* git config --global core.autocrlf false

* Update pre-commit.yml

* only check `chia/`

* typing_extensions

* typing_extensions

* removing unused typing import

* move top_level out of the rglob

* catchup dl clvm hex files

* Revert "catchup dl clvm hex files"

This reverts commit cd3d4f70b8.

* now
This commit is contained in:
Kyle Altendorf 2022-09-12 17:08:55 -04:00 committed by GitHub
parent e588566045
commit 789ee4f415
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 194 additions and 204 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1 +0,0 @@
can't compile ("defconstant" "AGG_SIG_UNSAFE" 49), unknown operator

View File

@ -1 +0,0 @@
ff02ffff01ff04ffff04ff38ffff04ffff02ff3affff04ff02ffff04ff05ffff04ffff02ff2effff04ff02ffff04ff17ffff04ffff02ff26ffff04ff02ffff04ff2fff80808080ff8080808080ff8080808080ffff04ff27ff80808080ffff02ff32ffff04ff02ffff04ff0bffff04ff2fffff01ff01808080808080ffff04ffff01ffffff32ff0233ffff0401ff0102ffffffff02ffff03ff05ffff01ff02ff22ffff04ff02ffff04ff0dffff04ffff0bff3cffff0bff34ff2480ffff0bff3cffff0bff3cffff0bff34ff2c80ff0980ffff0bff3cff0bffff0bff34ff8080808080ff8080808080ffff010b80ff0180ff02ffff03ff0bffff01ff04ffff04ff38ffff04ffff02ff2affff04ff02ffff04ff05ffff04ffff04ffff04ff17ff1380ff8080ff8080808080ffff01ff80808080ffff04ffff04ff10ffff04ff23ffff04ffff02ff3effff04ff02ffff04ffff04ff13ffff04ff17ff808080ff80808080ff80808080ffff02ff32ffff04ff02ffff04ff05ffff04ff1bffff04ffff10ff17ffff010180ff8080808080808080ff8080ff0180ffff02ff36ffff04ff02ffff04ff05ffff04ffff02ff3effff04ff02ffff04ff0bff80808080ff8080808080ff02ff36ffff04ff02ffff04ff05ffff04ffff02ff3effff04ff02ffff04ff0bff80808080ffff04ffff02ff3effff04ff02ffff04ff05ff80808080ff808080808080ffffff02ffff03ffff07ff0580ffff01ff04ff29ffff02ff26ffff04ff02ffff04ff0dff8080808080ff8080ff0180ff0bff3cffff0bff34ff2880ffff0bff3cffff0bff3cffff0bff34ff2c80ff0580ffff0bff3cffff02ff22ffff04ff02ffff04ff07ffff04ffff0bff34ff3480ff8080808080ffff0bff34ff8080808080ffff02ffff03ffff07ff0b80ffff01ff10ff13ffff02ff2effff04ff02ffff04ff05ffff04ff1bff808080808080ffff011580ff0180ff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff3effff04ff02ffff04ff09ff80808080ffff02ff3effff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ff018080

View File

@ -1 +0,0 @@
can't compile ("my-id"), unknown operator

View File

@ -1 +1 @@
f890a7866079009517ae0b652d530268d2531bbac99670aaba461d604bc0ff0c
f890a7866079009517ae0b652d530268d2531bbac99670aaba461d604bc0ff0c

View File

@ -1 +1 @@
1720d13250a7c16988eaf530331cefa9dd57a76b2c82236bec8bbbff91499b89
1720d13250a7c16988eaf530331cefa9dd57a76b2c82236bec8bbbff91499b89

View File

@ -1 +1 @@
493afb89eed93ab86741b2aa61b8f5de495d33ff9b781dfc8919e602b2afa150
493afb89eed93ab86741b2aa61b8f5de495d33ff9b781dfc8919e602b2afa150

View File

@ -1 +1 @@
de5a6e06d41518be97ff6365694f4f89475dda773dede267caa33da63b434e36
de5a6e06d41518be97ff6365694f4f89475dda773dede267caa33da63b434e36

View File

@ -1 +1 @@
0893e36a88c064fddfa6f8abdb42c044584a98cb4273b80cccc83b4867b701a1
0893e36a88c064fddfa6f8abdb42c044584a98cb4273b80cccc83b4867b701a1

View File

@ -1 +0,0 @@
ff02ffff01ff04ffff04ffff013effff04ffff02ff02ffff04ff02ffff04ff05ff80808080ff808080ff8080ffff04ffff01ff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff02ffff04ff02ffff04ff09ff80808080ffff02ff02ffff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ff018080

View File

@ -1 +0,0 @@
3df9de54667a96f32eba322635f14d3474edadf23f396ba5a3e2e077a89a682a

View File

@ -1 +1 @@
ff02ffff01ff04ffff04ffff02ffff03ffff22ff27ff3780ffff01ff02ffff03ffff21ffff09ff27ffff01826d7580ffff09ff27ffff01826c7580ffff09ff27ffff01758080ffff01ff02ff02ffff04ff02ffff04ff05ffff04ff27ffff04ff37ff808080808080ffff010580ff0180ffff010580ff0180ffff04ff0bff808080ffff01ff808080ffff04ffff01ff02ffff03ff05ffff01ff02ffff03ffff09ff11ff0b80ffff01ff04ffff04ff0bffff04ff17ff198080ff0d80ffff01ff04ff09ffff02ff02ffff04ff02ffff04ff0dffff04ff0bffff04ff17ff8080808080808080ff0180ff8080ff0180ff018080
ff02ffff01ff04ffff04ffff02ffff03ffff22ff27ff3780ffff01ff02ffff03ffff21ffff09ff27ffff01826d7580ffff09ff27ffff01826c7580ffff09ff27ffff01758080ffff01ff02ff02ffff04ff02ffff04ff05ffff04ff27ffff04ff37ff808080808080ffff010580ff0180ffff010580ff0180ffff04ff0bff808080ffff01ff808080ffff04ffff01ff02ffff03ff05ffff01ff02ffff03ffff09ff11ff0b80ffff01ff04ffff04ff0bffff04ff17ff198080ff0d80ffff01ff04ff09ffff02ff02ffff04ff02ffff04ff0dffff04ff0bffff04ff17ff8080808080808080ff0180ff8080ff0180ff018080

View File

@ -1 +1 @@
ff02ffff01ff04ffff04ffff02ffff03ff27ffff01ff02ff02ffff04ff02ffff04ff05ffff04ff27ff8080808080ffff010580ff0180ffff04ffff02ffff03ffff09ffff0dff5780ffff012080ffff0157ffff010b80ff0180ff808080ffff01ff808080ffff04ffff01ff02ffff03ff05ffff01ff02ffff03ffff09ff11ffff017580ffff01ff04ffff04ffff0175ffff04ff0bff198080ff0d80ffff01ff04ff09ffff02ff02ffff04ff02ffff04ff0dffff04ff0bff80808080808080ff0180ff8080ff0180ff018080
ff02ffff01ff04ffff04ffff02ffff03ff27ffff01ff02ff02ffff04ff02ffff04ff05ffff04ff27ff8080808080ffff010580ff0180ffff04ffff02ffff03ffff09ffff0dff5780ffff012080ffff0157ffff010b80ff0180ff808080ffff01ff808080ffff04ffff01ff02ffff03ff05ffff01ff02ffff03ffff09ff11ffff017580ffff01ff04ffff04ffff0175ffff04ff0bff198080ff0d80ffff01ff04ff09ffff02ff02ffff04ff02ffff04ff0dffff04ff0bff80808080808080ff0180ff8080ff0180ff018080

View File

@ -1 +1 @@
c5abea79afaa001b5427dfa0c8cf42ca6f38f5841b78f9b3c252733eb2de2726
c5abea79afaa001b5427dfa0c8cf42ca6f38f5841b78f9b3c252733eb2de2726

View File

@ -1 +1 @@
ff02ffff01ff04ffff04ff04ffff04ff05ffff04ffff02ff06ffff04ff02ffff04ff0bff80808080ff80808080ff0b80ffff04ffff01ff32ff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff06ffff04ff02ffff04ff09ff80808080ffff02ff06ffff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ff018080
ff02ffff01ff04ffff04ff04ffff04ff05ffff04ffff02ff06ffff04ff02ffff04ff0bff80808080ff80808080ff0b80ffff04ffff01ff32ff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff06ffff04ff02ffff04ff09ff80808080ffff02ff06ffff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ff018080

View File

@ -1 +1 @@
b10ce2d0b18dcf8c21ddfaf55d9b9f0adcbf1e0beb55b1a8b9cad9bbff4e5f22
b10ce2d0b18dcf8c21ddfaf55d9b9f0adcbf1e0beb55b1a8b9cad9bbff4e5f22

View File

@ -1 +1 @@
ff02ffff01ff02ffff03ffff09ff81bfff2480ffff01ff04ffff04ff30ffff04ff5fffff04ffff02ff3effff04ff02ffff04ffff04ff81bfff81ff80ff80808080ff80808080ff81ff80ffff01ff04ffff04ff30ffff04ff05ffff04ffff02ff3effff04ff02ffff04ffff04ff81bfff81ff80ff80808080ff80808080ffff02ffff03ffff09ff81bfff3c80ffff01ff02ff2effff04ff02ffff04ff0bffff04ff17ffff04ff2fffff04ff81ffff80808080808080ffff01ff02ff22ffff04ff02ffff04ff2fffff04ff81ffff808080808080ff01808080ff0180ffff04ffff01ffffffffff02ffff03ffff15ff05ff0b80ffff01ff0101ffff01ff02ffff03ffff09ff05ff0b80ffff01ff0101ff8080ff018080ff018031ff5246ffff0333ff3c01ffffffff02ffff03ffff02ffff03ffff09ffff0bff820bfbff13ff8205fb80ff82017b80ffff01ff0101ffff01ff02ffff03ffff09ff05ff82017b80ffff01ff0101ff8080ff018080ff0180ffff01ff04ffff02ff26ffff04ff02ffff04ff82017bffff04ff13ffff04ff8202fbff808080808080ffff04ffff02ff2affff04ff02ffff04ff2bffff04ff5bffff04ff81bbff808080808080ffff04ffff02ff3affff04ff02ffff04ff13ffff04ffff10ff81bbff8202fb80ff8080808080ff80808080ffff01ffff08808080ff0180ff04ff34ffff04ff05ffff04ffff11ff0bffff10ff17ff2f8080ff80808080ffff04ff2cffff04ffff0bff05ff0bff1780ff808080ff04ff34ffff04ff05ffff04ff0bff80808080ffffff04ff38ffff04ffff0bff05ff0bff1780ff808080ff02ffff03ffff02ff20ffff04ff02ffff04ffff12ff05ff1780ffff04ffff12ff0bff2f80ff8080808080ffff01ff04ff28ffff04ff05ff808080ffff01ffff08808080ff0180ffff02ffff03ffff02ffff03ffff09ffff0bff8217efff81afff822fef80ff4f80ffff01ff0101ffff01ff02ffff03ffff09ff17ff4f80ffff01ff0101ff8080ff018080ff0180ffff01ff04ffff02ff36ffff04ff02ffff04ff820befffff04ff8205efffff04ff05ffff04ff0bff80808080808080ffff04ffff02ff32ffff04ff02ffff04ff81afffff04ff82016fffff04ff8205efffff04ff825fefff80808080808080ffff04ffff02ff26ffff04ff02ffff04ff4fffff04ff81afffff04ff82016fff808080808080ffff04ffff02ff3affff04ff02ffff04ff8202efffff04ff8205efff8080808080ff8080808080ffff01ffff08808080ff0180ff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff3effff04ff02ffff04ff09ff80808080ffff02ff3effff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ff018080
ff02ffff01ff02ffff03ffff09ff81bfff2480ffff01ff04ffff04ff30ffff04ff5fffff04ffff02ff3effff04ff02ffff04ffff04ff81bfff81ff80ff80808080ff80808080ff81ff80ffff01ff04ffff04ff30ffff04ff05ffff04ffff02ff3effff04ff02ffff04ffff04ff81bfff81ff80ff80808080ff80808080ffff02ffff03ffff09ff81bfff3c80ffff01ff02ff2effff04ff02ffff04ff0bffff04ff17ffff04ff2fffff04ff81ffff80808080808080ffff01ff02ff22ffff04ff02ffff04ff2fffff04ff81ffff808080808080ff01808080ff0180ffff04ffff01ffffffffff02ffff03ffff15ff05ff0b80ffff01ff0101ffff01ff02ffff03ffff09ff05ff0b80ffff01ff0101ff8080ff018080ff018031ff5246ffff0333ff3c01ffffffff02ffff03ffff02ffff03ffff09ffff0bff820bfbff13ff8205fb80ff82017b80ffff01ff0101ffff01ff02ffff03ffff09ff05ff82017b80ffff01ff0101ff8080ff018080ff0180ffff01ff04ffff02ff26ffff04ff02ffff04ff82017bffff04ff13ffff04ff8202fbff808080808080ffff04ffff02ff2affff04ff02ffff04ff2bffff04ff5bffff04ff81bbff808080808080ffff04ffff02ff3affff04ff02ffff04ff13ffff04ffff10ff81bbff8202fb80ff8080808080ff80808080ffff01ffff08808080ff0180ff04ff34ffff04ff05ffff04ffff11ff0bffff10ff17ff2f8080ff80808080ffff04ff2cffff04ffff0bff05ff0bff1780ff808080ff04ff34ffff04ff05ffff04ff0bff80808080ffffff04ff38ffff04ffff0bff05ff0bff1780ff808080ff02ffff03ffff02ff20ffff04ff02ffff04ffff12ff05ff1780ffff04ffff12ff0bff2f80ff8080808080ffff01ff04ff28ffff04ff05ff808080ffff01ffff08808080ff0180ffff02ffff03ffff02ffff03ffff09ffff0bff8217efff81afff822fef80ff4f80ffff01ff0101ffff01ff02ffff03ffff09ff17ff4f80ffff01ff0101ff8080ff018080ff0180ffff01ff04ffff02ff36ffff04ff02ffff04ff820befffff04ff8205efffff04ff05ffff04ff0bff80808080808080ffff04ffff02ff32ffff04ff02ffff04ff81afffff04ff82016fffff04ff8205efffff04ff825fefff80808080808080ffff04ffff02ff26ffff04ff02ffff04ff4fffff04ff81afffff04ff82016fff808080808080ffff04ffff02ff3affff04ff02ffff04ff8202efffff04ff8205efff8080808080ff8080808080ffff01ffff08808080ff0180ff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff3effff04ff02ffff04ff09ff80808080ffff02ff3effff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ff018080

167
tests/check_clvm.py Normal file
View File

@ -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())

View File

@ -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)