작동 원리
호패는 온체인 레지스트리, 발급 서비스, SDK, 서피스의 4개 레이어로 구성됩니다. 신뢰의 원천은 GIWA 프리디플로이 EAS 위의 어테스테이션 하나입니다.
4레이어 아키텍처
| 레이어 | 구성요소 | 역할 |
|---|---|---|
| L1 · 온체인 | HopaeRegistry | EAS 기반 발급·폐기·검증. 레지스트리 자체가 EAS 어테스터라서 발급 키를 교체해도 어테스테이션 계보가 유지됩니다. |
| L2 · 발급 서비스 | 심사 → 발급/폐기 tx · 수명주기 데몬 | 심사 후 증적 레코드를 만들고 발급 키로 트랜잭션을 전송합니다. 가스는 서비스가 부담합니다. 일일 재대사 데몬은 로드맵입니다. |
| L3 · SDK | @hopae/sdk | isVerified 래퍼, React 훅, <HopaeBadge/>. |
| L4 · 서피스 | 데모 웹 · 콘솔 · 지갑 | 발급 체험, 지갑 검색, gKRW 송금, 크리덴셜 검증, 컴플라이언스 콘솔. 지갑 안의 인증마크는 로드맵입니다. |
발급 플로우
issue flow
[소유권 증명] 대상 지갑의 EIP-191 서명 검증 — 원문에 level·claimsRoot·시각 바인딩, 10분 유효
↓
[심사] 검사 7종 실행 → 케이스 생성 (FAIL 1건이면 발급 없음)
소유권 · 선언 정합성 · 지정 지갑 대사 · 명단 대사 · 온체인 노출 · 관할 · 위험평가
↓
[증적 생성] evidence record(JSON) → keccak256 → evidenceHash
↓
[발급 tx] HopaeRegistry.issue(subject, kind, level, evidenceHash, claimsRoot, auditRef, expiration)
↓
[EAS] 어테스테이션 생성 — 구 어테스테이션이 살아있으면 선폐기(supersede)
↓
[검증] 모든 dApp: isVerified(subject, kind, minLevel) → true증적 없는 발급은 불가능합니다. evidenceHash가 비어 있으면 컨트랙트가 revert합니다. 재발급 시 살아있는 구 어테스테이션을 EAS에서 먼저 폐기한 뒤 발급하므로, EAS를 직접 읽는 외부 검증자에게도 낡은 어테스테이션이 남지 않습니다.
어테스테이션 수명주기
| 상태 | isVerified() | 진입 조건 |
|---|---|---|
| active | ✅ true | 발급 완료, 폐기·만료되지 않음. |
| revoked | ❌ false | 제재 히트·재심사 탈락 등으로 폐기됨. 사유 해시(reasonHash)가 온체인에 기록. |
| lapsed | ❌ false | EAS 만료 시각 경과(발급 시 TTL 365일). 재검증으로 갱신 발급해야 함. |
| none | ❌ false | 해당 (지갑, 종류)에 어테스테이션이 없음. |
판정은 fail-closed입니다. 폐기 트랜잭션 하나면 게이트를 쓰는 모든 dApp에서 동시에 차단되고, dApp 쪽에는 아무 조치도 필요 없습니다. 상태 전이를 누가 일으키는지, 재대사와 케이스 처리가 어떻게 도는지는 수명주기와 운영 문서에 있습니다.
검증 경로
isVerified(subject, kind, minLevel)는 다음을 순서대로 확인하는 순수 view 호출입니다:
HopaeRegistry.isVerified — 판정 순서
1. attestationOf[subject][kind] → 어테스테이션 UID 조회 (없으면 false)
2. EAS에서 어테스테이션 로드
3. revocationTime != 0 → false (폐기됨)
4. expirationTime ≤ now → false (만료됨)
5. level ≥ minLevel → true / false가스가 들지 않는 read라서 매 트랜잭션마다 호출해도 부담이 없습니다. Solidity modifier와 프론트엔드 훅 어느 쪽에서든 같은 결과를 얻습니다.
프라이버시와 증적 설계
온체인에 올라가는 것 (전부)
| 필드 | 타입 | 내용 |
|---|---|---|
kind | uint16 | 자격 종류 — KYC(1) / KYB(2) / KYA(3) |
level | uint8 | 보증 등급 1~3 (인증 등급 문서 참조) |
evidenceHash | bytes32 | 오프체인 증적 레코드(심사 결과·케이스 ID·타임스탬프)의 keccak256 |
claimsRoot | bytes32 | (스키마 v2) 검증된 필드들의 Poseidon2 커밋 루트 — ZK 선택공개 준비 |
auditRef | bytes32 | (스키마 v2) 감사용 암호화 증적 봉투의 해시 |
이름·생년월일·신분증 같은 개인정보는 온체인에 0바이트입니다. 증적 레코드 원문에도 개인정보 대신 벤더 참조 ID와 해시만 들어갑니다. 온체인 해시는 “증거가 존재하고 변조되지 않았다”는 앵커이고, 원본 증적은 감사·분쟁 시 해시 대조로 무결성을 입증합니다.
현재 GIWA Sepolia 배포는 ZK-ready 스키마 v2입니다. 발급마다 검증 필드들의 커밋먼트 루트(claimsRoot)와 감사봉투 해시(auditRef)가 함께 기록됩니다. 검증 방법은 프라이버시와 ZK 문서를 참고하세요.