Workspace IndexAlgorithms › Day 62

Light Clients and Stateless Verification TODO

Algorithms · Day 62 / 100 · D. Distributed Systems & Consensus (Day 52-68)

Concept

A light client is a node that follows only the chain of block headers, without storing or executing full blocks and state, and verifies specific facts using Merkle proofs. It treats a header's state root as its anchor of trust: given an inclusion proof that some account balance or storage value belongs under that root, it recomputes the hashes locally to confirm it. The legitimacy of the header itself has to come from the consensus layer — on a PoS chain, the light client follows headers via lightweight proofs over the validator signature set. Stateless verification goes a step further: the block arrives together with a witness — the state fragments needed to execute it, plus their proofs — so the block can be re-executed and verified without a state database at all. The bottleneck of this approach is witness size; because Merkle Patricia tries have a wide branching factor, their proofs are large, which is why smaller commitment structures such as Verkle trees or STARK-based proofs are being researched and adopted.

In environments that can't run a full node — mobile, browser, cross-chain bridges — light client verification is the only realistic way to minimize trust assumptions.

Code & Formula

# 라이트 클라이언트와 상태 없는(stateless) 검증 — Merkle 증명 하나로 전체 데이터 없이 포함 여부를 검증한다.
# 전체 트리를 갖지 않고도 leaf + 형제 해시 경로(proof) + 루트만으로 위조 여부를 탐지한다.

import hashlib

def h(*parts):
    return hashlib.sha256(b"".join(parts)).digest()

def merkle_root(leaves):
    layer = leaves
    while len(layer) > 1:
        layer = [h(layer[i], layer[i + 1]) for i in range(0, len(layer), 2)]
    return layer[0]

def merkle_proof(leaves, index):
    proof = []
    layer, idx = leaves, index
    while len(layer) > 1:
        sibling_idx = idx ^ 1
        is_left = sibling_idx < idx           # 형제가 왼쪽에 있는지
        proof.append((layer[sibling_idx], is_left))
        layer = [h(layer[i], layer[i + 1]) for i in range(0, len(layer), 2)]
        idx //= 2
    return proof

def verify(leaf, proof, root):
    computed = leaf
    for sibling, is_left in proof:
        computed = h(sibling, computed) if is_left else h(computed, sibling)
    return computed == root

accounts = [f"account-{i}:balance={i * 100}".encode() for i in range(8)]
leaves = [h(a) for a in accounts]
root = merkle_root(leaves)

target_index = 5
proof = merkle_proof(leaves, target_index)

# 라이트 클라이언트: 전체 accounts 리스트 없이, leaf 하나 + proof + root만으로 검증
print("헤더의 상태 루트:", root.hex())
print("account-5 포함 증명 검증:", verify(leaves[target_index], proof, root))

# 공격자가 값을 조작한 leaf를 제시하면 검증에 실패해야 한다
forged_leaf = h(b"account-5:balance=999999")
print("조작된 leaf 검증(실패해야 정상):", verify(forged_leaf, proof, root))

Exercise

Fetch a proof for a specific account via eth_getProof, then write a script that walks the hashes yourself — without trusting the node — to verify they match the header's stateRoot.

Practical Connection

If Verex's frontend or settlement watcher verifies positions and settlement results with state proofs instead of trusting RPC responses at face value, the RPC provider can be removed from the trust set entirely.

If you study this on a given day, add a note link and a ✅ to this line in the source curriculum (docs/knowledge/dev-100-curriculum.md) and this spot will lead straight to the note body. You can also write directly on this page — but regenerating overwrites it, so it's safer to keep anything you want to save as markdown under docs/algorithms/.


한국어

라이트 클라이언트와 상태 없는(stateless) 검증 TODO

Algorithms · Day 62 / 100 · D. 분산시스템·합의 (Day 52–68)

개념

