관리 메뉴

HAMA 블로그

[하이퍼레저 패브릭] Gossip Protocol 본문

블록체인

[하이퍼레저 패브릭] Gossip Protocol

[하마] 이승현 (wowlsh93@gmail.com) 2018. 8. 28. 14:53



1. Gossip 프로토콜 일반 

이더리움의 DEVp2p 네트워킹보다는 비교적으로 간단한 편인 하이퍼레저 패브릭에서의 네트워킹구조 를 살펴보자.
참고로 이더리움의 DEVp2p 에 관련되어 이전에 작성한 글이 있으니 Public 체인에서는 어떻게 하는지 참고 하자.

-> [Ethereum] Node Discovery with Kademlia 
-> [이더리움 코어] DevP2P 소스코드 분석 (feat. golang) 

암튼 둘다 Goosip 을 이용하는데, Gossip 즉 소문이란 무엇인가? 내가 주변 몇사람한테 연예인에 대한 잘못된 소문을 내는 순간에 그들이 또 각자 소문을 내고 이런식으로 내가 전체에게 알리지 않아도 전체가 알게 되는 것을 말하며 특징은 이런것이 있을 수 있겠다..

- 전체에 말하지 않아도 되는 편리함.
- a 라는 사람에게 도착하는 순서가 정해져 있지 않음.  
- 어떤 경로가 끊어져도, a 는 다른 경로를 통해서 전달 받을 수 있다.

- 중복 전달 될 수도 있다. 
- 최악의 상황에선 전달 못 받을 수도 있다. 
- 구라가 횡횡 할 수 있다. 

이런 특징을 그대로 구현한것이 Goosip 프로토콜이다. 근데 좀 룰을 정한게 있는데 

- 한 노드는 부트스트랩 노드를 통해 시작하며, 부트스트랩 노드 각각이 가지고 있는 Alive 노드정보를 합쳐서 셋 구성. 
- 한 노드는 주변 연결된 노드들이 살아있는지 계속 확인 해야한다. 
- 한 노드는 자기가 알고 있는 노드들의 전체 정보를 주변에 주기적으로 알려줘서 전체 네트워크가 현재 상황에 대해 알 수 있게 한다.
- 소문을 낼 때에는 전체노드중 몇개를 랜덤하게 정해서 소문을 퍼트린다.
- 소문을 반복해서 퍼트리지 않는다.전에 받은 소문은 다시 처리하지 않는다.
- 이더리움은 구라를 수용하면서 신뢰를 만들고, 하이퍼레저 패브릭은 인증을 통해서 원천봉쇄한다. 

자 이 아이디어를 머리에 담고 하이퍼레저 패브릭을 살펴보자.

이미 아시는 분도 있겠지만 하이퍼레저 패브릭의 워크플로우를 간단히 설명하면,

1. 클라이언트는 어플리케이션(SDK)를 통해서 Peer 들에게 트랜잭션을 실행 시킨다.
2. Endorsement역할을 하는 이 Peer 들은 체인코드를 실행시키고 장착된 체인코드 로직에 따라서 결과를 내어 다시 클라쪽으로 read/write 셋을 전달 한다.(이 과정에서 장부를 업데이트 하지 않음)
3. 이 결과 셋을 가지고 orderer 서비스에게 순서를 정해서 블록화 해달라고 요청한다.
4. orerer 서비스는 블록화 하면 Peer 들은 이 블록을 가져와서 검증하고 저장한다.

이 과정 중에서 Gossip 프로토콜이 이용되는것이 바로 4번 flow 에서이다. 
즉 orderer 는 모든 peer과 커뮤니케이션을 하는게 아니라, 조직별 대표 peer 하나에게 알리면 이 peer 가 gossip 을 통해 점진적으로 전체로 전달되게 되는 것이다. 각 피어는 전달받은 블록(트랜잭션 뭉치들)을 검증하고 장부(상태DB&블록체인) 에 저장한다. (Gossip은 또한 Peer간 Sync를 맞추는데도 사용된다.)



조금 더 구체적인 위의 그림에서는 5번에 해당한다. 리더피어(그림이 잘못됨. 앵커피어가 아니다) 에게만 전달하면 그것이 소문(블록정보)을 퍼트리기 시작한다. 그림에는 브로드캐스트 처럼 보이지만 저기서 가쉽이 사용되는데, 조직마다 리더피어가 있으며, 그 녀석이 오더러에게서 Pull 하면서 시작된다. 그림에는 구분이 안되어 있지만 추가적으로 하나의 조직이 다른 조직의 Peer 와 연계할 때에 Anchor Peer 를 이용한다. 리더피어=Anchor Peer 로도 설정 할 수도 있다.

2. Gossip 프로토콜 with 하이퍼레저 패브릭 

다시 좀 더 자세히 알아 보자. 위에서 설명했듯이 하이퍼레저 패브릭에서는 트랜잭션 실행 피어와 트랜잭션 정렬 피어 사이에서 업무를 분담해서 CPU부하(고루틴을 통함)  및 네트웍 부하를 처리한다. 이런 분리된 네트워크에서 확장성,보안성, 일관성 등에 대한 처리를 유연하게 하기 위해 패브릭은  가쉽 데이터 전파 프로토콜 을 만들었다. 

