diff options
| author | eunhhu <[email protected]> | 2026-10-13 05:08:06 +0100 |
|---|---|---|
| committer | eunhhu <[email protected]> | 2026-10-13 05:08:06 +0100 |
| commit | 41a2e5c65dc92a0c47212efcb7f5dfef8443f9b2 (patch) | |
| tree | 5c3354e41a5f15b253d333de24dd1bae4037c77b /research/experiments/044-specs/check.py | |
| parent | 5a44af0308017f4e7b54a8ff6ccdc797b5d94015 (diff) | |
| download | pure-41a2e5c65dc92a0c47212efcb7f5dfef8443f9b2.tar.gz pure-41a2e5c65dc92a0c47212efcb7f5dfef8443f9b2.zip | |
Research 140, 027's stage 1 measured: SHA-256 written in aup (its examples/sha256.aup) right for FIPS 180-2's examples and 138 more messages on every path, in make check against hashlib; 52 lines against Python's 28 (the bar missed: no formatting, no bytes joined or sliced, no lists as values, moved into stage 2), 176 times C's time and 0.43 of plain Python's (1,591 ns a byte; a block's 19,129 instructions, 39% of them the inlined fn's literals not folded); 044's check, time.c against the same algorithm in C (digests compared first) and the Python reference
Diffstat (limited to 'research/experiments/044-specs/check.py')
| -rwxr-xr-x | research/experiments/044-specs/check.py | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/research/experiments/044-specs/check.py b/research/experiments/044-specs/check.py new file mode 100755 index 0000000..bc43090 --- /dev/null +++ b/research/experiments/044-specs/check.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +"""Research 140 / design 027 stage 1: SHA-256 written in aup (aup's examples/sha256.aup). + +Builds it with aup (AUP, default the sibling checkout), runs FIPS 180-2's +examples and messages of every length 0-129 and some longer ones on Pure's +three paths (batches, rounds, all compiled) and the default, each digest +against hashlib; then counts lines (code lines: neither blank nor a comment; +brace lines: a closing brace alone) of sha256.aup and of sha256.py's +algorithm (above its main). One JSON line.""" +import hashlib, json, os, random, subprocess, sys, tempfile + +here = os.path.dirname(os.path.abspath(__file__)) +pure = os.path.normpath(os.path.join(here, '../../..')) +aup = os.environ.get('AUP', os.path.join(pure, '..', 'aup')) + +def lines(path, stop=None): + code = braces = 0 + for line in open(path): + if stop and line.startswith(stop): break + text = line.strip() + if not text or text.startswith('#'): continue + code += 1 + braces += text == '}' + return code, braces + +random.seed(140) +messages = [b'', b'abc', b'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq', + b'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu'] +messages += [bytes(random.randrange(256) for _ in range(n)) for n in list(range(130)) + [255, 256, 511, 512, 1000, 4096, 10000, 32000]] +with tempfile.TemporaryDirectory() as tmp: + module = os.path.join(tmp, 'sha256.pmod') + subprocess.run([os.path.join(aup, 'build', 'aup'), 'build', os.path.join(aup, 'examples', 'sha256.aup'), '-o', module], check=True) + given = ''.join(f"message hash {m.hex() or '-'}\n" for m in messages).encode() + paths = {} + for name, env in (('batches', {'PURE_JIT': '0'}), ('rounds', {'PURE_JIT': '0', 'PURE_BATCH': '0'}), + ('all', {'PURE_JIT': 'all'}), ('default', {})): + out = subprocess.run([os.path.join(pure, 'build', 'pure-run'), module], input=given, capture_output=True, + env=dict(os.environ, **env), check=True).stdout.decode().splitlines() + paths[name] = sum(json.loads(o)['states']['digest'] == hashlib.sha256(m).hexdigest() and json.loads(o)['fault'] == 'none' + for m, o in zip(messages, out)) if len(out) == len(messages) else 0 +aup_code, aup_braces = lines(os.path.join(aup, 'examples', 'sha256.aup')) +python_code, _ = lines(os.path.join(here, 'sha256.py'), stop='if __name__') +ok = all(n == len(messages) for n in paths.values()) +print(json.dumps({'messages': len(messages), 'right': paths, 'aup_lines': aup_code, 'aup_brace_lines': aup_braces, + 'python_lines': python_code})) +sys.exit(0 if ok else 1) |
