본문으로 건너뛰기
Anon Wallet

지갑 동기화

쉴드 지갑에는 일반 지갑에 없는 문제가 있습니다. 잔액이 주소 아래 저장되는 대신, 다른 사용자의 노트와 함께 공유 풀에 놓인 암호화된 노트들로 구성됩니다. 풀에는 소유자 표시가 없습니다. 자신의 자산을 알려면 모든 노트 중에서 자신의 노트를 찾아야 합니다.

방법은 두 가지이며, 그 선택은 쉴드 지갑이 내리는 가장 중요한 프라이버시 결정입니다.

노트를 찾는 두 가지 방법

서버에 대신 찾아달라고 요청하기. 지갑은 조회 키에서 도출한 필터를 인덱서에 보내고, 인덱서는 일치하는 기록을 반환합니다. 빠르고 비용이 적게 들지만 조회 대상이 완전히 공개됩니다. 필터 자체가 질문이며, 서버는 답하려면 이를 읽어야 합니다.

데이터를 내려받아 직접 찾기. 지갑은 고정된 공개 조각으로 풀의 기록을 가져온 뒤 각 노트의 복호화를 로컬에서 시도합니다. 자신의 노트만 성공적으로 복호화됩니다. 서버에는 어떤 노트가 자신의 것인지 묻지 않았으므로 서버는 이를 알지 못합니다.

Anon은 두 번째 방법인 다이제스트 동기화를 사용합니다.

쿼리 자체가 유출인 이유

이를 로그 문제로 생각하기 쉽습니다. 인덱서가 쿼리를 보관하지 않겠다고 약속하면 노출도 사라질 것 같지만, 그렇지 않습니다.

인덱서 쿼리는 X와 일치하는 커밋먼트를 달라는 조건입니다. 이 조건은 조회 키에서 계산됩니다. 서버는 답하려면 조건을 해석해야 하므로, 보관 정책과 관계없이 매 요청마다 키 관련 자료가 다른 사람의 컴퓨터 메모리에 들어갑니다. 로그를 끄면 디스크에 기록되는 내용만 달라집니다. 서버가 알아야 했던 정보는 달라지지 않습니다.

로그를 남기지 않는 것은 약속입니다. 데이터를 갖지 않는 것은 구조입니다.

네트워크 수준의 익명성으로도 쿼리 모델을 해결할 수 없는 이유가 여기에 있습니다. 인덱서 요청을 Tor로 보내더라도 인덱서는 어떤 커밋먼트를 물었는지 정확히 압니다. 그때 사용자의 IP를 모를 뿐입니다.

다이제스트 요청의 형태

Anon의 기록은 CDN에 변경 불가능하고 일정하게 분할된 파일로 저장됩니다. 요청은 다음과 같습니다.

GET https://digest.anon.inc/v4/1/chunks/42/commitments.json.gz

여기에는 사용자 고유의 정보가 없습니다. 경로는 전역 체인 상태로 결정됩니다. 청크 42는 고정된 Ethereum 블록 범위를 포함하며, 세계 어디에서 누가 요청해도 같은 바이트를 받습니다. 자금이 없는 지갑과 천 개의 노트를 가진 지갑이 동일한 파일에 동일한 요청을 보냅니다.

따라서 두 가지 특성이 생깁니다.

  • 기록 요청에 지갑에서 도출한 필터가 없습니다. 모든 로그를 남기고 완전히 침해된 CDN도 특정 IP가 공개 파일을 다운로드했다는 사실만 알 수 있습니다. 그 파일에서 어떤 정보가 사용자와 관련되는지는 CDN이 가진 정보가 아니므로 알 수 없습니다.
  • 일치 여부가 보이지 않습니다. 데이터가 도착한 뒤 사용자 기기에서 복호화됩니다. 엣지는 청크 42에 사용자에게 해당하는 내용이 있었는지 알 수 없습니다. 인덱서는 필터가 질문이었기 때문에 구조상 이를 압니다.

봉인된 청크는 변경되지 않으며 엣지에 1년간 캐시됩니다. 따라서 안정적인 운영 상태에서는 가까운 Cloudflare 데이터 센터가 요청에 응답하고, 요청이 Anon 인프라까지 도달하지 않습니다.

각 서버가 볼 수 있는 정보

동기화만이 지갑의 네트워크 활동은 아니며, 각 경로의 특성도 다릅니다. 구체적으로는 다음과 같습니다.

