7. Peers(2)
피어 및 채널
일반적인 구성 요소인 피어 노드, orderer 노드 및 어플리케이션은 채널에 가입함으로써 공동 작업을 통해 해당 채널과 연결된 원장의 동일한 복사본을 공동으로 공유하고 관리하는 데 동의한다. 개념적으로 채널은 친구 그룹과 유사하다고 생각할 수 있다. 한 사람에게는 여러 개의 친구 그룹이 존재할 수 있으며, 각 그룹에는 함께하는 활동이 있다. 이 그룹은 친구들의 그룹과 비교하여 완전히 분리된 그룹일 수도 있고, 그룹 간에 연관된 관계가 있을 수도 있다. 그럼에도 불구하고 각 그룹은 일종의 "규칙"을 가진 독립체이다.
채널을 사용하면 특정 피어 및 어플리케이션 집합이 블록 체인 네트워크 내에서 서로 통신할 수 있다. 이 예에서 어플리케이션 A는 채널 C를 사용하여 피어 P1 및 P2와 직접 통신할 수 있다. 이 채널을 특정 어플리케이션과 피어 간의 통신 경로로 생각할 수 있다. (위 그림에선 orderer가 표시되지 않았지만 실제론 존재해야 한다.)
채널은 피어와 같이 물리적으로 존재하지 않는다. 채널을 물리적 피어 집단에 의해 형성된 논리적 구조로 생각하는 것이 더 적절하다. 피어는 채널에 대한 액세스 및 관리를 위한 제어 지점을 제공한다.
피어 및 조직
블록 체인 네트워크는 하나의 조직보다는 다수의 조직에 의해 관리된다. 이러한 분산 네트워크가 조직에 의해 소유되기 때문에 피어는 이러한 분산 네트워크 구축의 중심이다.
다수의 조직이 있는 블록 체인 네트워크의 피어.
블록 체인 네트워크는 서로 다른 조직들이 소유하고 참여하는 피어들로 구성된다. 이 그림에서는 8개의 피어와 4개의 조직으로 구성된 네트워크가 있다. 채널 C는 네트워크 N의 피어 P1, P3, P5, P7 및 P8를 연결한다. 이러한 조직이 소유한 다른 피어는 이 채널에 가입하지 않았지만 일반적으로 하나 이상의 다른 채널에 가입한다. 특정 조직에서 개발한 어플리케이션은 다른 조직의 어플리케이션과 마찬가지로 자신의 조직의 피어와 연결된다.
네트워크는 리소스는 리소스를 제공하는 여러 조직에 의해 형성되고 관리된다. 피어는 이 항목에서 논의중인 리소스이지만 조직에서 제공하는 리소스는 피어 외에도 다양하다. 이것에는 원칙이 있는데 조직이 리소스를 집단 네트워크에 제공하지 않으면 네트워크는 존재하지 않는다. 또한 네트워크는 이러한 조직에서 제공하는 리소스에 따라 확장 및 축소된다.
위 그림에서 Ordering service외에 중앙 리소스가 없다. 이것은 조직이 네트워크를 형성하는 리소스를 기여하기 전까지는 네트워크가 존재하는 의미가 없는 것을 뜻한다. 네트워크는 개별 조직에 의존하지 않기 때문에 네트워크에 조직이 남아있는 한 계속 존재할 것이다. 이것은 네트워크가 분산화 되었음을 뜻한다.
그림에서 같이 서로 다른 조직의 어플리케이션은 서로 같을 수도, 다를 수도 있다. 왜냐하면 어플리케이션이 피어의 원장 사본을 어떻게 처리하는지는 전적으로 조직에 달려 있기 때문이다. 이것은 비록 각 피어가 정확히 동일한 원장 데이터를 호스트하지만 어플리케이션과 프레젠테이션 논리는 각 조직마다 다를 수 있음을 의미한다.
어플리케이션은 요구되는 원장의 특성에 따라 해당 조직의 피어와 연결하거나 또는 다른 조직의 피어와 연결할 수 있다. 원장과 쿼리의 상호 작용의 경우 일반적으로 어플리케이션은 자신이 속한 조직의 피어와 연결된다. 원장과 업데이트의 상호 작용의 경우 원장 업데이트를 승인하는 데 필요한 모든 조직을 대표하는 피어들과 어플리케이션을 연결해야 한다.
피어 및 ID
피어는 특정 인증 기관의 디지털 인증서를 통해 자신에게 할당된 ID를 갖는다. 디지털 ID는피어에 대해 검증 가능한 많은 정보를 제공하는 신분증과 비슷하다. 네트워크의 모든 피어는 해당 조직의 관리자에 의해 디지털 ID를 부여받는다.
피어가 채널에 연결되면 디지털 인증서는 채널 MSP를 통해 피어가 속한 조직을 식별한다. 이 예제에서 P1과 P2는 CA1이 발행한 ID를 갖는다. 채널 C는 채널 구성 정책에서 ORG1.MSP를 사용하여 CA1의 ID가 Org1과 연관되어 있다고 결정한다. 마찬가지로 P3와 P4는 ORG2.MSP에 의해 Org2의 일부분으로 식별된다.
피어가 채널을 사용하여 블록 체인 네트워크에 연결할 때마다 채널 구성 정책은 권한을 결정하기 위해 피어의 ID를 사용한다. MSP에서 조직과 ID의 매핑을 제공한다. 즉, MSP는 피어가 특정 조직으로부터 특정 역할을 부여받는 방식을 결정하고 그에 따라서 피어는 블록체인 리소스에 대한 적절한 접근 권한을 얻는다. 또한 피어는 한 개의 조직에서만 소유할 수 있으므로 한 개의 MSP를 갖는다. 결론적으로 MSP는 블록 체인 네트워크에서 각 피어의 ID와 특정 조직의 역할을 매핑한다.
블록체인 네트워크와 통신하는 모든 것과 마찬가지로 피어 또한 디지털 인증서와 MSP로부터 조직 ID를 얻는다. 블록 체인 네트워크와 상호 작용하려는 경우 피어, 어플리케이션, 최종 사용자, 관리자 및 orderer는 ID 및 관련 MSP가 있어야 하며, ID를 사용하여 블록 체인 네트워크와 상호 작용하는 모든 주체에게 이름을 제공한다.
마지막으로 피어가 실제로 위치하는 곳은 중요하지 않다. (클라우드나 조직이 소유한 데이터 센터나 로컬 시스템에 위치할 수도 있다.) ID를 사용하야 피어가 특정 조직에 소속되어 있음을 식별할 수 있다. 그림에서 P3는 Org1의 데이터 센터에도 호스팅 될 수 있지만 CA2에서 발행된 디지털 인증서가 있는 이상 P3는 Org2가 소유한다.
피어 및 Orderers
우리는 피어의 원장과 체인 코드를 호스팅하는 블록 체인 네트워크의 기반을 형성하는 것을 보았다. 그러나 어플리케이션과 피어가 서로 상호 작용하여 모든 피어의 원장이 동기화 되도록 하는 메커니즘은 orderer라고 하는 특수 노드가 중재한다.
업데이트 트랜잭션은 단일 피어가 자체적으로 원장을 업데이트 할 수 없기 때문에 쿼리 트랜잭션과 매우 다르다. 업데이트는 네트워크내의 다른 피어의 승인이 필요하다. 네트워크의 다른 피어들은 업데이트 트랜잭션이 해당 피어의 로컬 원장에 적용되기 전에 원장 업데이트를 승인해야 한다. 이 프로세스를 합의 (consensus)라고 하며, 간단한 쿼리보다 완료하는데 훨씬 오래 걸린다. 모든 피어가 트랜잭션을 승인하고 거래가 원장에 기록되면 피어는 연결된 어플리케이션에 원장이 갱신되었음을 통보한다.
특히 원장을 업데이트하려는 어플리케이션은 3단계의 프로세스와 관련되어 있어 블록 체인 네트워크의 모든 피어가 원장을 서로 일관되게 유지할 수 있다. 첫 번째 단계에서 어플리케이션은 원장 업데이트의 보증을 제공하는 endorsing peer들의 하위집합과 함께 동작한다. 하지만 아직 원장 사본에 업데이트를 적용하지 않는다. 두 번째 단계에서는 이러한 별도의 보증이 트랜잭션으로 함께 묶여서 블록으로 포장된다. 마지막 단계에서 이러한 블록은 피어의 원장 사본에 적용되기 전에 각 트랜잭션이 검증되는 모든 피어로 다시 분배된다.
보았듯이 orderer 노드가 이 프로세스의 핵심이므로 어플리케이션 및 피어가 orderer 노드를 사용하여 분산되고 복제된 원장에 지속적으로 적용할 수 있는 원장 업데이트를 생성하는 방법을 좀 더 자세히 살펴보자.
1단계 : 제안
트랜잭션 워크플로우의 1단계에는 애플리케이션과 피어 집합 간의 상호 작용이 있다. (orderer는 아직 포함되지 않는다.) 1단계는 제안된 체인 코드 호출의 결과에 동의하도록 어플리케이션이 다른 조직의 endorsing peer들에게 승인을 요청한다.
1단계를 시작하기 위해 어플리케이션은 트랜잭션 제안서를 생성하여 승인을 위해 필요한 각 피어 집합에게 보낸다. 그런 다음 각 endorsing peer들은 트랜잭션 제안 응답을 생성하기 위해 트랜잭션 제안서를 사용하여 독립적으로 체인 코드를 실행시킨다. 이 업데이트는 원장에 적용되지 않고 단순히 서명한 후 어플리케이션으로 반환된다. 어플리케이션이 충분한 수의 서명된 제안 응답을 받으면 첫 번째 단계는 완료된다.
트랜잭션 제안서는 서명된 제안 응답을 반환하는 피어에 의해 독립적으로 실행된다. 이 예에서 애플리케이션 A1은 트랜잭션 T1의 제안서 P를 생성하여 채널 C에서 피어 P1과 피어 P2 모두에게 전송한다. P1은 트랜잭션 T1의 제안서 P를 사용하여 S1을 실행하고 E1에서 보증하는 트랜잭션 T1의 응답 R1을 생성한다. P1과는 독립적으로 P2는 트랜잭션 T1 제안서 P를 사용하여 S1을 실행하고 E2로 보증하는 트랜잭션 T1의 응답 R2를 생성한다. 어플리케이션 A1은 트랜잭션 T1에 대해 두 개의 승인된 응답인 E1과 E2를 받는다.
처음에는 일련의 제안된 최신원장을 생성하기 위해 어플리케이션이 피어 집합을 선택한다. 어떤 피어가 어플리케이션에 의해 선택될까? 그것은 네트워크에 의해 승인되기 전에 제안된 최신원장을 승인해야 하는 조직의 집합을 정의하는 보증 정책에 따라 다르다. 이것은 합의를 의미한다. 관련된 모든 조직은 업데이트가 피어의 원장에 적용되기 전에 승인을 받아야 한다.
피어는 디지털 서명을 추가하고 개인키를 사용하여 전체 페이로드에 서명함으로써 제안 응답을 보증한다. 이 승인은 이후에 이 조직의 피어가 특정 응답을 생성했음을 입증하는데 사용될 수 있다. 그림에서 피어 P1이 조직 Org1에 의해 소유된 경우 보증 E1은 "원장 L1에 대한 트랜잭션 T1의 응답 R1이 Org1의 피어 P1에 의해 제공되었습니다!"라는 디지털 증거이다.
1단계는 어플리케이션이 충분한 피어로부터 서명된 제안 응답을 받으면 종료된다. 우리는 서로 다른 피어들이 동일한 트랜잭션 제안에 대해 서로 다르고 일관성이 없는 트랜잭션 응답을 반환할 수 있음을 알고 있어야 한다. 이것은 단순히 다른 시간에 원장을 보유한 다른 피어에게 그리고 다른 상태에서 이런 결과가 나타난다. 이런 경우 어플리케이션은 간단히 좀 더 최신의 제안 응답을 요청할 수 있다. 그럴 가능성은 적지만 체인코드가 비 결정론적이기 때문에 피어마다 결과가 다르게 나타날 수 있다. 비결정론은 체인코드와 원장의 적이다. 그 이유는 일관적이지 않은 결과가 원장에 적용되면 심각한 문제를 일으키기 때문이다. 각 피어는 트랜잭션의 결과가 비 결정적이더라도 그것을 알 수 없다. 따라서 비 결정성이 감지되기 전에 비교를 위해 트랜잭션 응답을 모아야한다. (비결정론은 트랜잭션 파트에서 자세히 다룬다.)
1단계가 끝나면 어플리케이션은 일관성 없는 트랜잭션 응답을 자유롭게 폐기할 수 있다. 만약 어플리케이션이 비 동기화된 트랜잭션 응답을 사용하여 원장을 업데이트 하려고 하면 거부될 것이다.
2단계 : 패키지
트랜잭션 워크플로우의 두 번째 단계는 패키징이다. orderer는 이 프로세스의 중추적인 역할을 한다. Orderer는 여러 어플리케이션에서 보증된 트랜잭션 제안 응답을 포함하는 트랜잭션을 받는다. Orderer는 각 트랜잭션을 순서대로 정렬하고 트랜잭션 집단을 블록으로 패키징한다. 그리고 원래의 endorsing peer를 포함하여 orderer와 연결된 모든 피어에게 배포할 준비를 한다.
orderer 노드
의 첫 번째 역할은 제안된 최신원장을 패키징하는 것이다. 그림에서 어플리케이션 A1은 E1 및 E2가 승인한 트랜잭션 T1을 orderer O1에 전송한다. 마찬가지로 어플리케이션 A2는 E1이 승인한 트랜잭션 T2를 orderer O1에게 전송한다. O1은 어플리케이션 A1의 트랜잭션 T1과 어플리케이션 A2의 트랜잭션 T2를 같은 네트워크의 다른 어플리케이션의 트랜잭션과 함께 B2 블록으로 패키징한다. B2에서 트랜잭션 순서는 T1, T2, T3, T4, T6, T5이다. 이러한 순서는 트랜잭션이orderer 노드에 도착한 순서가 아닐 수도 있다.
orderer는 네트워크에 있는 특정 채널의 여러 개의 어플리케이션으로부터 제안된 원장 갱신을 동시에 수신한다. 그리고 이러한 제안된 업데이트를 잘 정의된 순서로 정렬한 다음 배포를 위해 블록으로 패키지화 한다. 이 블록들은 블록 체인의 블록이 될 것이다! orderer가 원하는 크기의 블록을 생성하거나 제한된 시간이 지나면 블록은 특정 채널에서 연결된 모든 피어로 전송된다. 이 블록이 3단계에서 어떻게 처리되는지 보도록 하자.
한 블록내의 트랜잭션 순서가 orderer에게 트랜잭션이 도착한 순서와 반드시 같지는 않다는 점은 주목할 가치가 있다! 트랜잭션은 블록에 임의의 순서로 패키징 될 수 있으며 그 순서는 실행 순서가 된다. 중요한 것은 정해진 엄격한 순서가 있다는 것이다.
이 블록 내에서의 트랜잭션의 엄격한 순서때문에 Hyperledger 패브릭은 동일한 트랜잭션을 여러 블록으로 패키징할 수 있는 다른 블록 체인과 조금 다르게 구별된다. Hyperledger Fabric에서는 트랜잭션이 블록에 일단 기록되면 순서는 불변하기 때문에 orderer에 의해 생성된 블록은 final이라고도 한다. 하이퍼 레저 패브릭은 ledger fork라고 알려진 재앙이 발생할 수 없음을 뜻한다. 트랜잭션이 블록에 기록되면 이후에 해당 트랜잭션에 대한 내용을 수정할 수 없다.
피어는 원장과 체인 코드를 호스팅하는 반면, orderer는 그렇지 않다는 것을 이제 알 수 있다. orderer에게 도착한 모든 트랜잭션은 기계적으로 하나의 블록에 포장되어 있다. orderer는 트랜잭션의 가치에 대해 아무런 판단도 하지 않는다. 이것은 Hyperledger Fabric의 중요한 특징이다. 모든 트랜잭션이 엄격한 순서로 정렬되며, 트랜잭션이 결코 삭제되거나 우선 순위가 존재하지 않는다.
결론적으로 orderer는 제안된 트랜잭션을 수집한 뒤 정렬하고 패키지로 포장하여 배포하는 간단하면서도 중요한 프로세스를 담당한다.
3단계 : 유효성 검사
트랜잭션 워크플로우의 최종 단계에서는 orderer에서 peer에게 블록을 배포하고 이후에 유효성 검사를 수행하여 원장에 적용한다. 특히, 각 피어에서 블록 내의 모든 트랜잭션은 원장에 적용되기 전에 모든 관련 조직에서 일관되게 보증되도록 유효성이 검사된다. 실패한 트랜잭션은 감사 목적을 위해 보유되지만 원장에 적용되지 않는다.
orderer 노드의 두 번째 역할은 피어로 블록을 배포하는 것이다. 그림에서 orderer O1은 블록 B2를 피어 P1와 피어 P2에 배포한다. 피어 P1은 블록 B2를 수신하여 새로운 블록이 P1의 원장 L1에 추가된다. 동시에 피어 P2도 블록 B2를 수신하여 새로운 블록이 P2의 원장 L1에 추가된다. 이 프로세스가 완료되면 원장 L1이 피어 P1 및 P2에서 일관되게 업데이트되고 각각 연결된 어플리케이션에 트랜잭션이 처리되었음을 보고한다.
3단계는 orderer가 연결된 모든 피어에게 블록을 배포하는 것으로 시작된다. 새로운 블록이 생성되면 피어는 채널내의 orderer에게 연결된다. orderer에게 연결된 모든 피어가 새 블록의 사본을 전송받는다. 각 피어는 이 블록을 독립적으로 처리하지만 채널의 다른 모든 피어와 정확히 같은 방식으로 처리한다. 이렇게 하면 원장이 일관되게 유지될 수 있다. 또한 모든 피어가 orderer와 연결될 필요는 없다는 점에 유의하자. 피어는 gossip 프로토콜을 사용하여 블록을 다른 피어에게 전달할 수 있으며, 이들 또한 독립적으로 처리할 수 있다.
블록을 수신하면 피어는 각 트랜잭션을 블록에 기록된 순서대로 처리한다. 모든 트랜잭션에 대해 각 피어는 트랜잭션을 생성한 체인 코드의 보증 정책에 명시된 조직이 거래를 승인했음을 확인한다. 예를 들어, 정책에 따라 일부 트랜잭션은 하나의 조직만이 보증하는 반면, 일부 트랜잭션은 유효하다고 간주되기 전에 여러 조직의 보증을 요구할 수 있다. 이 유효성 확인 프로세스는 모든 관련 조직이 동일한 결과를 생성했음을 검증한다. 또한 이 유효성 검증은 1단계의 보증 확인과는 다르다. 이 단계의 검증은 endorsing 피어로부터 응답을 수신하고 제안 트랜잭션의 전송을 결정하는 어플리케이션이다. 어플리케이션이 잘못된 트랜잭션을 보내어 보증 정책을 위반하는 경우에도 피어는 3단계의 유효성 확인 프로세스에서 트랜잭션을 거부할 수 있다.
트랜잭션이 올바르게 승인되면 피어는 이를 원장에게 적용하려고 시도한다. 피어는 원장 일관성 검사를 수행하여 원장의 현재 상태가 업데이트 제안서가 생성되었을 때의 원장의 상태와 호환되는지 확인해야한다. 예를 들어 또다른 트랜잭션이 원장의 동일한 자산을 업데이트하여 트랜잭션 업데이트가 더 이상 유효하지 않아 더 이상 원장에 적용할 수 없게 될 수 있다. 이러한 방식으로 각 피어의 원장 사본은 각각 유효성 검사에 대한 동일한 규칙을 따르기 때문에 네트워크 전체에서 일관되게 유지된다.
피어는 각 트랜잭션의 유효성을 성공적으로 확인한 후 원장을 업데이트한다. 실패한 트랜잭션은 원장에 적용되지 않지만 성공적인 트랜잭션과 같이 감사 목적으로 보유된다. 즉, 피어 블록은 각 트랜잭션에서 유효하거나 유효하지 않다는 표시를 제외하고는 orderer로부터 수신된 블록과 거의 동일하다.
3단계에서는 체인 코드 실행이 필요하지 않다. 이는 1단계에서만 수행되는 것이므로 중요하다. 이는 체인 코드가 블록 체인 네트워크 전체가 아닌 승인하는 노드에서만 사용 가능하다는 것을 의미한다. 이는 조직을 승인하는 체인코드의 로직을 기밀로 유지되도록 하는데 도움을 준다. 이는 승인된 트랙잭션인지 여부에 관계없이 채널의 모든 피어와 공유되는 체인 코드의 결과(거래 제안서 응답)와 대조된다. Endorsing peer의 전문화는 확장성을 높이기 위해 설계되었다.
마지막으로, 블록이 피어의 원장에 기록될 때마다 해당 피어는 이벤트를 생성한다. 블록 이벤트에는 전체 블록 컨텐츠가 포함되며 블록 트랜잭션 이벤트에는 블록의 각 트랜잭션의 유효성 확인 여부와 같은 요약 정보만 포함된다. 체인 코드 실행으로 생성된 체인 코드 이벤트도 이 때 발생할 수 있다. 어플리케이션은 이러한 이벤트 유형에 등록할 수 있으므로 이벤트가 발생했을 때 통보를 받을 수 있다.
요약하면 3단계는 orderer가 생성한 블록이 원장에 일관되게 적용되는지 확인한다. 트랜잭션을 블록으로 정렬하면 각 피어는 최신 블록이 블록 체인 네트워크 전체에서 일관되게 적용되는지 확인할 수 있다.
orderers 및 합의
이 전체 트랜잭션 워크플로우 프로세스를 합의라고 한다. 그 이유는 orderer가 중재하는 프로세스에서 모든 피어가 트랜잭션의 순서 및 내용에 대해 모두 동의했기 때문이다. 합의는 여러 단계의 프로세스이며, 어플리케이션은 모든 프로세스가 완료되어서 원장이 업데이트될 때만 통보받는다.
우리는 향후 orderer에 대해 더 자세하게 논의할 예정이지만, 지금은 orderer를 어플리케이션으로부터 원장 업데이트 제안서를 수집하고 유효성을 검사하기 위해 블록을 피어에게 배포하고 검증된 블록을 원장에 추가하는 노드로만 생각하자.