각 가십메세지들은 서명되어서 전달되며, 그에 따라 중간에 악의적인 노드의 메세지도 쉽게 확인되며, 가쉽 프로토콜 특성상 늦게 도착하거나, 몇몇 노드들의 네트워크 분단 상황에서도 결국 싱크는 맞춰지게된다.   

패프릭 네트워크에서 가쉽 데이터 전파 프로토콜  주요 3가지 기능으로는 다음과 같다.

  1. 피어 발견 및 채널 멤버쉽을 관리한다. (이용 가능한 피어들을 계속해서 체크함)
  2. 장부에 기록 할 데이터들을 모든 채널 상의 피어들에 전파.싱크가 안맞는 피어들을 확인하여 모자란 블럭 정보들을 계속해서 공급해줌. 
  3. 새로운 피어가 참여하면 peer to peer 로 장부 데이터들을 업데이트 해줌. 

동일한 채널위의 피어들은 메세지를 계속해서 수신하고,주변 피어에 전파하며, 싱크를 맞추게 된다. 이웃피어의 갯수는 설정으로 정해져 있으며, Pull 메커니즘을 따른다. 따라서 메세지가 올 때 까지 기다리는게 아니라, 적극적으로 가지고 오려는 행동을 한다. 채널 상의 각 조직의 리더 피어는 오더러에게 데이터를 가져(Pull)온 후 자신의 조직에 포함된 피어들에게 전파하기 시작한다.

리더 선출 

다음과 같이 2가지 방식이 있다.

  1. Static – 시스템 관리자는 조직마다 하나의 피어를 설정으로 정한다.

    core.yaml: 파일에서 

    peer: gossip: useLeaderElection: false orgLeader: true

    환경 설정에선 이렇게 하면 core.yaml을 덮어 쓴다. 

    export CORE_PEER_GOSSIP_USELEADERELECTION=false
    export CORE_PEER_GOSSIP_ORGLEADER=true
  2. Dynamic – 리드 선출 프로세스에 따라 결정되는데, 리드 피어가 문제가 생기면 각 피어들은 리드 선출과정에 돌입한다. 리드 선출 프로세스는 피어의 메타데이터에 기반하는데 각 피어가 가지고 있는 ID를 정렬해서 낮은 것이 리드가 되는데,  이 과정에서 여러개의 피어가 자신이 리더라고 주장 할 수 있지만 가장 낮은 이름을 가진 피어가 결국 우선권을 가지며  정해 진 시간 동안 선출이 안되면 그 다음 낮은 피어가 자신이 리더라고 주장 할 수 있게 된다.   좀 더 자세히 -> 요기 

3. 앵커(Anchor) 피어 

앵커 피어는 다른 조직들 간의 네트워크 정보를 가지고 있으며,  Service Discovery에 의해 사용 될 수 있다 즉 클라이언트는 네트워크에 누가 있는지 없어졌는지 등에 관한 상태정보를 알아야 한다. 또한 가쉽 커뮤니케이션을 용이하게 하기 위해 사용된다. 즉 하나의 조직에서 다른 조직에 메세지를 전달 할 때 앵커피어에게 전달한다. 체인코드를 호출 할 때 보증을 맡는 피어가 자신의 조직에만 있는 것은 아니기 않나. 그리고 이 말은 앵커피어는 조직 간 커뮤니케이션에 SPOF도 된다는 의미이다.앵커피어에 대한 정보는 채널 설정에서 정의 되어 있다. 참고로 앵커피어가 리더피어 역할을 해 되도되며, 독립적일 수 도 있다. 

Note

1. 각 피어간의 메세지 보안은 TLS 레이어에 의해 작동하며 서명을 요구하지 않는다. 피어들은 그들의 신원서(CA에 의해 부여된 certificates) 로 인증(authenticated)되며, TLS certs(ECerts를 가지고 TCA에 의해 만들어지는)가 사용될 지라도, 가쉽레이어에서 인증되는 것은 피어신원서이다. 장부블록은 오더러 서비스에 의해 서명되며, 채널의 리더피어들에게 전달된다. 

2. 인증(Authentication)은 피어의 "MSP" 에 의해 조정받는다. 피어가 처음으로 채널상에 접속하게 되면,TLS 세션은 멤버쉽 아이덴터티와 엮이는데, 이것은 기본적으로 각각의 피어를 채널과 네트웍상의 멤버쉽으로 인증하는 것이 된다. 

4. Dissenmination protocol

가십 구성요소는 다음 2개의 모듈로 구성된다.

discovery 모듈 - 활성 상태 및 응답하지 않는 피어 세트 유지

communication모듈 - 연결 유지 및 메시지 배포

discovery 모듈은 통신 모듈을 사용하여 자신의 정보를 보내고, 통신 모듈은 discovery 관련된 메세지를 discovery 모듈에 전달.