경로 운영 주체 키에서 도출되는가? 알 수 있는 정보
다이제스트 CDN(digest.anon.inc) Cloudflare 아니요 IP와 특정 블록 범위의 공개 파일을 가져왔다는 사실
인덱서 헤드 API(api.anon.inc) Anon 아니요 IP와 체인 최신 상태에서 대략 얼마나 뒤처져 있는지
PPOI 프록시 제3자 애그리게이터 앞단의 Anon 예 IP와 조회한 블라인드 커밋먼트
RPC 엔드포인트 설정한 제공자 아니요 IP와 조회한 공개 주소 및 컨트랙트
브로드캐스터 네트워크(Waku) P2P 아니요 암호화된 트랜잭션 메시지. 피어는 연결 메타데이터를 볼 수 있음
OHTTP 경유 페이마스터 Anon 게이트웨이와 독립 중계 서버 아니요 중계 서버는 클라이언트 IP와 암호화된 요청을, 게이트웨이는 복호화된 요청과 제출 시점을 봄

헤드 API는 청크 봉인 사이에 지갑을 최신 상태로 유지합니다. 블록 또는 시퀀스 커서를 받는데, 이는 지갑 내용이 아니라 체인에서의 동기화 위치입니다. 따라서 "이 IP는 대략 여기까지 동기화했다"는 사실을 드러낼 뿐, "이 노트들이 그 사람의 것"임을 나타내지는 않습니다.

PPOI 프록시는 별도의 프라이버시 경로입니다. 결백 증명은 보기 키에서 파생한 블라인드 커밋먼트를 집계기에 조회하므로 지갑별 요청입니다. 현재 프록시는 읽기 결과를 캐시하고 요청 매개변수를 캐시 메타데이터에 보관할 수 있습니다. 캐시 키의 해시는 데이터를 익명화하지 않습니다. 운영자는 보존 정책과 네트워크 메타데이터 연결 위험을 검토해야 합니다. PPOI 프록시를 참고하세요. 대량 이력 경로와 달리 POI 경로에는 지갑별 쿼리가 있습니다.

보호하지 못하는 부분

  • 시점과 양. 전체 기록을 받는 최초 동기화와 최신 부분만 받는 재방문 지갑의 트래픽은 다릅니다. 이를 통해 "이 IP는 블록 X 즈음에 마지막으로 동기화했다"고 추정할 수 있지만, 어떤 노트가 사용자의 것인지는 드러나지 않습니다.
  • 연결 메타데이터. 직접 연결을 받는 서버는 IP 주소, 시점, TLS 메타데이터를 볼 수 있습니다. OHTTP 중계는 클라이언트 연결과 요청을 복호화하는 게이트웨이를 분리하지만, 중계 서버에는 클라이언트 IP가 보입니다.
  • 위에서 설명한 PPOI 경로의 블라인드 커밋먼트.

올바르게 설정한 VPN이나 Tor로 네트워크 수준의 노출을 줄일 수 있지만, 신뢰 대상이 달라지고 트래픽 분석이나 지갑별 애플리케이션 데이터까지 없어지지는 않습니다.

네트워크 프라이버시가 요청의 지갑별 내용을 지우지는 않습니다.

쿼리 기반 인덱서에서는 애플리케이션 계층에서 유출이 발생하므로, 사용자는 지갑을 사용하지 않는 것 외에는 해결할 방법이 없습니다. 일정하고 내용에 독립적인 기록 요청은 이러한 필터 공개를 피합니다. 다른 지갑 요청과 네트워크 메타데이터는 별도로 고려해야 합니다.

절충점

이 방식은 비공개 정보 검색이 아닙니다. 숨길 지갑별 요청 자체가 없으므로 요청을 암호학적으로 숨기지 않습니다. 익명 집합 전체를 내려받아 직접 검색할 뿐입니다. 대신 대역폭을 사용합니다. 첫 동기화에서는 몇 개의 일치하는 행 대신 풀의 압축 기록을 전송합니다.

이 작업에는 적절한 절충입니다. 데이터가 공개되어 있고 변경되지 않으며 모든 사용자에게 동일하므로 캐시에 적합합니다. 따라서 비용은 사용자마다가 아니라 각 엣지 위치의 파일마다 한 번 발생하며, 특정 유형의 정보 공개를 통째로 없앱니다. 다만 청크 선택이 사용자와 무관할 때에만 성립하는 절충입니다. 지갑 내용에 따라 "필요한" 범위만 가져오면 더 느린 형태로 쿼리를 다시 만든 셈입니다. 따라서 청크 경계는 블록 높이만으로 결정됩니다.