"""Educational hash-linked records. No currency, consensus or real mining."""
from dataclasses import dataclass, replace
from hashlib import sha256
import json

@dataclass(frozen=True)
class Block:
    index: int
    data: str
    previous_hash: str

def digest(block):
    payload = json.dumps(
        {"index": block.index, "data": block.data,
         "previous_hash": block.previous_hash},
        sort_keys=True, separators=(",", ":"), ensure_ascii=False,
    ).encode("utf-8")
    return sha256(payload).hexdigest()

def append(chain, data):
    previous = digest(chain[-1]) if chain else "0" * 64
    chain.append(Block(len(chain), data, previous))

def valid(chain):
    previous = "0" * 64
    for index, block in enumerate(chain):
        if block.index != index or block.previous_hash != previous:
            return False
        previous = digest(block)
    return True

def check(condition, message):
    if not condition:
        raise AssertionError(message)

def self_test():
    chain = []
    for value in ["A sends B 10", "B sends C 4", "C sends D 1"]:
        append(chain, value)
    check(valid(chain), "original chain")
    tampered = chain.copy()
    tampered[0] = replace(tampered[0], data="A sends B 100")
    check(not valid(tampered), "interior tampering detected")
    last_changed = chain.copy()
    last_changed[-1] = replace(last_changed[-1], data="C sends D 999")
    check(valid(last_changed), "last payload has no later link to compare")
    check(digest(last_changed[-1]) != digest(chain[-1]), "trusted tip detects change")
    rebuilt = []
    for value in ["A sends B 100", "B sends C 4", "C sends D 1"]:
        append(rebuilt, value)
    check(valid(rebuilt), "full rewrite also passes local links")
    check(digest(rebuilt[-1]) != digest(chain[-1]), "different trusted tip")
    print("Toy chain: all checks passed")

if __name__ == "__main__":
    self_test()