discovery 프로토콜 흐름 
각 피어는 생성시 부트스트랩 피어 세트 B를 받는다.
각 피어는 알려진 멤버 집합을 나타내는 <id, endpoint, logical_timeestamp> 의 세트 V응답하지 않는 피어의 유사한 세트 H를 가지고 있으며, V[id]는  ID 요소를 가진 피어의 마지막 활성 메시지를 나타낸다.
메시지는 네트워크 CA에서 발급한 Pub(Priv) 키를 이용하여 암호화된 방식으로 서명(검증)할 수 있다.

discovery 프로토콜 정의 

1) H=BV={}
2) 시작할 때 H의 모든 p에 연결을 시도 하고 성공하면 p를 V에 추가하고 통신 모듈을 업데이트.
3) 
각 p(i) 로 부터 그들이 가지고 있는 V 를 통합하여 자신의 V를 구성. 
4) 
V가 변경된 경우 통신 모듈을 업데이트하여 새로 추가된 모든 피어에 대한 연결을 생성하고 응답하지 않는 피어에 대한 연결을 제거
5) 매 T초 마다 
피어 p는 다른피어들(랜덤이지 않을까)에 자신의 alive 메시지를 전달.메시지에는 다음이 포함된다.  

          P(id), P(endpoint), m (inc_number: P가 돌기 시작한 시간, seq# :각 alive메세지마다 하나씩 증가 )
6) 
discovery 세트 V의 각 p 멤버에 대해, Alive 메시지의 마지막 시간을 추적한다. 받은지 5초가지났다면 
         V세트로부터 그 p를 제거 / H세트에 그 p 추가 / 통신모듈에서 커넥션을 종료 
7) 어떤 
피어 p에서 Alive 메시지 m 을 수신 시:
     - m.id이 V에 없으면 추가 
    - m.timestamp.inc_number > V[id].timestamp.inc_number , m.timestamp.seq# > V[id].timestamp.seq# 면 V에 추가 

Communication 프로토콜 흐름 
원장에 전달되지 않은 메시지에 대한 내부 버퍼 유지
피어에서 수신한 각 메시지에는 확인할 수 있는 ID가 있는데 이 ID는 Alive 메시지인 경우 <m.timeestamp, p.id> 또는 원장 배포 블록인 경우 원장 블록의 해시입니다. 어느 쪽이든 프로토콜 통신 프로토콜은 메시지의 ID를 m.id로 참조합니다. - 각 피어는 이전에 발생한 메시지 ID의 세트 R과 수신 시간을 주기적으로 보유하고 5 초 이상 전에 수신 된 오래된 메시지 아이디를 삭제합니다.

 Communication 프로토콜 정의  1) 시간 t에 피어 p(i)로부터 메시지 m을 수신하면 -> 메시지가 Alive 메시지 인 경우 ->discovery 모듈로 전달 2) 이전에 m.id ID를 받은 경우 (R에서 발견할수있음) 메시지를 삭제 3) 그렇지 않다면    3-1)  <m.id, m.t> 를 R 로 추가 
   3-2)  V로 부터 
k = log (| V |) + 3 개의 무작위 피어를 선택 - 각각의 p(i)가 응답하지 않으면 discovery 모듈을 업데이트하여 p(i) 를 H에 추가 - m 을 무작위 피어 p(i) 들에 전파 (모아 보낼 수도)
4) T 초마다 한 번, V의 각 P에 대해 k = log (| V |) + 3 개의 무작위 응답 피어 세트를 선택하고 4-1) V 전체를 p(i) 들에게 보냄.
   4-2) V(p,i), H(p,i)를 얻어서 V(p,i) , H(p,i) 에 있는 각 p를 V,H에 추가한다. 4-3) Send to p your highest ledger originated message sequence number s for which you received before all m s.t ,i < s 4-4) If you have before received a message m(j) that wasn't passed to the ledger yet such that j>s , send to p a bitmap b of all sequence numbers from s to j , And receive back from p(i) a set of messages M(i) and (optionally) its own s , b 4-5) M의 메시지를 내부적으로 저장 4-6) (Optionally) send back to p(i) a crafted M of your own according to p(i) 's s(i) , b(i) sent 5) 사용자 또는 discovery 모듈로부터 메시지 m을 수신하면 : 5-1) <m.id, m.t>를 R에 추가하십시오. 5-2) k = log (| V |) + 3 개의 랜덤 피어 집합을 선택하고 m을 그들에게 보낸다.

이렇게 정리된 내용을 토대로 다음에는 실제 하이퍼레저 패브릭의 gossip 에 관련된 코드를 분석해 보도록 한다. 언제하냐고? 신이 나면~~

개인적으로 간략하게 구현 해 본 블록전파/가쉽프로토콜 바로가기  



레퍼런스:

https://hyperledger-fabric.readthedocs.io/en/release-1.2/gossip.html
https://github.com/hyperledger/fabric/tree/release-1.2/gossip
https://jira.hyperledger.org/browse/FAB-170


Comments