File Exchange (IPFS BitSwap Protocol)

BitSwap은 BitTorrent에서 영감을 얻은 프로토콜입니다. BitTorrent에서처럼, Peer들은 본인이 얻고 싶은 파일블록(want_list)와 본인이 갖고 있는 파일블록(have_list)가 있습니다. 그러나, BitTorrent는 하나의 파일을 받고자할 때 그 파일의 블록들만 한정적으로 받아올 수 있는 반면, BitSwap에서는 일치하는 파일블록이라면 어떤 파일에 속해 있든지 받아올 수 있다는 장점이 있습니다.

만약 노드들이 받기만 하려고하고 줄 생각이 없다면 문제가 발생합니다. 이를 해결하기 위해 BitSwap는 기본적으로 물물교환 시스템(barter system)을 표방합니다. 무언가 받기 위해서는 무언가 주어야합니다. 상대방에게 내가 원하는게 있지만, 내가 대가로 줄게 없으면 (filecoin 구상이 시작된 배경이기도 합니다.) 그 노드는 열심히 일해서 굉장히 희귀한 파일블록이라도 얻어서 보유해놓아야 합니다. (이는 희귀한 파일블록들이 더욱 배포, 확산되는 효과를 낳습니다.)

또한 BitSwap Credit 시스템을 통하여, 노드들이 peer에게 파일블록을 보내주면, 보낸 노드는 자산이 증가하며, 받은 노드는 부채가 증가하게 됩니다. 결국 평판이 쌓이는 구조이므로 받기만 하려는 어뷰징을 막을 수 있고, 파일블록을 보유하고 보내주는 것에 인센티브가 생기게 됩니다.

BitTorrent에서는 Tit-for-tat(눈에는 눈, 이에는 이) 전략이 표준으로 되어있지만, BitSwap의 노드들은 각자 자신의 전략을 설정할 수 있습니다. 이러한 전략들의 총체는 곧 BitSwap 생태계의 성능을 좌우하게 될 것 입니다.

IPFS의 File Exchange 특성인 IPFS BitSwap Protocol을 알아보기 위하여 우선 그 기본인 BitTorrent를 짚고 넘어가겠습니다.

BitTorrent

BitTorrent는 오늘날 개별 파일 공유에 가장 많이 사용하는 대표적인 프로토콜입니다. 또한 저작권 측면에서 보면 2010년 이래에 20만명 이상이 저작권으로 고소당하기도 했던 장본인이기도 합니다. 2001년 Bram이 처음 만든 이 프로토콜은 BitTorrent-Protocol을 참고하기 바랍니다.

IPFS는 BitSwap Protocol의 기본을 위한 BitTorrent

BitTorrent는 트래픽을 어지럽히는 주범이라고 하지만 오늘날 트래픽의 가장 큰 부분을 차지하고 있는 프로토콜입니다. 기존의 서버-클라이언트 방식이 아닌, 클라이언트-클라이언트 방식의 P2P를 사용합니다. P2P 방식을 이용하여 자료를 공유하면 공유하는 사용자가 많을수록 다운로드 속도가 빨라지는 특징을 보입니다.

특징

P2P(Peer-to-Peer) 방식을 사용하는 프로토콜로 서버-클라이언트 구조의 일대일 공유 방식이 아닌 클라이언트-클라이언트 구조의 일대다 파일 공유 방식을 사용합니다.

일대일 파일 공유 방식은 서버가 원본 파일을 가지고 있고 클라이언트가 서버로부터 원본 파일을 받아가는 방식(그림의 a)입니다. 일대일 파일 공유 방식은 인터넷 환경과 서버의 성능/정책에 따라 파일 전송 속도가 결정되며 전송이 완료될 때까지 유지됩니다.

일대다 파일 공유 방식(그림의 b)은 원본 파일을 조각(piece)으로 나누어 각 클라이언트간 조각을 교환하는 방식입니다. 각 클라이언트들은 파일을 공유하는 새로운 클라이언트를 발견하면 자신의 조각 정보를 알려주고 새로운 클라이언트에게 자신이 필요한 조각을 요청합니다. 이러한 방식은 하나의 클라이언트에 여러 클라이언트가 세션을 생성하게되고 세션이 늘어나면 사용자의 다운로드 속도가 늘어나 클라이언트가 사용하는 인터넷 환경의 최대 대역폭까지 다운로드 속도를 증가시킵니다.

동작원리

BitTorrent는 P2P 방식을 사용하는 대표적인 프로토콜입니다. P2P 방식은 클라이언트와 클라이언트 간에 세션이 직접 생성되어 공유하고자 하는 파일을 여러 개의 조각(Piece)으로 나누어 주고받는 것이 특징입니다.

