Workspace IndexDev Notes › Simplicity CTF

#98PoC

Simplicity CTF

Blockstream's first Simplicity CTF — unlock 0.01 LBTC (~$600) locked in a contract for the reward; hands-on practice with Simplicity, the new smart-contract language for Bitcoin/Liquid.

Not yet scoped — for later. github.com/Arvolear/simplicity-ctf (added 2026-07-07)

Why

A hands-on way to actually learn Simplicity rather than just read about it.

How it works

Blockstream's first Simplicity CTF — solve it to unlock 0.01 LBTC (~$600) locked in a contract.

Related code

"""Simplicity CTF: a toy combinator evaluator in Simplicity's spirit --
small pure functions composed (not a stack of imperative statements) to
check an unlock condition, mirroring the CTF's "unlock the locked LBTC" goal.
"""

# Combinators: each takes an "environment" (witness bytes) and returns a value.
def unit(_env):
    return ()

def iden(env):
    return env

def comp(f, g):
    """Sequential composition: g after f."""
    return lambda env: g(f(env))

def pair(f, g):
    """Parallel composition: run f and g on the same input, pair results."""
    return lambda env: (f(env), g(env))

def case(f, g):
    """Branch on a boolean-tagged input: (True, x) -> f(x), (False, x) -> g(x)."""
    def run(env):
        tag, value = env
        return f(value) if tag else g(value)
    return run


# Build an unlock condition purely by combinator composition, Simplicity-style:
# witness = (has_preimage, preimage_bytes)
SECRET_HASH = hash("liquid-bitcoin-secret") & 0xFFFF

def check_preimage(preimage):
    return (hash(preimage) & 0xFFFF) == SECRET_HASH

def reject(_env):
    return False

unlock_program = case(
    f=lambda preimage: check_preimage(preimage),  # tag=True branch: verify preimage
    g=reject,                                       # tag=False branch: always fail
)

for label, witness in [
    ("correct preimage", (True, "liquid-bitcoin-secret")),
    ("wrong preimage", (True, "guess")),
    ("no preimage supplied", (False, None)),
]:
    unlocked = unlock_program(witness)
    print(f"{label}: witness={witness} -> unlocked={unlocked}")

← All Dev Notes · Workspace Index · Top ↑

Simplicity CTF 나중에 도전

Blockstream의 첫 Simplicity CTF — 컨트랙트에 잠긴 0.01 LBTC(~$600) 해제하면 보상. Simplicity(비트코인/Liquid용 신 스마트컨트랙트 언어) 실전 학습 기회.

아직 범위 미정 — 시간 날 때 도전. github.com/Arvolear/simplicity-ctf (7/7 추가)

Simplicity 실전 학습 기회 — 시간 날 때 도전.

동작 방식

Blockstream의 첫 Simplicity CTF — 컨트랙트에 잠긴 0.01 LBTC(~$600) 해제하면 보상.

관련 코드

"""Simplicity CTF: a toy combinator evaluator in Simplicity's spirit --
small pure functions composed (not a stack of imperative statements) to
check an unlock condition, mirroring the CTF's "unlock the locked LBTC" goal.
"""

# Combinators: each takes an "environment" (witness bytes) and returns a value.
def unit(_env):
    return ()

def iden(env):
    return env

def comp(f, g):
    """Sequential composition: g after f."""
    return lambda env: g(f(env))

def pair(f, g):
    """Parallel composition: run f and g on the same input, pair results."""
    return lambda env: (f(env), g(env))

def case(f, g):
    """Branch on a boolean-tagged input: (True, x) -> f(x), (False, x) -> g(x)."""
    def run(env):
        tag, value = env
        return f(value) if tag else g(value)
    return run


# Build an unlock condition purely by combinator composition, Simplicity-style:
# witness = (has_preimage, preimage_bytes)
SECRET_HASH = hash("liquid-bitcoin-secret") & 0xFFFF

def check_preimage(preimage):
    return (hash(preimage) & 0xFFFF) == SECRET_HASH

def reject(_env):
    return False

unlock_program = case(
    f=lambda preimage: check_preimage(preimage),  # tag=True branch: verify preimage
    g=reject,                                       # tag=False branch: always fail
)

for label, witness in [
    ("correct preimage", (True, "liquid-bitcoin-secret")),
    ("wrong preimage", (True, "guess")),
    ("no preimage supplied", (False, None)),
]:
    unlocked = unlock_program(witness)
    print(f"{label}: witness={witness} -> unlocked={unlocked}")

← 전체 개발 노트 · 워크스페이스 인덱스 · 맨 위 ↑