블록체인을 공부하며 궁금한 점이나 잘 이해되지 않는 부분에 대해서 정리하기 위한 포스팅입니다.
원장과 블록을 공부하면서 둘다 트랜잭션의 정보를 저장하는데 서로 어떤 차이가 있는지 의문이 생겼다.
원장 : 변경할 수 없는 순차 트랜잭션 레코드 및 현재 상태를 유지하는 상태 데이터베이스를 저장하는, 문자 그대로 "블록의 체인"으로 구성된다. 채널당 하나의 원장이 있으며 이에 대한 업데이트는 특정 채널의 정책에 따라 체인코드에 의해 관리된다.
블록 : 데이터(순서 지정된 트랙잭션)의 보관 단위로, 일정한 시간 단위로 생성된다. 이러한 블록들은 형성된 후 시간의 흐름에 따라 순차적으로 연결되어 체인 형태의 구조를 가지게 된다.
위의 정의를 정리해보면 아래와 같다.
블록은 순서가 지정된 트랜잭션을 보관하는 단위로 체인 형태의 구조를 가지고 있다. 이때 블록은 일정한 시간 단위로 생성되기 때문에 한 블록에 모든 트랜잭션의 내용을 담고 있는 것이 아닌 일정 시간동안의 트랜잭션 내용만을 담고 있다. 대신 체인 형태로 모든 블락이 연결되어 있으므로 이전의 데이터들을 확인할 수 있다.
원장은 이러한 블록들의 데이터를 포함하고 있다.
블록은 모든 블록체인 사용자가 접근할 수 있다. 대신 조회,추가만 가능하고 데이터를 삭제하거나 변경할 수는 없다.
데이터를 조회, 추가하기 위해 필요한 것이 chaincode이다.
블록은 검증이 된 트랜잭션을 통해서만 업데이트된다. 이때 트랜잭션을 검증하는 것이 chaincode이다.
때문에 블록은 chaincode를 통해서 검증이 된 트랜잭션을 바탕으로 업데이트가 된다.
chaincode는 스마트 컨트랙트를 하이퍼레져 패브릭에서 부르는 용어이다.
인스턴스화는 특정 채널에서 체인코드 컨테이너를 시작하고 초기화하는 프로세스이다. 인스턴스화는 체인코드의 필수 초기화를 수행하며, 여기에는 체인코드의 초기 세계 상태를 구성하는 키 값 쌍 설정이 포함된다.
체인코드를 피어에 설치하고 나면 단일 네트워크에서 구성원이 채널에서 체인코드를 인스턴스화 한다. 인스턴스화를 수행하려면 네트워크 구성원은 채널에 가입되어 있어야 하고, 하나의 구성원만 체인 코드를 인스턴스화하면 된다.
인스턴스화를 한 후, 체인코드가 설치된 채널에 가입하는 피어에서 체인코드 컨테이너를 시작한다. 그런 다음 피어에서는 실행 컨테이너를 사용하여 트랜잭션을 수행할 수 있다.
만약 체인코드가 설치된 피어가 이미 인스턴스화된 채널에 가입하면 체인코드 컨테이너가 자동으로 시작된다. 이 경량 접근법을 사용하면 컴퓨팅 및 스토리지 공간을 절약하고 네트워크를 확장하는 데 도움이 된다.
채널에 대해서 조금 자세히 알아본다.
채널은 서로 다른 노드들을 묶는 역할로, 개인적으로 거래하려는 네트워크 구성원의 서브세트로 구성된다.
채널은 네트워크 설정과 별개로 채널 구성원이 채널 구성원만 액세스할 수 있는 특정 규칙 및 개별 원장을 설정할 수 있게 하여 데이터 격리 및 기밀성을 제공한다.
이러한 채널 설정 정보는 블록에 담겨 장부에 기록된다.
채널은 네트워크 안에 존재하지만 네트워크 설정과 채널 설정 사이 중복되는 설정이 없으므로, 네트워크 설정이 변경되어도 채널 설정에 직접적인 영향은 없다.
하나의 채널에는 하나의 원장을 가지는데, 이를 이용해서 private 트랜잭션의 수행이 가능해진다.
instantiate transaction
체인코드가 설치된 피어가 채널에서 체인코드를 시작하고 초기화하는 요청이다. 인스턴스화는 채널 구성원(피어)에게 체인코드에 대해 알리는 역할을 한다.
이때, 하나의 네트워크 구성원만 체인코드를 인스턴스화하면 된다.
Invoke transaction
체인코드가 성공적으로 설치되고 인스턴스화 된 후에는 체인코드가 활성화되어 Invoke 트랜잭션을 통해 원장 읽기/쓰기를 수행한다.
peer chaincode instantiate/invoke
와 같이 사용되는데, instantiate와 invoke는 peer chaincode의 하위 명령 옵션으로 피어와 관련된 다른 chaincode 조작과 관련된다.(메시지x, 함수콜x)
하이퍼레저 패브릭에서 블록체인 네트워크에 참여하는 구성원들을 공인받고 보안성이 보장된 노드 간 통신을 수행하기 위해 하이퍼레저 패브릭 CA 라는 애플리케이션을 제공
하이퍼레저 패브릭 CA가 제공하는 다양한 디지털 인증서는 MSP(Membership Service Provider) 정보를 구성한다. MSP는 이름 그대로 멤버쉽 서비스에 대한 아키텍처의 추상을 제공하는 목적의 컴포넌트로 채널의 관리 권한을 주거나 채널 접근 권한을 관리한다. 예를 들어 새로운 채널을 생성하거나 특정 채널에 피어가 참여하고 체인코드를 호출하기 위한 권한 관리에 바로 MSP 정보가 사용된다.
=> 즉, 거의 모든 하이퍼레저 기능은 MSP 정보를 토대로 동작
MSP는 블록체인 네트워크 관리 권한과 그 범위를 다르게 가질 수 있다.
MSP의 정보들은 제네시스 블록과 채널을 구성하는 트랜잭션에 포함된다.
Local MSP는 물리적 및 논리적으로 노드나 사용자별로 하나씩 존재하게 된다.
Channel MSP는 채널 구성에서 논리적으로 한번만 정의된다. 그리고 채널내의 모든 노드의 파일시스템에서 인스턴스화되어 합의를 통해 동기화 상태를 유지한다.
-> 각 노드의 로컬 파일 시스템에 각 채널 MSP의 사본이 있는 반면, 논리적으로 채널 MSP는 채널이나 네트워크상에서 상주하며 유지 관리된다.
-> 하이퍼레어 패브릭에서 제공하는 cryptogen 툴또는 하이퍼레저 패브릭 CA 애플리케이션이 수행
보통 오더러는 1~2개로 산정하는데, 만약 1개일 때 해킹 및 장애 요인으로 다운될 경우
-> 오더러의 수와 기능은 수시로 변경할 수 있도록 설정 가능하게 구성되어 있기 때문에 만약 문제가 발생하면 오더러를 추가하는 등의 방식으로 문제 해결 가능
그리고 응답시간이나 블로킹 등의 성능적인 부분은 파라미터 또는 체인코드 내에서 설정 가능
※ 블로킹: 요청이 발생하고 완료될 때까지 모든 일이 중단한 상태로 대기해야하는 것
오더러는 방대한 양의 트랜잭션을 모아서 블록을 생성하는 작업을 수행한다. 그러면 당연히 오버헤드(부하)가 발생하기 때문에 오더러는 MQ에 트랜잭션들을 적재하여 처리한다.이때 보통 kafka 또는 zookeeper를 사용한다.
카프카는 토픽(Topic)을 기준으로 메시지를 적재/관리하는데 하이퍼레저 패브릭에서는 채널당 하나의 토픽과 하나의 파티션을 사용하게 된다. 즉, 하이퍼레저 패브릭에서 메시지 큐 구성은 특정 채널만을 위한 컴포넌트가 아니라 여러 채널의 트랜잭션을 처리할 수 있는 구조로 되어 있다.
클라이언트 노드에서 오더링 노드로 트랜잭션 발생
클라이언트 노드에서 원장을 변경하기 위한 트랜잭션을 최초로 생성해서 이를 엔도서 노드로부터 검증받게 된다. 이렇게 검증이 완료된 트랜잭션은 블록에 포함되고 해당 채널의 체인(원장)에 묶이기 위해 오더링 노드로 전달된다.
오더링 노드에서 카프카 브로커에 트랜잭션 전달(Produce)
클라이언트로부터 트랜잭션을 전달받은 오더러는 해당 트랜잭션을 추가적으로 검증한다. 정책에 맞게 전자서명은 다 갖추고 있는 트랜잭션인지, 트랜잭션 생성 시간이 현재 시간과 크게 차이 나지 않는지 등을 원장에 묶이기 전에 최종적으로 검증한다.
카프카에서 트랜잭션들을 발생 시간순으로 처리
검증된 트랜잭션들은 해당 채널에 속하는 파티션에 순차적으로 적재된다. 따라서 트랜잭션들이 발생 순서에 따라 처리되는 것을 보장한다.
오더링 노드가 카프카로부터 트랜잭션들을 읽어 들여 블록을 생성(Consume)
트랜잭션을 카프카로 전달했던 오더링 노드는 다시 카프카로부터 트랜잭션들을 읽어 들여 블록을 생성한다.
생성된 블록을 로컬 원장에 저장
생성한 블록을 오더러 노드에 있는 해당 채널의 로컬 원장에 저장한다.
오더러와 연동하는 모든 노드의 원장 동기화
오더러와 연동하는 모든 노드에게 생성된 블록을 전송한 후, 각 노드가 해당 블록을 검증한 후 각 노드의 원장에 연결한다.
이에 대한 내용으로는 블로그 참고
클라이언트가 요청을 받게 되면 SDK에서는 제안 트랜잭션(transaction proposal)을 생성한다. 이 제안 트랜잭션은 SDK에서 grpc 프로토콜
로 전송될 수 있는 형태로 변형된다. 그리고 SDK에서는 제안 트랜잭션과 사용자가 전송하는 트랜잭션이라는 것을 검증하는 서명과 함께 grpc를 통해 엔도싱 피어로 보낸다. 그리고 제안 응답(proposal response)을 다시 SDK로 반환한다. 반환받은 제안 응답을 다시 오더러에 보낸다.
하이퍼레저 패브릭은 패브릭 이벤트를 통해 블록체인 상에서 발생한 사건들(블록 생성, 체인코드 액션 발생 등)을 SDK를 통해 이벤트로 수신할 수 있다. v1.1 부터 peer 레벨이 아닌 channel 레벨로 이벤트 서비스가 제공되어 peer의 org에 속해있는 member가 아닌 외부 member도 접근할 수 있게 되었다.
docker-compose.yaml에서 피어 관련된 도커 설정을 보면 포트 2개가 열려있는 것을 볼 수 있다.
peer0.org2.example.com:
container_name: peer0.org2.example.com
extends:
file: base.yaml
service: peer-base
environment:
- CORE_PEER_ID=peer0.org2.example.com
- CORE_PEER_LOCALMSPID=Org2MSP
- CORE_PEER_ADDRESS=peer0.org2.example.com:7051
ports:
- 8051:7051 #peer가 일반적으로 다른 피어 또는 오더러와 통신하는 포트
- 8053:7053 #이벤트를 위해서 외부 어플리케이션과 통신하는 포트
volumes:
- ./channel/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/:/etc/hyperledger/crypto/peer
depends_on:
- orderer.example.com
network-config.yaml에서는 특정 피어의 eventSource를 설정할 수 있다.
peer1.org1.example.com:
endorsingPeer: false
chaincodeQuery: true
ledgerQuery: true
eventSource: false
peer0.org2.example.com:
endorsingPeer: true
chaincodeQuery: true
ledgerQuery: true
eventSource: true
만약 eventSource
가 True인 경우에는 SDK가 이 피어는 event를 받을 수 있다고 판단하여 connection을 한다.
그리고 eventSource
가 True인 피어와는 아래 적힌 eventURL을 통해 접근이 가능하다.
peer0.org2.example.com:
url: grpcs://localhost:8051
eventUrl: grpcs://localhost:8053
grpcOptions:
ssl-target-name-override: peer0.org2.example.com
tlsCACerts:
path: artifacts/channel/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
ChannelEventHub
클래스를 통해 채널 기반 이벤트 서비스를 이용할 수 있다.
ChannelEventHub
를 사용하기 위해서는 newChannelEventHub
객체를 사용하여 ChannelEventHub
인스턴스를 생성한다.
그리고 생성한 인스턴스를 통해 관련 메서드를 실행하여 원하는 이벤트를 가져온다.
위의 이벤트들은 모두 Hyperledger Fabric SDK에서 실행된다.
📌 블록체인 용어집
박도준님 안녕하세요,
헤드헌팅사 유니코써치의 김만규 컨설턴트입니다.
블록체인 관련 Job Position JD에서 모르는 사항을 공부 중
도준님의 블로그에서 좋은 자료를 발견, 덕분에 공부하는데 어려움이 다소 해소되었습니다.
감사드리며, 좋은 글 기대하겠습니다.
또한 혹시 이직을 준비하고 계시다면 제가 도움 받았듯, 도준님의 이직과정이 즐거운 경험이 될 수 있도록 최선을 다해 지원하겠습니다.
감사합니다.
Tel) 010 4913 7163
Email) leo@unicosearch.com
Linkedin) https://www.linkedin.com/in/no1recruiting/