대표적인 공유 정책으로 ”optimistic unchoking” 메커니즘이 있습니다. 해당 메커니즘은 클라이언트의 대역폭을 일부 강제적으로 할당하여 무작위로 피어들에게 조각을 보내어 모든 피어들이 일정한 조각을 가지도록 하며, 이와 같은 원리를 통해 공유 속도와 효율성을 증대하였습니다.

  • Piece(조각): 공유 파일을 작게 조각 낸 파일
  • Seeder(시더): 공유 파일 완전체를 가지고 있는 클라이언트 (파일의 모든 조각을 소유)
  • Leecher(리처): 공유 파일 불완전체를 가지고 있는 클라이언트 (파일의 일부 조각만을 소유)
  • Peer(피어): 시더와 리처를 합한 의미
  • Tracker(트래커): 피어들의 정보를 관리하는 서버
  • Swarm(스웜): 각 공유 파일마다 존재하며, 공유 파일에 대한 고유 식별자(Hash)와 공유 파일을 소유하고 있는 피어 리스트 정보를 가짐
.torrent file

요청파일 고유의 Hash 값이 포함되어 있으며 트래커의 URL 주소가 포함되어 있습니다. Hash 값은 파일 식별자로써 동일한 파일 이름을 가진 다른 컨텐츠와 구분을 위하여 생성되는 고유의 값이며 트래커의 URL은 파일을 공유하는 피어들의 정보를 관리하는 서버(트래커)를 지정하는 것 입니다.

Tracker Request

다운로드 받고자 하는 사용자가 토렌트 파일을 실행하면 BitTorrent 클라이언트는 토렌트 파일에 포함된 요청파일의 고유 Hash 값을 트래커(토렌트 파일에 포함되어 있는 URL)로 전송하는데 이 메시지를 의미(HTTP Get과 비슷한 의미)합니다. 동일한 토렌트 파일을 사용하여 요청파일을 공유하고 있는 모든 피어들은, 트래커에게 해당 파일의 Hash 값을 보내게 되며 피어들로부터 Tracker Request를 받은 트래커는 해당 파일의 Hash값에 해당하는 스웜(Swarm)을 생성하고 해당 파일의 Hash 값을 보낸 피어 IP 주소를 스웜을 통해 관리합니다.

Tracker Response

Tracker Request 패킷을 전송 받은 트래커는 피어들에게 Tracker Response 패킷을 전송합니다. 이 때 트래커는 피어들이 보낸 식별자에 대한 스웜이 존재하는지 파악하고, 존재하지 않는다면 다른 피어가 Tracker Request 패킷을 보낼 때까지 대기합니다. 스웜이 생성되면 Tracker Request 동작을 수행하고 있던 피어 리스트를 피어들에게 전송하는데 이 때의 메시지 또는 패킷을 Tracker Response 라고 합니다. 피어 리스트는 기본으로 50개의 피어 IP 주소로 구성되며, 만약 스웜에 저장되어 있는 피어들의 주소가 50 이상이라면 무작위로 피어 주소들을 리스트로 구성하여 전송하게 되고, 50 개 미만이면 모든 피어 리스트를 전송합니다.

File Download

트래커로부터 Peer 리스트를 받은 피어들은 서로에게 공유 파일의 식별자를 전송합니다. 식별자를 전송 받은 피어들 중 파일 조각을 보유하고 있어, 해당 공유파일에 대한 공유가 가능한 피어라면, 동일한 식별자를 공유를 요청한 피어에게 전송하여 서로 간의 공유 세션을 형성합니다. 이 때 피어들은 피어 리스트에 의해 최대 50 개의 세션을 동시에 형성하게 되고, 공유 파일은 일정 크기의 조각으로 나뉘어 공유합니다. 그 후, 피어들은 자신이 가지고 있는 조각을 파악하고 자신이 가지고 있지 않은 조각을 다른 피어에게 요청하며, 자신이 가지고 있는 조각을 다른 피어가 필요로 하면 조각을 해당 피어에게 전송합니다. 이와 같은 과정을 통해 다운로드와 업로드가 동시에 일어나게 됩니다.

.torrent 구조 (시드 파일 구조)

시드 파일은 일반적으로 토렌트 파일이라고도 불리며, 파일 공유를 위한 여러 메타데이터를 담고 있는 메타파일 입니다. 공유파일이 하나인 싱글 시드 파일과 공유파일이 여러 개인 멀티 시드 파일로 구분할 수 있습니다.

Name Parameter 설명
Torrent Filename 토렌트 파일명 (파일명.torrent)
  Info Hash 공유 파일의 Hash 값
Tracker Tracker URL 트래커 URL 주소 / 여러 트래커 주소 포함 가능
Metadata Directory 토렌트 파일이 저장되는 디렉토리 이름 (싱글 시드 파일과 멀티 시드 파일 구분)
  Created On 토렌트 파일 생성 일시
  Created By 토렌트 파일 생성자 정보
  Comment 생성자의 코멘트
  Piece Length 피어간 주고받을 조각 크기 / 최소 128KByte
  Private 개인 파일 여부 On/Off
