-
[블록체인] Hyperledger Fabric블록체인 2022. 5. 20. 16:06반응형
하이퍼레저 패브릭 전체 구성에 대해 알아보고 이를 예제 코드로 구현해 보도록 한다.
하이퍼레저 패브릭은, 허가형 네트워크 이므로 각 조직을 나타내는 네트워크가 구성돼야 한다.
앞으로 엔도싱 / 커밋 피어 / 오더러 / CA/ 원장/ 블록체인 / 월드 스테이트를 간단히 구현하여 어떻게 상호작용 하는지 알아보도록 한다.
각 구성 요소에 대한 설명은 다음과 같다.
- 엔도싱 피어 - 클라이언트가 발생시킨 트랜잭션을 계산/보증한 후 리턴
- 커밋 피어 - 오더러가 보낸 블록을 장부에 기록
- 오더러 - 보증된 트랜잭션(Read/Write Set)을 받아서 정렬한 후 블록으로 만들어서 커밋 피어에게 전달
- 카프카 - 오더러가 정렬할 때 사용하는 도구
- CA - 피어와 사용자에게 암호화 재료를 만들어 주는 도구
- MSP - 허가형이므로 신원 검증을 하는 도궁
- 원장 - 블록체인과 상태저장소를 갖고 있음
- LevelDB - key-value 맵으로 상태를 저장함
합의 시스템
블록체인에 블록을 저장하기 위해서는 피어들의 합의가 필요한데, 하이퍼레저 패브릭에서 합의 과정은 다음과 같다.
<실행 & 보증> - <정렬> - <검증 & 저장>
장부에 쓰기와 읽기를 구현하는 코드를 생성해 보자.
- 쓰기
쓸 데이터를 백엔드로 보내면 백엔드에서는 하이퍼레저 패브릭 시스템과 통신할 수 있는 SDK를 호출한다. 이 연결고리를 미들웨어라고 한다.
1. 미들웨어는 엔도싱 피어들에게 트랜잭션을 요청한다.
2. 엔도싱 피어들은 해당 트랜잭션에 대한 체인코드를 호출하여 실행하고 결과값(RWSet)을 미들웨어로 돌려준다.
3. 미들웨어는 RWSet을 받아서 보증에 대해 확인한다. 확인 후 오더러에게 RWSet을 보내준다.
4. 오더러들은 받은 트랜잭션을 카프카 채널에 Push하고, Pull하여 정렬한다.
5. 오더러는 정렬된 트랜잭션 모음을 카프카에게 받아서 블록으로 생성한다.
6. 완성된 블록을 커밋 피어로 보낸다.
7. 커밋 피어는 블록을 검증하고 원장에 저장한다.
-읽기
백엔드에서 하이퍼레저 패브릭 시스템과 통신할 수 있는 SDK를 호출한다.
1. 미들웨어는 커밋 피어에게 트랜잭션을 요청한다.
2. 커밋 피어는 원장에서 정보를 가져온다.
3. 미들웨어에 반납한다.
func WriteTrans(key string, value string) string { rwset1, rwset2 := fabric.WriteTransaction(key, value, fabric.MSP_org1) if rwset1.msp == fabric.MSP_peer1 && rwset2.msp == fabric.MSP_peer2 { msps := [] string{rwset1.msp, rwset2.msp} rwset := RWSet{key:key, value:value, peers_msp:msps} fabric.SendToOrderer(rwset) return "ok" } return "failed" }
미들웨어에서 패브릭으로 저장 정보(key, value)와 자신의 신원증명(msp)을 매개변수로 트랜잭션을 일으킨다.
반환 값(rwset)을 받아와서 각 피어들의 보증정보를 확인한 후에 오더러로 전송한다(SendToOrderer)
패브릭에서 오더러에게 전송하는 값들은 라운드 로빈 방식으로 처리한다.
func (o *Orderer) consumer() { go func() { for{ rwsets := o.kafka.Pull() if rwsets == nil { runtime.Gosched() continue } newBlock := o.createBlock(rwsets) for _, committer := range o.committer { committer.addblock <- newBlock } } }() }
카프카를 이용해 정렬한 트랜잭션들을 가지고 임시 블록을 만든 다음에 커밋 피어로 전송한다.
func (p *Peer) committing() { go func() { for { select { case block := <-p.addblock: ok := p.validating(block) if ok == false { continue } for _, trans := range block.Trans { p.ledger.setState(trans) } p.ledger.addBlock(block) case <- p.peer_done; return } } }() }
오더러가 보낸 임시 블록을 받아서 검증하고 각각의 트랜잭션을 StateStorage에 저장하고 블록체인에도 연결한다.
func (l *Ledger) addBlock(block Block){ ledger_mutex.Lock() prevBlock := l.Blockchain[len(l.Blockcahin)-1] newBlock := l.generateBlock(prevBlock, block) l.Blockchain = append(l.Blockchain, newBlock) spew.Dump(newBlock) ledger_mutex.Unlock() }
블록을 만들어서 이전 블록에 연결하는 함수
오더러에서 커밋피어로 블록을 주면, 커밋 피어가 블록을 저장하고 끝나는 코드를 작성했다.
그런데 원래는 커밋피어는 커밋 피어들끼리 가십프로토콜을 통해 블록을 전달한다. 이 부분을 코딩해 본다.
블록전파(가십프로토콜)
다른 피어에게 랜덤하게 블록을 전파하는 부분
func (p *Peer) propagate(msg Msg){ fmt.Printf("[Peer] propagate [&s} \n", msg.Payload) p.node.pm.propagationBlockSig <- msg }
분산 네트워크를 구성하기 위해 도커를 이용한다. 가십 프로토콜을 이미지로 생성한다.
# Start from a Debian image with the latest version of Go installed
# and a workspace (GOPATH) configured at /go.
FROM golang
# Copy the local package files to the container's workspace.
ADD . /go/src/github.com/wowlsh93/hyperledger-fabric-400-gossip
#Build the gossip command inside the container
RUN go install githuc.com/wowlsh93/hyperledger-fabric-400-gossip/gossip위의 도커파일을 통해 gossip이라는 이름의 도커이미지를 만든다.
docker build -t gossip .
이미지는 golang을 사용하여 빌드될 때 현재 프로젝트를 컨테이너의 /go/src/github.com/wowlsh93/hyperledger-fabric-400-gossip 위치에 복사해 놓는다.
만들어진 이미지로 실행해 보자.
docker run -p 28000:28000 --net host --name gossip1 --rm
출처: https://hamait.tistory.com/1019 [HAMA 블로그]-p : 외부 포트와 내부 포트
-rm : 컨테이너가 내려가면 자동으로 삭제되게 한다.
두 번째 터미널을 열어서 일반 피어를 위한 컨테이너를 띄운다.
docker run -p 28001:28001 --net host --name gossip2 --rm
이제 Go를 사용한 암호화에 대해 정리해 보자.
MSP는 하이퍼레저 패브릭에서 피어와 사용자에 대한 인증 작업에 대한 추상층이다.
관련 구현에 대한 깃 코드를 찾아보기로 한다.
https://hamait.tistory.com/1029?category=276132
-끝-
반응형'블록체인' 카테고리의 다른 글
(비공개) [블록체인]하이퍼레저 환경구성 (0) 2022.05.27 [블록체인] 기말발표 자료 모음 (0) 2022.05.23 [블록체인] 솔리디티 언어 기초 정리 (0) 2022.05.14 [블록체인] 하이퍼레저패브릭 테스트 (0) 2022.04.15 [블록체인] DID Indy tutorial (0) 2022.04.01