라이트 클라이언트는 전체 블록과 상태를 보관·실행하지 않고, 블록 헤더 체인만 따라가면서 특정 사실을 Merkle 증명으로 검증하는 노드다. 헤더의 상태 루트를 신뢰의 앵커로 삼아, 어떤 계정 잔액이나 스토리지 값이 그 루트에 포함된다는 포함 증명을 받아 로컬에서 해시로 재계산해 확인한다. 여기서 헤더 자체의 정당성은 합의 계층에서 얻어야 하며, PoS 체인에서는 검증자 서명 집합에 대한 경량 증명을 통해 헤더를 따라간다. 상태 없는(stateless) 검증은 여기서 한 걸음 더 나아가, 블록 실행에 필요한 상태 조각과 그 증명을 witness로 블록과 함께 받아 상태 DB 없이도 블록을 재실행·검증하는 방식이다. 이 접근의 병목은 witness 크기이며, Merkle Patricia 트리는 분기 계수 때문에 증명이 커서 Verkle 트리나 STARK 기반 증명 같은 더 작은 커밋먼트 구조가 연구·도입 대상이 된다.

모바일·브라우저·크로스체인 브리지처럼 풀노드를 돌릴 수 없는 환경에서 신뢰 가정을 최소화하려면 라이트 클라이언트 검증이 유일한 현실적 수단이다.

코드 · 수식

# 라이트 클라이언트와 상태 없는(stateless) 검증 — Merkle 증명 하나로 전체 데이터 없이 포함 여부를 검증한다.
# 전체 트리를 갖지 않고도 leaf + 형제 해시 경로(proof) + 루트만으로 위조 여부를 탐지한다.

import hashlib

def h(*parts):
    return hashlib.sha256(b"".join(parts)).digest()

def merkle_root(leaves):
    layer = leaves
    while len(layer) > 1:
        layer = [h(layer[i], layer[i + 1]) for i in range(0, len(layer), 2)]
    return layer[0]

def merkle_proof(leaves, index):
    proof = []
    layer, idx = leaves, index
    while len(layer) > 1:
        sibling_idx = idx ^ 1
        is_left = sibling_idx < idx           # 형제가 왼쪽에 있는지
        proof.append((layer[sibling_idx], is_left))
        layer = [h(layer[i], layer[i + 1]) for i in range(0, len(layer), 2)]
        idx //= 2
    return proof

def verify(leaf, proof, root):
    computed = leaf
    for sibling, is_left in proof:
        computed = h(sibling, computed) if is_left else h(computed, sibling)
    return computed == root

accounts = [f"account-{i}:balance={i * 100}".encode() for i in range(8)]
leaves = [h(a) for a in accounts]
root = merkle_root(leaves)

target_index = 5
proof = merkle_proof(leaves, target_index)

# 라이트 클라이언트: 전체 accounts 리스트 없이, leaf 하나 + proof + root만으로 검증
print("헤더의 상태 루트:", root.hex())
print("account-5 포함 증명 검증:", verify(leaves[target_index], proof, root))

# 공격자가 값을 조작한 leaf를 제시하면 검증에 실패해야 한다
forged_leaf = h(b"account-5:balance=999999")
print("조작된 leaf 검증(실패해야 정상):", verify(forged_leaf, proof, root))

연습

eth_getProof로 특정 계정의 증명을 받아, 노드를 믿지 않고 직접 해시를 따라 올라가 헤더의 stateRoot와 일치하는지 검증하는 스크립트를 작성해 볼 것.

실무 · Verex 연결

Verex의 프론트엔드나 정산 감시자가 RPC 응답을 그대로 믿는 대신 상태 증명으로 포지션·정산 결과를 검증하면, RPC 제공자를 신뢰 대상에서 제거할 수 있다.

공부한 날 원본 커리큘럼(docs/knowledge/dev-100-curriculum.md)의 이 줄에 노트 링크와 ✅ 를 붙이면, 이 자리는 노트 본문으로 바로 이어집니다. 노트 없이 이 페이지에 바로 적어도 됩니다 — 다만 다시 생성하면 덮어쓰이므로, 남길 글은 docs/algorithms/ 의 마크다운으로 쓰는 편이 안전합니다.

← 61. 데이터 가용성 샘플링과 소거부호(Reed-Solomon)63. 크로스체인 신뢰 가정 분류 →