Files Filename 공유 파일 실제 파일명

Directory, Piece Length, Private, Filename이 Hash 값을 생성하기 위해 사용되는 파라미터입니다. 기존 P2P는 하나의 파일만 주고받을 수 있었지만 BitTorrent는 하나의 토렌트 파일 안네 여러 파일을 포함시킬 수 있습니다. (토렌트 파일의 “Directory” 를 지정하여 “Files” 내 여러 개의 파일을 포함 시켜서 배포 가능)

Peer to Tracker 통신

Peer와 Tracker 통신은 HTTP를 사용하며 클라이언트가 실행한 토렌트 파일(.torrent)에 포함된 정보를 통해 트래커에게 피어 리스트를 요청합니다. 요청을 받은 트래커는 클라이언트의 Hash 정보를 기반으로 스웜에 속한 피어들의 리스트를 요청한 후 클라이언트에 전송합니다.

Tracker Request 및 Tracker Response 에서 전달되는 정보들은 다음 표와 같습니다.

Message Parameter 설명
Tracker Request info_hash 토렌트 파일에 포함된 공유 파일의 Hash 정보
  peer_id 클라이언트 식별 ID
  port Tracker Response 메시지용 클라이언트 port
  upload 업로드 파일 합 (바이트)
  download 다운로드 파일 합 (바이트)
  left 다운로드 받을 남은 파일 크기 합 (바이트)
  key (option) 클라이언트 IP 변경에 무관하게 클라이언트 인식을 위한 값 (피어간 공유하지 않음)
  event Started: 파일전송 시작 / Stopped: 파일전송 중지 / Completed: 파일전송 완료
  numwant (option) 몇개의 피어 정보를 받을것인지 요청 (기본: 50)
  compact Set1: 피어들의 IP 주소와 Port 정보만 받음 / Set0: IP 주소와 Port 외에 Peer-ID 등의 정보를 받음
  no_peer_id Peer-ID는 생략하고 정보 요청 (Compact=1의 경우 무시)
  ip (option) 클라이언트 IP 주소
Tracker Response complete 현재 파일 공유 시더 수
  downloaded 공유 파일 다운로드 완료 횟수
  incomplete 현재 파일을 다운로드 하고 있는 리처 수
  interval Tracker Request 전송 Interval (단위: 초)
  min interval (option) Tracker Request 전송 최소 Interval (단위: 초)
  peers 피어 IP 리스트

Peer to Peer 통신

트래커를 통해 피어 리스트를 받은 BitTorrent 클라이언트는 리스트에 있는 피어들과 BitTorrent 프로토콜을 이용하여 통신을 시작합니다. 클라이언트는 파일을 교환하기 위하여 피어들과 서로의 정보를 주고 (Handshake) 받습니다.

이후 피어들은 자신이 가지고 있는 조각의 정보를 피어들에게 주기적으로 알려주며 자신이 필요한 조각은 대상 클라이언트에게 요청하여 조각을 받습니다.

클라이언트는 Handshake(1~4) 이후 피어 1과 피어 2에서 Have 메시지(5~6)를 받았습니다. 해당 Have 메시지에는 피어 1과 피어 2가 가지고 있는 조각의 정보가 포함되어 있습니다. 이러한 Have 메시지를 통해 사용자는 피어 1이 가지고 있는 조각을 알게 됩니다. 0x000001ed라는 조각을 피어 1에게 요청(Request 메시지)하여 피어 1로부터 해당 조각을 Piece 메시지를 통해 전송 (7~8) 받게 됩니다.

이후 사용자는 자신이 새로운 조각을 가지게 되었으므로 Have 메시지를 통해 0x000001ed인 조각을 자신이 가지고 있다고 피어 1과 피어 2에게 (9~10) 알립니다. 피어 2에서 0x000001ed인 조각을 사용자에게 요청하는 경우(11), 사용자는 자신이 가지고 있는 조각이므로 피어 2에게 해당 조각을 전송(12) 합니다. 이러한 방식으로 피어와 피어 간에 조각 교환이 계속하여 발생하게 됩니다.

피어간 통신에 사용되는 메시지는 다음표와 같습니다.

Message 설명
Keep-alive 대상 피어가 온라인 상태인지 체크하는 메시지
Choke Request 에 대한 응답을 할 수 없음을 알리는 메시지
Unchoke Choke 상태를 해지하여 Request 에 대한 응답이 가능함을 알리는 메시지
Have 자신이 가지고 있는 조각의 정보를 피어들에게 알리는 메시지
Request 받고자 하는 조각의 Index와 Offset 정보를 대상 피어에게 알리는 메시지
Piece 실제 파일 조각, Index 및 Offset 정보가 보함된 메시지

Reference