5 · 보안
XChain의 보안은 체인 단위가 아니라 자산 단위입니다. 모든 자산이 최소 보안 등급을 지니며, 고가치 자산은 애초에 데이터 도메인에 존재할 수 없습니다. 이것이 ‘등급 낮추기’ 공격을 구조적으로 불가능하게 만들고, 가치의 안전을 작은 검증자 집합에 대한 신뢰가 아니라 암호와 자본 위에 놓습니다.
고가치를 위한 세 겹
고가치(T0–T1)에는 세 겹이 결합합니다:
- ZK 유효성 증명 — 위원회가 완전히 장악당해도 무효한 상태를 위조할 수 없습니다. 잃는 것은 라이브니스이지 안전성이 아닙니다.
- 글로벌 restaking — 어느 체인에서의 부정이든 글로벌 자본을 슬래싱합니다.
- Watcher / 사기 증명 — 탐지와 이의 제기.
가치가 낮은 데이터(T3–T4)는 발행 증명(proof-of-publication)만으로 보호됩니다. 세 가지 체인 보안 등급이 이 범위를 덮고, 그 위에 pessimistic proof가 장애 격리를 제공합니다. 문제를 일으킨 체인은 자기 몫만 잃을 수 있습니다.
| 보안 등급 | 적용 대상 | 무엇이 뒷받침하나 | 고가치를 나를 수 있나? |
|---|---|---|---|
| SOVEREIGN | T3–T4 · 데이터 도메인 | 자체 검증자 + 발행 증명 | 불가 — UAC가 구조적으로 금지 |
| SHARED | T1–T2 · Execution | Partial Set Security — 빌려온 검증자 집합 | 가능, 그 등급 한도까지 |
| ZK_SECURED | T0–T1 · Settlement / Value | 유효성 증명 필수 + 글로벌 restaking + watchers | 가능 — 최상위 등급 |
그림 5 — 가치에 맞춘 보안 지출: 가치 도메인에는 세 겹, 가장자리에는 발행 증명만.
검증은 실제로 얼마나 드는가
“다시 실행하지 말고 검증하라”는 누군가 재 보기 전까지는 주장일 뿐입니다. 그래서 숫자를 냅니다. 이것들은 실제 Groth16/BN254 검증 경로 — master 에 병합되어 devnet 노드에서 엔드투엔드로 증명된 그 경로 — 에서 나온 값입니다. ⚠️ 이것은 공개 테스트넷에 대한 설명이 아닙니다. 그쪽은 여전히 업그레이드 전 바이너리와 MOCK prover로 돌아가며, 그 구분은 현황과 라이브 네트워크 에서 추적하고 여기서 얼버무리지 않습니다.
| 측정 항목 | 값 | 왜 중요한가 |
|---|---|---|
| 상태 전이 증명서 1건 검증 | ~1.19 ms (BN254 페어링 1회, 순수 Go, DeliverTx 내부) | 블록 주기 3,000 ms 에서 검증이 병목이 되기 전까지 블록당 약 2,500건을 검증할 수 있습니다 |
공개 입력 MiMC(prev,tx,new) 계산 | ~14 µs | 체인이 스스로 유도하므로 증명이 하나의 전이에 묶이고 다른 전이에 재사용될 수 없습니다 |
groth16.Verify 비용과 회로 규모의 관계 | 일정 — 공개 입력 개수와도, 제약 개수와도 무관 | 따라서 1.19 ms라는 값은 현재의 임시 회로뿐 아니라 진짜 SP1 검증 키에도 그대로 해당합니다 |
| 증명 생성 (SP1 wrap → Groth16) | 약 1,597만 제약, 약 21.5 GB 메모리 | 구조상 오프체인 — 검증자 위에서 도는 일이 결코 없습니다. 생성에는 prover 네트워크나 64 GB 이상 머신이 필요합니다 |
이 비대칭이 곧 이 아키텍처의 요점입니다. 증명을 만드는 일은 전용 인프라가 필요할 만큼 무겁고, 확인하는 일은 블록 주기와 무관할 만큼 가볍습니다. 그래서 가장자리 물량이 늘어도 Root의 비용이 거의 일정하게 유지됩니다 — 그리고 같은 이유로 prover 공급이 해결된 셈 치지 않고 미해결 과제 에 경제적 난제로 솔직히 올라 있습니다.
실제로 단단하게 만든다는 것
세 가지 성질이 하중을 받고 있으며, 각각은 주장이 아니라 확인된 것입니다:
결정성. 검증기는 부동소수점도 난수도 쓰지 않습니다. 이는 사소한 배려가 아닙니다. 어느 검증자가 다른 결과를 내면 app hash가 갈리고 체인이 멈춥니다. 같은 검증을 여러 번 반복해 동일한 결과가 나오는지로 확인하고, 두 검증자가 블록 안에서 진짜 증명을 검증한 뒤 같은 app hash에 이르는 엔드투엔드 실행으로도 확인합니다.
쓰레기를 우아하게 거부하기. 트랜잭션에서 오는 것은 모두 적대적 입력이고, DeliverTx 안에서는 패닉도 멈춤도 곧 체인 정지입니다. 퍼징이 진짜 사례를 하나 찾아냈습니다. 증명 디코더가 신뢰할 수 없는 nbCommitments 필드를 읽어 그 값대로 할당하고 있었고, 공격자가 이를 약 40억으로 잡으면 약 256 GB 할당을 유발할 수 있었습니다 — 체인을 세울 수 있는, 트랜잭션 단위 서비스 거부였습니다. 수정은 증명이 암호 라이브러리에 닿기 전에 결정적인 형태 가드를 두는 것입니다(정확히 기대한 길이, 커밋먼트 수 0). 타임아웃 방식은 결정성을 깨뜨리므로 기각했습니다. 수정 후: 깨끗한 퍼징 실행 426만 회, 예전에 멈추게 하던 입력은 1초 안에 끝나는 회귀 테스트로 남았고, 실제 노드에서는 악의적 입력을 거부하면서 계속 블록을 생성합니다.
자기가 일으킨 일에 값을 치르기. 더 미묘한 발견도 있었습니다. 진짜 증명과 MOCK 사이의 가스 차이(약 48,191 대 약 40,638)는 검증이 실제로 쓰는 약 1.19 ms의 CPU가 아니라 거의 전부 더 큰 증명을 저장하는 것에서 왔습니다 — 가스는 저장 연산에 매겨지고 핸들러 안의 순수 계산에는 매겨지지 않기 때문입니다. 그래서 공격자는 형식은 맞지만 무효한 증명을 뿌려 진짜 CPU를 싸게 살 수 있었습니다. 수정은 검증을 수행하기 전에 그 비용을 명시적으로 청구해, 수수료가 가한 비용을 반영하게 하는 것입니다.
이 중 어느 것도 설계를 들여다보며 추론해서 찾은 것이 아니라, 돌려 봐서 찾은 것입니다. 공개 테스트넷이 존재하는 이유가 이 한 문단입니다.
요점: 각 자산에 보안 등급을 묶는 것이 쐐기돌입니다 — “가치를 엉뚱한 곳에 두지 말라”를 지침에서 구조적 보장으로 바꿉니다. 지금까지 말한 모든 보장 — 도메인 경계, READ/WRITE 분리, 자산별 등급 — 은 감사하고 신뢰할 만큼 작은 어딘가에서 강제되어야 합니다. 그곳이 좁은 허리, 곧 다음에 규정할 일곱 가지 원시 요소입니다.