하마
5k
2019-02-07 14:15:11 작성 2019-02-07 16:21:48 수정됨
0
233

400라인의 go코드로 구현한 하이퍼레저 패브릭 [2]- 블록전파/Gossip 프로토콜


go초보자로써 go언어의 매력은 잘하든 못하든 그냥 타이핑 해보게 된다는 거 같습니다. 이 글은 어찌보면 블록체인/하이퍼레저패브릭보다는 go활성화를 위해 조금이나마 도움이 되고자 go언어에 관심 있고, p2p프로그래밍에 관심있는 분을 위해 작성한 코드입니다. 질문은 댓글로 주시면 아는 한 답변 드립니다.



          go로 간략히 구현한 블록전파/Gossip Protocol 


지난 글(400라인의 go코드로 구현한 하이퍼레저 패브릭)에 이어 이번에는 하이퍼레저 패브릭의 블록전파/가쉽프로토콜을 추가 구현 해 보는 시간을 갖겠습니다. 이번 설연휴동안 여유있게 코딩했는데 역시나 세세한 부분이 많이 생략되습니다만 중요맥락에 대해서는 대략 비슷하게 동작되게 하는 목표로 구현하였습니다. (더 줄일 수도 있었지만, 앞으로 추가될 기능들을 위한 기반으로 600라인이 넘어갔습니다.) 

1개의 리더피어와 여러개의 일반 Commit 피어가 작동하게 될 것이며, 각 피어는 포트로 구분 될 것입니다. 리더피어가 오더러에게 메세지를 10초에 한번씩 가져와서 몇개의 피어에만 전파시키면 결국은 모든 피어가 모두 동일한 데이터를 담고 있게 할 것입니다. 시작되는 피어는 부트스트랩노드에서 초기 피어정보를 가져올 것이며, 30초에 한번씩 주변 노드로부터 노드정보들을 가져와서 업데이트 할 것입니다. 중간에 몇몇개의 피어가 멈추어도 동작 할 것이며,  그 피어 중 하나를 다시 살리면, (혹은 새로운 피어가 들어가도) 그 피어는 그 동안의 모든 데이터를 이웃으로 부터 받게 될 것입니다. 리더피어가 멈추면, 리더를 선출하게 됩니다. 

400 라인 하이퍼레저 패브릭 구성 요소 복습 

* Endorse Peer - 클라이언트가 발생시킨 트랜잭션을 계산/보증한 후 Read/Write Set을 리턴
* Commit Peer - Orderer가 보내준 블럭을 장부(블록체인 및 상태저장소) 에 기록
* Orderer - Read/Write Set 을 받아 정렬 한후 블록으로 만들어 Commit Peer에 전달.
* Kafaka - Orderer를 도와서 정렬작업을 합니다.
 * Fabric CA - 각 Peer 와 사용자(조직)등에 대한 암호화 재료를 만들어 주며, CA의 역할을 합니다.
* MSP - 각 조직및 사용자에 대한 신원검증을 처리 합니다.
* Ledger - append only인 블록체인과 상태저장소를 가지고 있습니다.
* LevelDB - key,value 맵으로 상태를 저장하고 있습니다.

심플하게 구현된 하이퍼레저 패브릭은 위의 구성요소로 되어 있으며, 6번 오더러(O)에서 리드피어로 블록을 주면, 리드피어는 블록을 저장하고 끝났습니다. 근데 원래는 리드피어(C)는 자신의 동료 Commit피어들에게 가쉽프로토콜로 블록을 전파하거든요. 그 부분이 이번에 새로 추가한 코드입니다. 

해당 부분을 위해 간략하게 정리한 아이디어는 아래와 같습니다. 


블록전파/가쉽프로토콜 아이디어 정리

1. 암호화 핸드쉐이크 (TLS)  - 생략
2. 프로토콜 핸드쉐이크  - 생략
3. 스트리밍 인코딩/디코딩 - 생략
4. UDP 및 NAT Traversal - 퍼블릭 블록체인 아니면 필요가 없음. 
5. 서로의 이름만 확인 후 간략한 패킷정의로 TCP 스트리밍으로 통신 (RPC사용안함)

6. 부트스트랩 피어/리더 피어/ 오더러 설정 - 하드코딩 /  채널,조직 등 추상개념 제외 
7. 각 피어는 시작시부트스트랩 피어에 접속하여, 부트스트랩 피어들이 가지고 있는 다른 피어정보들을 가져와서 저장. 
8. 3초에 한번씩 자신이 살아있다는 정보를 모든 피어에 알림.- 생략
9. 자신이 가지고 있는 피어에게 alive메세지가 5초안에 안날라오면, V에서 제거하여 H로 이동.- 생략
10. Alive메세지를 받으면 그게 내 V에 없는 피어라면 V에 넣는다. 있는데 seq,시작시간가 둘다 크면 업데이트. - 생략
11. 리더에게 alive메세지가 안오면, 피어들은 부트스트랩에 랜덤으로 리더로 선출해서 서로에게 알림. 모든 피어는 서로의 투표를 받아서, 가장 많이 투표된 피어를 선출하고, 그 피어는 스스로 리더피어가되서 오더러에서 데이터를 가져옴. - 생략

12. 리더피어는 5초에 한번씩 블록을 가져옴. (오더로에서 가져왔다고 시뮬레이션함.실제 연결안함)
13  부트스트랩으로 부터 초기 연결정보를 가져오고, 후에는 30초에 한번씩 주변피어정보를 수집함. 
14. 수집된 피어 중 자신이 가지고 있지 않은 피어에 즉시 연결 요청함. 
15. 블록 받으면 이웃노드들중 랜덤 3개에 전파 (Push모델) 
16. 한번 받은 블록을 기록해두고, 똑같은 것을 받으면 버림. (같은 블록 처리를 방지) 
17. 램덤 Push 모델로는 구멍이 생기기 마련, Pull로 자신의 구멍을 메우는 호출도 함. - 생략
17. 새로 발견된 이웃이 블록을 적게 가지고 있으면 블록 전파  - 생략
18. 새로 접속한 피어는 주변에 alive메세지와 함께 블록 정보도 뭍혀서 날림. 주변 피어들은 자신들의 블록 id를 리턴해주고 랜덤선택하여 블록 요청 (가장 큰 블록 id를 가진 피어한테 요청하면 그 피어가 병목이 될 수도) - 생략
19. 자신의 블록id와 2이상 차이가 날 경우에만 블록 요청 - 생략

구성도

이런식으로 리더피어가 동채널/동조직 commit피어집단에 모두 전파하는게 아니며 


 
이런식으로 주변 랜덤n개에만 전파하면 각각 그들도 주변에 전파합니다. 


소스코드
https://github.com/wowlsh93/hyperledger-fabric-400-gossip


실행
터미널 7개 정도 띄운후 
터미널1:  go run peer.go -name 28000 -port 28000 -leader
터미널2:  go run peer.go -name 28001 -port 28001 -bootstrap 28000
터미널3:  go run peer.go -name 28002 -port 28002 -bootstrap 28000
터미널4:  go run peer.go -name 28003 -port 28003 -bootstrap 28000
터미널5:  go run peer.go -name 28004 -port 28004 -bootstrap 28000
터미널6:  go run peer.go -name 28005 -port 28005 -bootstrap 28000
터미널7:  go run peer.go -name 28006 -port 28006 -bootstrap 28000


* 리드피어는 오더러에서 블록을 가져 온다.


* 이웃피어로부터 정보를 수집한다. 

* 블록을 주변에 전파한다.  (전파하는 와중에도 동일한 블록이 들어 올 수 있으나, 이미 받은 블록이면 버림) 

0
1
  • 댓글 0

  • 로그인을 하시면 댓글을 등록할 수 있습니다.