본문 바로가기

Hyperledger Fabric/Document

[HYPERLEDGER FABRIC v1.1]Architecture Reference

Architecture Explained

 아키텍처 설명

Hyperledger Fabric가 제공하는 이점

  • Chaincode의 신뢰 유연성(Chaincode trust flexibility) : 이 아키텍처는 체인코드(블록체인 어플리케이션)을 주문서비스와 분리하였습니다. 이는 주문서비스의 한 세트 노드에 의해 제공 될수 있으며, 일부 오류나 오작동을 수용할 수 있습니다. endorsers는 각 체인코드마다 다를 수 있습니다.
  • 확장성(Scalability) : 특정 체인코드를 담당하는 endorser 노드는 주문자와 역할이 다르기 때문에 동일한 노드에서 기능을 수행하는 것 보다 확장성이 좋습니다. 특히 서로 다른 체인 코드가 분리된 endorser를 지정하면 endorser 사이에 체인코드를 분할하고 패러럴 하게 체인코드를 실행 하여 보증할 수 있습니다. 게다가 비용이 많이 드는 체인코드 실행은 주문 서비스의 중요한 경로에서 제거가 됩니다.
  • 기밀유지(Confidentiality) : 컨텐츠 및 해당 트랜잭션의 상태 업데이트와 관련하여 기밀성 요구 사항이 있는 체인코드 배포가 용이합니다.
  • 컨센서스의 모듈화(Consensus modularity) : 모듈식으로 컨센서스가 플러그인이 가능하도록 수성되었습니다.

시스템 아키텍처

블록체인은 서로 통신하는 많은 노드로 구성된 분산 시스템입니다. 블록체인은 chaincode 라는 프로그램으로 실행하여 트랜잭션을 발생시키며 상태 및 원장 데이터를 보유하고 있습니다.체인코드는 트랜잭션을 호출하는 핵심 요소 입니다. 거래는 "보증" 되어야 되며 승인된 거래만 커밋되어 해당 상태에 영향을 미칠수 있습니다.

  • 관리 기능 및 매개 변수에는 하나 이상의 특수한 체인코드(시스템 체인 코드)가 있을수 있습니다.

트랜잭션(Transactions)

거래에는 두가지 유형이 있습니다.

  • 배포 트랜잭션(Deploy transactions) : 새로운 체인코드를 생성하고 프로그램을 매개변수로 사용합니다. 배포 트랜잭션이 성공적으로 실행되면 체인코드가 블록체인 위에 설치가 됩니다.
  • 호출 트랜잭션( Invoke transactions) : 이전에 배포된 체인코드의 컨텍스트에서 작업을 수행하는 부분입니다. 호출 트랜잭션은 체인코드와 제공된 기능 중 하나ㅜ를 참조합니다. 성공하면 체인코드에 지정된 함수를 실행 합니다. 이 함수는 해당 상태를 수정하고 내용을 반환 합니다.

다음에 설명하듯이 배포 트랜잭션은 호출 트랜잭션의 특수한 경우이며 새로운 체인코드를 만들어서 배포 하는 것은 시스템체인코드의 호출 트랜잭션에 해당 합니다.

비고 : 이 문서는 현재 트랜잭션이 새로운 체인코드를 생성하거나 이미 배치 된 하나의 체인코드에 의해 제공되는 연산을 호출한다고 가정 합니다. 이문서에서 a 쿼리 트랜잭션, b 교차 체인 트랜잭션을 지원

블록체인 데이터 구조(Blockchain datastructures)

상태(State)

블록체인의 최신 상태는 Key 값이 이름이고 Value가 내용이 key-value store 로 모델링이 되어있습니다. 이 부분은 블록체인에 put 과 get kvs 로 체인코드로 작업이 진행 되고 있습니다.

상태는 지속적으로 저장되고 상태에 대한 업데이트가 기록되게 됩니다. kvs가 상태 모델로 채택되어 사용되고 있지만 RDBMS 또는 다른 솔루션으로 대체하여 사용할 수도 있습니다.

KVS의 s(상태)는 K -> (V X N) 으로 매핑 됩니다.

  • K는 키의 집합
  • V는 값의 집합
  • N은 제한 없이 순서대로 설정되는 버전 번호입니다. 다음 함수 : N -> N은 N의 구성요소를 바탕으로 다음 버전 번호를 반환합니다

V와 N은 모두 특수 요소 ⊥ (빈 유형)를 포함하며, N은 가장 낮은 요소입니다. 처음에는 모든 키가 (⊥, ⊥)에 매핑됩니다. s (k) = (v, ver)에 대해 우리는 v를 s(k).value로 표시하고 ver은 s(k)로 나타내게 됩니다.

KVS 운영은 다음과 같이 모델링됩니다.

  • k ∈ K와 v ∈ V에 대해 put (k, v)를 취하고 블록 체인 상태 s를 취하여
    s'(k) = (v, next (s) (k') = s (k') k' != k
  • get(k)는 s(k)를 반환 합니다.

상태는 peer에 의해 유지되지만 주문자 및 고객에 의해 유지되지는 않습니다.

상태파티션 : KVS의 키는 특정 체인코드의 트랜잭션만이 체인코드에 속하는 키를 수정 할수 있다는 의미에서 특정 체인코드에 속하도록 이름에서 인식 할 수 있습니다. 원칙적으로 모든 체인코드는 다른 체인코드에 속한 키를 읽을 수 있습니다. 두개 이상의 체인코드에 속하는 상태를 수정하는 교차 트랜잭션에 대한 지원이 v1 이후 가능해 졌습니다.

원장

Ledger는 시스템 운영 중에 발생하는 모든 성공적인 상태 변경(유효한 트랜잭션에 한하여) 및 상태 변경 시도 실패(유효하지 않는 트랜잭션에 대하여) 의 검증이 가능하도록 기록을 제공합니다.

Ledger는 주문서비스에 의해 트랜잭션 블록을 완전히 정렬 된 해시 체인으로 구성합니다. 해시 체인은 원장에 블록의 전체 순서를 정하고 각 블록에 정렬된 트랜잭션의 배열을 포함시킵니다. 이렇게 하면 모든 거래에서 전체 주문에 순서가 부과(타임 스탬프) 되는 것입니다.

Ledger는 모든 peer 및 선택적으로 orderer와의 하위 집합으로 보관 됩니다. orderer 입장에서 원장을 원고 (OrdererLedger)라고 부르지 만 피어 (PeerLedger)에 대해서는 원장을 참조하는 것입니다. PeerLedger는 OrdererLedger와 다른 점은 peer은 유효하지 않은 트랜잭션과 유효하지 않은 트랜잭션을 구별하는 비트 마스크를 로컬에서 유지한다는 점입니다

PeersLedger는 피어 투 피어를 할 수 있습니다. OrdererLedger는 내결함성 및 가용성 (PeerLedger)을 유지 관리하며 주문 서비스 에 속하게 됩니다.

노드(Node)

노드는 블록체인의 통신 엔티티 입니다. 노드(Node)는 동일한 유형의 여러 노드가 동일한 실제 서버에서 실행 될 수 있다는 점에서는 논리적인 기능입니다. 신뢰도메인(trust domains)에서 노드를 그룹화하고 노드를 제어하는 논리 엔티티와 관련된 노드의 수를 계산 합니다.

노드에는 3가지 유형이 있습니다.

  1. 클라이언트 또는 제출 클라이언트(submitting-client) : 실제 클라이언트 호출을 endorser에게 제출하고 거래 제안서를 주문 서비스에 브로드 캐스팅 하는 클라이언트
  2. 피어(peer) : 트랜잭션을 커밋하고 상태와 원장의 복사본을 유지하는 노드. peer가 특별한 endorser의 역할도 수행할 수도 있습니다.
  3. 주문 서비스 노드 또는 주문자(Ordering-service-node or orderer)  : 주문의 브로드캐스팅과 같은 배달의 보증을 구현하는 통신 서비스를 실행하는 노드

Client

클라이언트는 최종 사용자를 대신하여 작동하는 엔티티를 나타냅니다. 블록체인과 통신하기 위해서는 peer에 연결해야 합니다. 클라이언트는 원하는 peer에 연결 할 수 있습니다. 클라이언트 트랜잭션을 작성하고 이를 통하여 트랜잭션을 호출 합니다.

PEER

peer은 주문 서비스의 블록형태로 요청된 상태를 업데이트 받고 상태와 원장의 관계를 유지 관리합니다.

peer은 endorsing peer이나 endorser의 역할을 수행 할 수 있습니다. endorsing peer의 특수 기능은 특정 체인코드와 관련하여 발생하며 커밋 되기 전에 트랜잭션을 승인 하는 것으로 구성됩니다. 모든 체인코드는 보증 정책을 지정할 수 있습니다. 이 정책은 유효한 트랜잭션 보증에 필요한 충분 조건으로 정의합니다. 새로운 체인코드를 설치하고 배포 트랜잭션의 특별한 (배포) 은 다음과 같습니다. 이는 시스템 체인코드의 보증 정책으로 지정됩니다.

Ordering service nodes (Orderers)

orderers의 형태는 주문 서비스, 즉 배달의 보장을 제공하는 통신 패브릭입니다. 주문 서비스는 여러가지 방법으로 구현 될 수 있습니다. 예를 들어 개발 및 테스트에 사용되는 중앙 집중식 서비스 부터 다양한 네트워크 및 노드의 결함 모델을 대상으로 하는 분산된 프로토콜에 이르기 까지 다양합니다.

주문 서비스는 클라이언트와 peer에게 공유하는 통신채널을 제공하여 트랜잭션이 포함된 메시지에 대한 브로드 캐스트 서비스를 제공합니다. 클라이언트를 채널에 연결하고 채널에서 메시지를 브로드캐스팅 한 다음 모든 피어에 전달 할수 있습니다. 이채널은 모든 메시지의 배달, 즉 총 주문 배송 및 메시지 전달의 안정성을 지원합니다. 즉 채널은 연결된 모든 피어에게 동일한 메시지를 보내게 되고 논리적 순서로 모든 피어에게 내용을 전달 합니다. 이 통신의 보장은 총 주문에 대한 브로드캐스트 또는 합의라고도 합니다. 분산 시스템과 관련하여 전달된 메시지는 블록체인의 상태에 포함될 후보 트랜잭션입니다.

Partitioning (ordering service channels) : 주문 서비스의 게시/가입/구독에 관한 메시징 시스템의 주제를 비슷한 여러 채널에 지원할 수 있습니다. 클라이언트는 주어진 채널에 연결 할 수 있으며 메시지를 보내고 도착한 메시지를 확인 할수 있습니다. 채널을 파티션으로도 생각할 수 있습니다. 한 채널에 연결하는 클라이언트는 다른 채널의 존재를 인식하지 못하지만 클라이언트는 여러 채널에 연결 할 수 있습니다. Hyperledger Fabric에 포함된 일부 주문 서비스의 구현은 여러 채널을 지원하지만 여기서는 편의를 위해 주문서비스가 단일 채널/ 주제로 구성 된다고 가정 합니다.

Ordering service API. : peer은 주문 서비스에서 제공하는 인터페이스를 통해 주문 서비스에서 제공하는 채널에 연결합니다. 주문 서비스 API는 두가지 기본 작업(비동기 이벤트)으로 구성됩니다.

TODO  : 클리이언트/peer의 시퀀스 번호 아래 특정 블록을 패치하기 위한 API를 추가 할 예정입니다.

  • broadcast(blob) : 클라이언트는 채널을 통한 전파를 위해 임의의 메시지 BLOB를 브로드 캐스트하기 위해이를 호출합니다. 이것은 서비스에 요청을 보낼 때 BFT 컨텍스트에서 요청 (blob)이라고도합니다.
  • deliver(seqno, prevhash, blob) : 주문 서비스는 peer에 대해 이것을 호출하여 지정된 음수가 아닌 정수 시퀀스 번호 (seqno)와 가장 최근에 전달 된 blob (prevhash)의 해시를 사용하여 메시지 blob을 전달합니다. 즉, 주문 서비스의 출력 이벤트입니다. deliver ()는 pub-sub 시스템에서는 notify () 또는 BFT 시스템에서 commit ()이라고도합니다.

원장및 블록 형성 : 원장에는 주문 서비스가 보낸 모든 데이터가 포함됩니다. 이것은 전달 (seqno, prevhash, blob) 이벤트의 시퀀스이며, 앞에서 설명한 prevhash의 계산에 따라 해시 체인을 형성합니다.

효율성을 위해 대부분의 경우 개별 트랜잭션 (blob)을 출력하는 대신 주문 서비스는 단일 전달 이벤트 내에서 blob 및 내용 블록을 그룹화합니다 (일괄 처리). 이 경우, 주문 서비스는 각 블록 내의 blob 순서를 부과하고 전달합니다. 블럭 내의 blob수는 주문 서비스 구현에 의해 동적으로 선택 될 수있다.

다음에서는 표현의 편의를 위해 서비스 속성(이 하위 섹션의 나머지 부분)를 정의하고 전달 이벤트 당 하나의 BLOB를 가정하여 트랜잭션 승인 워크 플로 (섹션 2)를 설명합니다. 블록에 대한 전달 이벤트가 블럭 내의 BLOB의 위에서 언급 한 결정 순서에 따라 블록 내의 각 BLOB에 대한 개별 전달 이벤트의 시퀀스에 해당한다고 가정하면 이러한 이벤트는 블록으로 쉽게 확장됩니다.

주문서비스 속성(Ordering service properties)

주문서비스에서 보장되는 것은 브로드캐스팅 된 메시지에 어떤 일이 일어나고 전달된 메시지 간에 어떤 관계가 존재 하는지 규정하는 것입니다. 이러한 보증은 다음과 같습니다.

  1. 안전성 (일관성 보장) : 피어가 채널에 충분히 오랫동안 연결되어있는 경우 (연결이 끊어 지거나 중단 될 수는 있지만 다시 시작되고 다시 연결되는 경우) 동일한 일련의 전달 된 (seqno, prevhash, blob) 메시지가 표시됩니다. 즉, 출력 (deliver () 이벤트)은 모든 피어에서 동일한 순서로 시퀀스 번호에 따라 발생하며 동일한 시퀀스 번호에 대해 동일한 내용 (blob 및 prevhash)을 전달합니다. 이것은 논리적 순서 일 뿐이며, 한 피어의 deliver (seqno, prevhash, blob)는 다른 피어에서 동일한 메시지를 출력하는 deliver (seqno, prevhash, blob)에 대한 실시간 관계에서 발생할 필요가 없습니다. 다르게 말하자면 특정 seqno가 주어지면 두 개의 올바른 피어가 다른 prevhash 또는 blob 값을 제공하지 않습니다. 또한, 일부 클라이언트 (피어)가 실제로 브로드 캐스트 (blob)를 호출하지 않고, 바람직하게는 모든 브로드 캐스트 된 브롭 (blob)이 단지 한 번만 전달되는 경우가 아니라면, 값 브롭이 전달되지 않습니다. 또한 deliver () 이벤트는 이전 deliver () 이벤트 (prevhash)의 데이터에 대한 암호화 해시를 포함합니다. 순서 서비스가 원자 적 브로드 캐스트(atomic-broadcast) 보장을 구현하면 prevhash는 시퀀스 번호 seqno-1을 사용하는 deliver () 이벤트의 매개 변수를 암호화 해시합니다. 이렇게하면 나중에 섹션 4와 5에서 설명하는대로 주문 서비스 출력의 무결성을 확인하는 데 사용되는 deliver () 이벤트에서 해시 체인을 설정합니다. 첫 번째 deliver () 이벤트의 특별한 경우 prevhash는 기본값을가집니다.
  2. Liveness (배달 보장) : 주문서비스의 배달 보장은 주문서비스 구현에 의해 지정됩니다. 정확한 보증은 네트워크 및 노드 결함 모델에 따라 달라 질 수 있습니다. 원칙적으로 제출 클라이언트가 실해하지 않으면 주문 서비스는 주문서비스에 연결된 모든 피어가 제출된 모든 트랜잭션을 제공하도록 보장해야 합니다.

요약하면 주문 서비스에서는 다음과 같은 속성을 보장 해야 합니다.

  • 협정(Agreement) : 올바른 seagno, prevhash0 == prevhash1 및 blob0 == blob1을 사용하여 올바른 피어에서 전달되는 두 이벤트 (예 : seqno, prevhash0, blob0) 및 deliver (seqno, prevhash1, blob1)
  • Hashchain 무결성(Hashchain integrity) : 올바른 피어에서의 두 이벤트가 (seqno-1, prevhash0, blob0) 및 deliver (seqno, prevhash, blob) 인 경우 prevhash = HASH (seqno-1 || prevhash0 || blob0).
  • No skipping : 주문 서비스가 seqno> 0과 같은 올바른 피어 p에서 deliver (seqno, prevhash, blob)를 출력하면 p는 이미 이벤트 전달을 전달합니다 (seqno-1, prevhash0, blob0).
  • No creation : 올바른 피어의 모든 이벤트 전달 (seqno, prevhash, blob) 앞에는 일부 (가능하면 별개의) 피어에서 브로드 캐스트 (blob) 이벤트가 있어야합니다.
  • No duplication (optional, yet desirable) : 2 개의 이벤트 전달 (seqno0, prevhash0, blob) 및 deliver (seqno1, prevhash1, blob ')가 올바른 피어 및 blob == blob'에서 발생하는 두 개의 이벤트 브로드 캐스트 (blob) 및 브로드 캐스트 (blob ')의 경우 seqno0 = = seqno1 및 prevhash0 == prevhash1.
  • Liveness : 올바른 클라이언트가 이벤트 브로드 캐스트 (blob)를 호출하면 모든 올바른 피어는 이벤트 전달 (*, *, blob)을 발행합니다. 여기서 *는 임의의 값을 나타냅니다.

거래 보증의 기본 워크 플로

트랜잭션에 대한 요청 플로우를 개괄적으로 설명합니다.

참고 : 다음 프로토콜 *은 모든 트랜잭션이 결정적이라고 가정 하지 않습니다. 즉, 비 결정적 트랜잭션을 허용합니다.

클리이언트는 트랜잭션을 생성하고 선택한 피어를 승인하는 곳으로 보내게 됩니다.

트랜잭션을 호출하기 위해 클라이언트는 자신이 선택한 피어 투 피어 집합에 PROPOSE 메시지를 보냅니다 지정된 chaincodeID에 대한 승인 피어 세트는 피어를 통해 클라이언트에 제공되며, 이는 인증 계약에서 보증하는 피어 세트를 구성하게 됩니다. 예를 들어, 트랜잭션은 주어진 chaincodeID의 모든 endorsers에게 전송 될 수 있습니다. 즉, 일부 최종 사용자는 오프라인 일 수 있고, 다른 사용자는 반대 할 수 있으며 거래를 승인하지 않을 수도 있습니다. 제출하는 클라이언트는 사용 가능한 endorser를 사용하여 정책 표현식을 만족 시키려고 시도합니다.

다음에서는 먼저 PROPOSE메시지 형식을 자세히 설명한 다음 제출하는 클라이언트와 엔도 서 간의 상호 작용 패턴을 논의합니다.

PROPOSE message format

PROPOSE메시지 포맷은 <PROPOSE,tx,[anchor]> 이며 tx는 필수이고 anchor은 옵셔널한 입력 변수 입니다.

  • tx=<clientID,chaincodeID,txPayload,timestamp,clientSig>
    • clientID는 제출 클라이언트의 ID
    • chaincodeID는 트랜잭션이 속한(발생시키는) 체인코드 ID
    • txPayload : 제출된 트랜잭션을 포함하는 페이로드
    • timestamp : 모든 새로운 트랜잭션마가 가지는 단순하게 증가하는 정수
    • clientSig : tx의 다른 필드에 있는 클라이언트의 서명 txPayload의 세부 사항은 호출 트랜잭션과 배치 트랜잭션 (즉, 배치 특정 시스템 체인 코드를 참조하는 트랜잭션 호출) 사이에서 달라집니다. invoke 트랜잭션의 경우 txPayload는 두 개의 필드로 구성됩니다.
    • txPayload = <operation, metadata>
      • operation은 체인 코드 연산 (함수)과 인수를 나타내며,
      • 메타 데이터(metadata)는 호출과 관련된 속성을 나타냅니다. 배포 트랜잭션의 경우 txPayload는 세 개의 필드로 구성됩니다.
    • txPayload = <source, metadata, policies>
      • source는 체인 코드의 소스 코드를 나타내며
      • 메타 데이터(metadata)는 체인 코드 및 애플리케이션과 관련된 속성을 나타내며,
      • 정책(policies)에는 보증 정책과 같이 모든 피어가 액세스 할 수있는 체인 코드와 관련된 정책이 포함됩니다. 배포 트랜잭션에는 보증 정책이 txPayload와 함께 제공되지 않지만 배포의 txPayload에는 보증 정책 ID와 해당 매개 변수가 포함됩니다.
  • 앵커(anchor)는 KVS의 지정된 버전의 키에 대해 PROPOSE 요청을 바인딩하거나 "앵커"하는 키 버전 쌍 (즉, 앵커는 KxN의 하위 집합)을 포함합니다. 클라이언트가 앵커 인수를 지정한 경우 endorser는 로컬 앵커의 KVS에있는 해당 키의 읽기 버전 번호에서만 트랜잭션을 승인합니다 .

tx의 암호화 해시는 모든 노드에서 고유 한 트랜잭션 식별자 tid (즉, tid = HASH (tx))로 사용됩니다. 클라이언트는 메모리에 tid를 저장하고 피어를 승인하는 응답을 기다립니다.

Message patterns

고객은 endorser와의 상호 작용의 순서를 결정합니다. 예를 들어 클라이언트는 전형적으로 앵커 인자없이 <PROPOSE, tx>를 하나의 endorser에게 보내면, 나중에 클라이언트가 PROPOSE 메시지의 인자로 사용할 수있는 버전 의존성 (anchor)을 생성하게됩니다. 다른 endorsers. 또 다른 예로, 클라이언트는 자신이 선택한 모든 endorsers에 직접 <PROPOSE, tx> (앵커 없음)를 보낼 수 있습니다. 서로 다른 의사 소통 패턴이 가능하며 고객은 자유롭게 결정할 수 있습니다.

피어는 거래를 시뮬레이션 하고 보증의 서명을 생성합니다.

endorser피어 epID는 클라이언트로부터 <PROPOSE, tx, [anchor]> 메시지를 받으면 먼저 클라이언트의 서명인 clientSig를 확인한 다음 트랜잭션을 시뮬레이트합니다. 클라이언트가 앵커를 특정하면, 엔도 싱 피어는 로컬 KVS 내의 대응하는 키의 판독 버전 번호 (즉, 아래에 정의 된 바와 같은 판독 세트)가 앵커에 의해 지정된 버전 번호와 일치 할 때만 트랜잭션을 시뮬레이트한다.

트랜잭션 시뮬레이션은 트랜잭션이 참조하는 체인 코드 (chaincodeID)를 호출하고 승인하는 피어가 로컬로 보유하고있는 상태의 복사본을 호출하여 피어를 임시로 실행 (txPayload)하는 것을 보증합니다.

실행의 결과로, 승인하는 피어는 DB 언어로 MVCC + postimage 정보라고도하는 읽기 버전 종속성 (readset) 및 상태 업데이트 (writeset)를 계산합니다.

상태는 키 - 값 쌍으로 구성됩니다. 모든 키 - 값 엔트리는 버전 관리됩니다. 즉, 모든 항목에는 키 아래에 저장된 값이 업데이트 될 때마다 증가하는 순서화 된 버전 정보가 들어 있습니다. 트랜잭션을 해석하는 피어는 읽기 또는 쓰기를 위해 체인 코드에 의해 액세스 된 모든 키 - 값 쌍을 기록하지만 피어는 해당 상태를 아직 업데이트하지 않습니다.

  • 보증하는 피어가 트랜잭션을 실행하기 전에 상태가 주어지면 트랜잭션이 읽는 모든 키 k에 대해 pair (k, s (k) .version)가 readset에 추가됩니다.
  • 또한 트랜잭션에 의해 새로운 값 v '로 수정 된 모든 키 k에 대해 pair (k, v')가 쓰기 세트에 추가됩니다. 또는 v '는 이전 값 (s (k) .value)에 대한 새 값의 델타가 될 수 있습니다.

클라이언트가 PROPOSE 메시지에서 앵커를 지정하면 클라이언트 지정 앵커는 트랜잭션을 시뮬레이션 할 때 피어를 승인하여 생성 된 readset과 같아야합니다.

그런 다음 피어는 트랜잭션을 승인하는 피어의 로직 (승인 논리라고 함)으로 내부적으로 제안 (및 가능하면 tx)을 전달합니다. 기본적으로 피어의 논리를 승인하면 트랜잭션 제안을 받아들이고 간단히 트랜잭션 제안에 서명합니다. 그러나, 승인 논리는 임의의 기능을 해석하여 예를 들어 트랜잭션- 제안 및 레거시 시스템과 상호 작용하여 트랜잭션을 보증할지 여부에 대한 결정에 도달하는 입력으로 사용할 수있다.

승인 로직이 트랜잭션을 승인하기로 결정하면 <TRANSACTION-ENDORSED, tid, tran-proposal, epSig> 메시지를 제출 클라이언트 (tx.clientID)로 전송합니다.

  • 여기서 txContentBlob는 체인 코드 / 거래 관련 정보입니다. txContentBlob를 tx의 일부 표현으로 사용하는 것입니다 (예 : txContentBlob = tx.txPayload).
  • epSig는 tran-proposal에서 승인하는 피어의 서명입니다.

그렇지 않으면, 보증 논리가 거래를 승인하는 것을 거부하는 경우, 보증인은 제출 클라이언트에게 메시지 (TRANSACTION-INVALID, tid, REJECTED)를 보낼 수 있습니다.

endorser가 이 단계에서 상태를 변경하지 않는다는 것에 주의 하십시오. 승인 컨텍스트에서 트랜잭션 시뮬레이션에 의해 생성된 업데이트는 상태에 영향을 미치지 않습니다.

제출 클라이언트는 트랜잭션에 대한 보증을 수집하고 주문 서비스를 통해 브로드 캐스트 합니다.

제출 클라이언트는 "충분한"메시지와 서명 (TRANSACTION-ENDORSED, tid, *, *)을 수신 할 때까지 기다렸다가 거래 제안서가 승인되었다고 결론을 내립니다. 논의 된 바와 같이, 이것은 하나 이상의 endorsers와의 상호 작용의 왕복 여행을 포함 할 수 있습니다.

"충분 함"의 정확한 수는 chaincode 보증 정책에 따라 다릅니다. 보증 정책이 충족되면 거래가 승인되는 것이고 아직 커밋되지 않았다는 것에 유의하십시오. 트랜잭션이 승인되었다는 것을 보증하는 peer로부터 서명 된 TRANSACTION-ENDORSED 메시지의 모음을 승인 (endorsement)이라고하며 보증으로 표시합니다.

제출 클라이언트가 거래 제안서에 대한 보증을 수집하지 못하면 나중에 재시도 할 수 있는 옵션을 사용하여 트랜잭션을 포기하게 됩니다.

유효한 보증서가있는 거래의 경우 이제 주문 서비스를 사용하기 시작합니다. 제출 클라이언트는 blob = endorsement 인 브로드 캐스트 (blob)를 사용하여 주문 서비스를 호출합니다. 클라이언트가 직접 주문 서비스를 호출 할 능력이없는 경우, 클라이언트는 자신이 선택한 피어를 통해 브로드 캐스트를 프록시 할 수 있습니다. 그러한 피어는 보증인으로부터 어떠한 메시지도 제거하지 않도록 클라이언트에 의해 신뢰되어야하며 그렇지 않으면 거래가 무효로 간주 될 수 있습니다. 그러나 프록시 피어는 유효한 보증을 만들지 못할 수 있습니다.

주문서비스는 peer에게 트랜잭션을 전달합니다.

이벤트 전달 (seqno, prevhash, blob)이 발생하고 피어가 시퀀스 번호가 seqno보다 낮은 blob에 대한 모든 상태 업데이트를 적용하면 피어는 다음을 수행합니다.

  • blob.endorsement가 참조하는 chaincode (blob.tran-proposal.chaincodeID)의 정책에 따라 blob.endorsement가 유효한지 확인합니다.
  • 일반적인 경우에는 종속성 (blob.endorsement.tran-proposal.readset)도 위반하지 않았다는 것을 확인합니다. 보다 복잡한 유스 케이스에서는 보증서의 트란 - 제안 필드가 다를 수 있으며이 경우 보증 정책은 상태의 변화 방식을 지정합니다.

종속성 확인은 상태 업데이트에 대해 선택되는 일관성 속성 또는 "격리 보증"에 따라 다양한 방법으로 구현 될 수 있습니다. 연쇄 코드 보증 정책이 다른 연쇄 보증 정책을 지정하지 않는 한 연속성은 기본 격리 보증입니다. readset의 모든 키와 관련된 버전을 해당 상태의 키 버전과 같게 요구하고 이 요구 사항을 충족시키지 않는 트랜잭션을 거부함으로써 직렬화 기능을 제공 할 수 있습니다.

  • 이러한 모든 검사가 통과되면 트랜잭션은 유효하거나 완료된 것으로 간주됩니다. 이 경우 피어는 PeerLedger의 비트 마스크에서 트랜잭션을 1로 표시하고 blob.endorsement.tran-proposal.writeset을 블록 체인 상태에 적용합니다
  • blob.endorsement의 보증 정책 확인이 실패하면 트랜잭션은 유효하지 않으며 피어는 PeerLedger의 비트 마스크에서 트랜잭션을 0으로 표시합니다. 유효하지 않은 트랜잭션으로 인해 상태가 변경되지는 않는 것입니다.

주어진 시퀀스 번호로 배달 이벤트 (블록)를 처리 한 후 모든 (올바른) 피어가 동일한 상태를 유지하기에 충분하다는 점에 유의하십시오. 즉, 주문 서비스의 보증에 의해, 모든 올바른 피어는 동일한 전달 순서 (seqno, prevhash, blob)로 이벤트를 수신합니다. 보증 정책의 평가와 readset의 버전 종속성 평가가 결정적이기 때문에 올바른 모든 피어는 BLOB에 포함 된 트랜잭션이 유효한지 동일한 결론에 도달하게됩니다. 따라서 모든 피어는 동일한 순서의 트랜잭션을 커밋하고 적용하며 같은 방식으로 상태를 업데이트합니다.


추천정책

보증 정책 요소

보증 정책은 트랜잭션을 보증하는 조건입니다. 블록 체인 피어는 특정 체인 코드를 설치하는 배포 트랜잭션에 의해 참조되는 사전 지정된 일련의 보증 정책을 가지고 있습니다. 보증 정책을 매개 변수화 할 수 있으며 이러한 매개 변수는 배포 트랜잭션에 의해 지정 될 수 있습니다.

블록 체인 및 보안 속성을 보장하기 위해 보증 정책 집합은 한정된 실행 시간 (종료), 결정론, 성능 및 보안 보장을 보장하기 위해 제한된 기능 세트로 입증 된 정책 집합이어야합니다.

승인 정책의 동적 추가는 제한적 정책 평가 시간 (종료), 결정론, 성능 및 보안 보장 측면에서 매우 민감합니다. 따라서 승인 정책의 동적 추가는 허용되지 않지만 향후 지원 될 수 있습니다.(예 : 체인 코드 배포 시간에 배포 트랜잭션을 통한)

보증 정책에 대한 트랜잭션 평가

트랜잭션은 정책에 따라 승인 된 경우에만 유효한 것으로 선언됩니다. 체인 코드에 대한 호출 (invoke) 트랜잭션은 먼저 체인 코드의 정책을 만족시키는 보증 을 획득해야하며 그렇지 않으면 커밋되지 않습니다. 이것은 제출 클라이언트와 승인하는 동료 간의 상호 작용을 통해 발생합니다.

공식적으로 보증 정책은 보증에 대한 내용이며, TRUE 또는 FALSE로 평가 될 가능성이있는 추가 상태 일 수 있습니다. 배포 트랜잭션의 경우 시스템 전반의 정책 (예 : 시스템 체인 코드)에 따라 보증을받습니다.

보증 정책 에 입각한 특정 변수를 나타냅니다. 잠재적으로 다음을 참조 할 수 있습니다.

  1. 체인 코드의 메타 데이터에있는 체인 코드와 관련된 키 또는 ID
  2. 체인 코드의 추가 메타 데이터
  3. endorsement, endorsement.tran-proposa 구성요소
  4. 잠재적으로 더 많은 것들

위의 목록은 표현력과 복잡성이 증가함에 따라 정렬됩니다. 즉, 노드의 키와 ID만을 참조하는 정책을 지원하는 것이 비교적 간단합니다.

보증 정책 내용의 평가는 결정 론적이어야합니다. endorsement는 모든 피어로 평가되어야 하고 다른 동료들과 상호 작용해야 하며 같은 방법으로 승인 정책을 평가 해야 합니다.

보증정책의 예

보증정책의 내용은 논리 표현식을 포함 할 수 있으며 TRUE 또는 FALSE로 평가됩니다. 일반적으로 조건은 체인 코드에 대해 피어를 보증함으로써 발행 된 트랜잭션 호출에서 디지털 서명을 사용합니다.

체인 코드가 endorser  집합 E = {Alice, Bob, Charlie, Dave, Eve, Frank, George}를 지정한다고 가정합니다.

  • E의 모든 구성원의 동일한 tran-proposal에있는 유효한 서명.
  • E의 단일 회원으로부터 유효한 서명
  • 조건 (Alice OR Bob) AND (Charlie, Dave, Eve, Frank, George 중 둘 중 하나)에 따라 동료를 승인하는 것과 동일한 tran-proposal에 유효한 서명.
  • 7 명의 endorsers 중 5 명이 동일한 tran-proposal에서 유효한 서명. (보다 일반적으로, n> 3f endorsers의 chaincode, n endorsers 중 2f + 1에 의한 유효한 서명 또는 (n + f) / 2 endorsers 이상의 그룹에 의한 유효한 서명)
  • {Alice = 49, Bob = 15, Charlie = 15, Dave = 10, Eve = 7, Frank = 3, George = 1}과 같이 endorsers에 "stake"또는 "weights" 총 지분은 100입니다 : 정책은 {Alice, X}와 George와 다른 X가있는 지분의 대부분 (즉, 스테이크가 결합 된 그룹)이 유효한 세트의 유효한 서명이 필요합니다. 앨리스를 제외한 모두 함께}.
  • 앞의 예제 조건에서 스테이크의 할당은 정적 (체인 코드의 메타 데이터에 고정) 또는 동적 (예 : 체인 코드의 상태에 따라 다르며 실행 중에 수정 될 수 있음) 일 수 있습니다.
  • tran-proposal1의 (Alice or Bob)에서 유효한 서명과 tran-proposal2의 Charlie, Dave, Eve, Frank, George 중 어느 하나의 유효한 서명. 여기서 tran-proposal1과 tran-proposal2는 승인하는 동료에서만 서로 다릅니다.

이러한 정책이 얼마나 유용한지는 응용 프로그램, endorsers의 실패 또는 오작동 및 다양한 기타 속성에 대한 솔루션의 원하는 복원력에 따라 달라집니다.

검증된 원장 및 PeerLedger 체크포인트

검증된 원장(VLedger)

유효하고 커밋된 트랜잭션을 포함하는 원장의 추상화를 위해 peer는 주 원장 이외에도 유효 원장을 유지 관리 할수 있습니다. 유효하지 않은 트랜잭션을 필터링 하여 원장에서 파생된 해시 체인입니다.

VLedger 블록 (여기서 vBlocks라고 함)의 구성은 다음과 같이 진행됩니다. PeerLedger 블록에는 유효하지 않은 트랜잭션 (즉, 잘못된 보증 또는 잘못된 버전 종속성이있는 트랜잭션)이 포함될 수 있으므로 블록에서 트랜잭션이 vBlock에 추가되기 전에 그러한 트랜잭션이 피어에 의해 필터링됩니다. 모든 피어는 (PeerLedger와 관련된 비트 마스크를 사용하여) 스스로 처리합니다. vBlock은 필터링 된 잘못된 트랜잭션이없는 블록으로 정의됩니다. 이러한 vBlocks은 기본적으로 크기면에서 동적이며 비어있을 수 있습니다. vBlock 구성에 대한 그림은 아래 그림과 같습니다.




vBlock은 모든 피어에 의해 해시 체인에 연결됩니다. 보다 구체적으로, 검증 된 원장의 모든 블록에는 다음이 포함됩니다.

  • 이전 vBlock의 해시값
  • vBlock 번호
  • 마지막 vBlock이 계산 된 이후에 피어가 커밋 한 모든 유효한 트랜잭션 (즉, 해당 블록의 유효한 트랜잭션 목록)의 정렬 된 목록
  • 현재 vBlock이 파생되는 블록의 해시값

이 모든 정보는 피어에 의해 연결되고 해시되어 유효성 검사기에서 vBlock의 해시를 생성합니다.

PeerLedger 체크포인팅

원장에 유효하지 않은 트랜잭션이 포함되어있어 영원히 기록되지 않을 수도 있습니다. 그러나 PeerLedger 블록을 폐기 한 후에 PeerLedger를 삭제하면 해당되는 vBlock을 만들 수 없습니다. 즉,이 경우 새 피어가 네트워크에 조인하면 다른 피어가 PeerLedger와 관련된 버려진 블록을 참여 피어로 전송할 수 없으며 참가 피어에게 해당 vBlock의 유효성을 알리지 못합니다.

PeerLedger의 제거 (pruning)를 용이하게하기 위해 이 문서는 검사점 메커니즘을 설명합니다. 이 메커니즘은 피어 네트워크에서 vBlock의 유효성을 확인하고 체크 포인트 된 vBlock이 폐기 된 PeerLedger 블록을 대체 할 수있게합니다. 이렇게하면 유효하지 않은 트랜잭션을 저장할 필요가 없으므로 저장 공간이 줄어 듭니다. 또한 PeerLedger를 재생하여 상태를 재구성 할 때 개별 트랜잭션의 유효성을 확인할 필요가 없으므로 유효성을 검사 한 원장에 포함 된 상태 업데이트를 재생할 수 있으므로 네트워크에 가입 한 새 피어의 상태를 재구성하는 작업이 줄어 듭니다.

Checkpointing protocol

검사 점 지정은 CHK 블록마다 피어에 의해 주기적으로 수행되며 CHK는 구성 가능한 매개 변수입니다. 검사 점을 초기화하기 위해 피어는 다른 피어에게 <CHECKPOINT, blocknohash, blockn, stateHash, peerSig> 메시지를 브로드 캐스트합니다. 여기서 blockno는 현재 블록 번호이고 blocknohash는 해당 해시이고 stateHash는 최신 상태의 해시입니다 (예를 들어, Merkle 해시에 의해 생성 된) blockPNO의 유효성을 검사하고 peerSig는 (CHECKPOINT, blocknohash, blockno, stateHash)에 대한 피어의 서명이며, 확인 된 원장을 참조합니다.

피어는 유효한 checkpoint를 설정하기 위해 blockno, blocknohash 및 stateHash가 일치하는 서명 된 메시지를 충분히 얻을 때까지 CHECKPOINT 메시지를 수집합니다

blocknohash를 사용하여 블록 번호 blockno에 대한 유효한 검사 점을 설정하면 피어가 다음을 수행합니다.

  • blockno> latestValidCheckpoint.blockno이면 피어가 latestValidCheckpoint = (blocknohash, blockno)를 지정합니다.
  • 유효한 체크 포인트를 구성하는 각각의 피어 서명들의 세트를 세트의 latestValidCheckpointProof
  • stateHash에 해당하는 상태를 latestValidCheckpointedState에 저장합니다.
  • (선택 사항) 블록 번호 blockno (포함)까지 PeerLedger를 제거합니다.

Valid checkpoints

명확하게, 체크 포인트 프로토콜은 다음과 같은 질문을 제기합니다 . 피어가 언제 "PeerLedger"를자를 수 있습니까? 얼마나 많은``CHECKPOINT`` 메시지가``충분히 많습니까? . 이것은 검사 점 유효성 정책에 의해 정의되며, 두 가지 가능한 접근법이 결합되어 있습니다.

  • 로컬 (피어 전용) 검사 점 유효성 정책 (LCVP). 주어진 피어 p의 로컬 정책은 피어 P 트러스트와 그의 CHECKPOINT 메시지가 유효한 체크 포인트를 설정하기에 충분한 피어 세트를 지정할 수있다. 예를 들어, 피어 앨리스의 LCVP는 앨리스가 밥 또는 찰리와 데이브 모두로부터 CHECKPOINT 메시지를 수신해야한다고 정의 할 수 있습니다.
  • 글로벌 체크 포인트 유효성 정책 (GCVP). 체크 포인트 유효성 정책은 전 세계적으로 지정 될 수 있습니다. 이는 로컬 피어 정책과 유사하지만 피어 세분성보다는 시스템 (블록 체인) 세밀도에서 규정된다는 점만 다릅니다. 예를 들어, GCVP는 다음을 지정할 수 있습니다.
    • 11 명의 서로 다른 동료 가 확인한 경우 각 피어는 체크 포인트를 신뢰할 수 있습니다 .
    • 모든 발주자가 동일한 시스템 (즉, 신뢰 도메인)의 피어와 함께 배치되고 f 명의 발주자가 (비잔틴) 오류가있을 수 있는 특정 배포에서는 f + 1 명의 다른 피어에 의해 확인 된 경우 각 피어가 체크 포인트를 신뢰할 수 있습니다.

Transaction Flow

이 문서는 표준 자산 교환 중에 발생하는 트랜잭션 메커니즘에 대해 설명합니다. 시나리오에는 무를 사고 파는 두 명의 고객 A와 B가 포함됩니다. 이들은 각각 네트워크를 통해 거래를 보내고 원장과 상호 작용하는 동료를가집니다.



Assumptions(가정)

이 플로우는 채널이 설정되어 실행 중이라고 가정합니다. 응용 프로그램 사용자는 조직의 인증 기관 (CA)을 등록 및 등록하고 네트워크 인증에 필요한 필수 암호화 자료를 다시 수신합니다.

무 코드 시장의 초기 상태를 나타내는 일련의 키 값 쌍을 포함하는 체인 코드가 피어에 설치되고 채널에 인스턴스화됩니다. 체인 코드는 일련의 거래 지시 사항과 무에 대해 합의 된 가격을 정의하는 로직을 포함합니다. 이 체인 코드에 대한 보증 정책이 설정되어있어 peerA와 peerB가 트랜잭션을 보증해야한다는 것을 나타냅니다.

1. 클라이언트 A, 트랜잭션 시작

무슨 일이야? - 고객 A가 무를 구입하라는 요청을 보냈습니다. 요청은 각각 클라이언트 A와 클라이언트 B를 대표하는 peerApeerB를 대상으로합니다. 보증 정책은 두 피어가 모든 트랜잭션을 보증해야한다는 것을 나타내므로 요청은 peerApeerB로 이동합니다. 다음으로 거래 제안이 구성됩니다. 지원되는 SDK (노드, 자바, 파이썬)를 활용하는 애플리케이션은 트랜잭션 제안서를 생성하는 사용 가능한 API 중 하나를 사용합니다. 제안은 체인 코드 기능을 호출하여 데이터를 판독기에 쓰거나 쓰기 (즉, 자산에 대한 새로운 키 값 쌍 작성) 할 수 있도록하는 요청입니다. SDK는 트랜잭션 제안서를 적절하게 설계된 형식 (gRPC를 통한 프로토콜 버퍼)으로 패키지화하기위한 shim 역할을하며 사용자의 암호화 자격 증명을 사용하여이 트랜잭션 제안서의 고유한 서명을 생성합니다.



2. 피어를 인증하고 트랜잭션을 실행하는 것을 보증하는 피어

(1) 거래 제안서가 잘 형성되었는지

(2) 과거에 제출되지 않았는지 (재생 공격 보호)

(3) 서명이 유효한지 (MSP 사용)

(4) 제출자 (예 : 클라이언트 A)가 해당 채널에서 제안 된 작업을 수행 할 수 있도록 적절한 권한을 부여 받았음을 나타냅니다. (즉, 각 인증 피어는 제출자가 채널의 작성자 정책을 충족하는지 확인합니다)

{MSP는 클라이언트에서 도착한 거래 요청을 확인하고 거래 결과 (보증)에 서명 할 수있는 피어 구성 요소입니다. * 쓰기 정책은 채널 생성시 정의되며 해당 채널에 트랜잭션을 제출할 수있는 사용자를 결정합니다.} *



3. 제안 응답 검사

응용 프로그램은 승인 피어 서명을 확인하고 제안 응답 (페이로드 표현을 포함 할 용어 용어에 대한 링크)을 비교하여 제안 응답이 동일하고 지정된 보증 정책이 충족되었는지 확인합니다 (예 : peerA 및 peerB 양측지지). 응용 프로그램이 응답을 조사하지 않거나 다른 방법으로 전달되지 않은 트랜잭션을 전달하는 경우에도 정책은 여전히 ​​동료와 시행 확인 단계에서 유지됩니다.



4. 클라이언트가 보증을 트랜잭션으로 어셈블

응용 프로그램은 거래 제안서와 응답을 "거래 메시지"내에서 주문 서비스로 "방송"합니다. 트랜잭션에는 읽기 / 쓰기 세트, 승인 피어 서명 및 채널 ID가 포함됩니다. Ordering Service는 트랜잭션을 수행하기 위해 트랜잭션의 전체 내용을 검사 할 필요가 없으며 네트워크의 모든 채널에서 트랜잭션을 수신하고 채널별로 시간순으로 순서를 지정하며 채널당 트랜잭션 블록을 생성합니다.



5. 거래가 확인되고 commit 됨

거래 블록은 채널의 모든 피어에게 전달됩니다. 블록 내의 트랜잭션은 보증 정책이 충족되고 트랜잭션 집합에 의해 읽기 집합이 생성 되었기 때문에 읽기 집합 변수에 대한 원장 상태가 변경되지 않았는지 확인하기 위해 유효성이 검사됩니다. 블록의 트랜잭션은 유효하거나 유효하지 않은 것으로 태그가 지정됩니다.



6. 원장 업데이트

각 피어는 블록을 채널의 체인에 추가하고 유효한 트랜잭션마다 쓰기 세트가 현재 상태 데이터베이스에 커밋됩니다. 클라이언트 응용 프로그램에 트랜잭션 (호출)이 체인에 영구적으로 추가되었음을 알리고 트랜잭션의 유효성을 검사했는지 유효하지 않은지 여부를 알리는 이벤트가 생성됩니다.

Hyperledger Fabric CA User Guide

Hyperledger Fabric SDKs

Hyperledger Fabric은 다양한 프로그래밍 언어에 대해 다양한 SDK를 제공 할 예정입니다. 처음 두 가지는 Node.js와 Java SDK입니다. 후속 릴리스에서 Python, REST 및 Go SDK를 제공하기를 바랍니다.

Hyperledger Fabric Node SDK 문서.
Hyperledger Fabric Java SDK 설명서.

Channels

Hyperledger 패브릭 채널은 비공개 및 기밀 트랜잭션을 수행하기 위해 두 명 이상의 특정 네트워크 구성원 간의 통신에 대한 개인 "서브넷"입니다. 채널은 구성원 (조직), 구성원 당 앵커 피어, 공유 원장, 체인 코드 응용 프로그램 및 주문 서비스 노드 (들)에 의해 정의됩니다. 네트워크상의 각 트랜잭션은 채널에서 실행되며 각 당사자는 인증되고 해당 채널에서 거래할 권한이 있어야합니다. 채널에 참여하는 각 피어는 구성원 서비스 공급자 (MSP)가 제공한 자체 ID를 가지며 채널 피어 및 서비스에 대한 각 피어를 인증합니다.

새 채널을 만들려면 클라이언트 SDK가 구성 시스템 체인 코드를 호출하고 앵커 피어** 및 구성원 (조직)과 같은 속성을 참조합니다. 이 요청은 채널 정책, 구성원 및 앵커 피어에 대한 구성 정보를 저장하는 채널 원장에 대한 **기원 블록(genesis block)을 만듭니다. 기존 채널에 새 구성원을 추가 할 때 이 기원 블록 또는 적용 가능한 경우 최신 재구성 블록이 새 구성원과 공유됩니다.

채널의 각 구성원에 대한 선임 피어(leading peer)가 선출되면 피어가 구성원을 대신하여 주문 서비스(ordering service)와 통신하는지 결정합니다. 리더가 식별되지 않으면 알고리즘을 사용하여 리더를 식별 할 수 있습니다. 컨센서스 서비스는 거래를 명령하고 이를 각 피어(peer)에게 전달하며, 피어는 피어 투 피어(peer)와 가십 프로토콜을 사용하여 채널을 통해 피어 투 피어에게 배포합니다.

하나의 앵커 피어가 여러 채널에 속할 수 있기 때문에 여러 원장을 유지할 수 있지만 원장 데이터는 한 채널에서 다른 채널로 전달할 수 없습니다. 이 원장 분리는 채널별로 구성 체인 코드, ID 멤버십 서비스 및 가십 데이터 보급 프로토콜에 의해 정의되고 구현됩니다. 장부 원장 및 채널 멤버십에 대한 정보가 포함된 데이터의 보급은 해당 채널의 회원 자격이 검증된 동료에게만 국한됩니다. 피어 및 원장 데이터를 채널별로 분리하면 사설 및 기밀 트랜잭션이 필요한 네트워크 구성원이 비즈니스 경쟁자 및 다른 제한된 회원과 동일한 블록 체인 네트워크에서 공존할 수 있습니다.

Capability Requirements

Fabric은 대개 여러 국가 또는 대륙에있는 여러 조직을 포함하는 분산 시스템이기 때문에 여러 다른 버전의 Fabric 코드가 네트워크에 존재할 수 있습니다 (일반적으로). 그럼에도 불구하고 네트워크가 트랜잭션을 동일한 방식으로 처리하여 모든 사람이 현재 네트워크 상태에 대해 동일한 시각을 갖도록하는 것이 중요합니다.

즉, 모든 네트워크와 네트워크 내의 모든 채널은 처리 트랜잭션에 참여할 수 있도록 "기능"이라고하는 집합을 정의해야합니다. 예를 들어, Fabric v1.1은 "피어"와 "클라이언트"의 새로운 MSP 역할 유형을 소개합니다. 그러나 v1.0 피어가 이러한 새로운 역할 유형을 이해하지 못하면 해당 역할 유형을 참조하는 보증 정책을 적절히 평가할 수 없습니다. 즉, 새 역할 유형을 사용하기 전에 네트워크가 v1.1 채널 기능 요구 사항을 사용하도록 동의해야 모든 피어가 동일한 결정을 내릴 수 있습니다.

필요한 기능을 지원하는 바이너리만 채널에 참여할 수 있으며 최신 바이너리 버전에서는 해당 기능을 사용할 수있을 때까지 새로운 유효성 검사 논리를 사용할 수 없습니다. 이런 식으로 기능 요구 사항은 서로 다른 빌드와 버전이 있더라도 네트워크가 상태를 포착 할 수 없음을 보장합니다.

기능 요구 사항 정의

기능 요구 사항은 채널 구성 (채널의 가장 최근 구성 블록에 있음)에서 채널별로 정의됩니다. 채널 구성에는 세 가지 위치가 있으며 각 위치는 다른 유형의 기능을 정의합니다.

Capability Type Canonical Path JSON Path
Channel /Channel/Capabilities .channel_group.values.Capabilities
Orderer /Channel/Orderer/Capabilities .channel_group.groups.Orderer.values.Capabilities
Application /Channel/Application/Capabilities .channel_group.groups.Application.values. Capabilities
  • 채널 :이 기능은 피어 및 주문자 모두에게 적용되며 루트 채널 그룹에 있습니다.
  • 주문자: 주문자에게만 적용되며 주문자그룹에 있습니다.
  • 응용 프로그램 : 피어에만 적용되며 응용 프로그램 그룹에 있습니다.

기능은 기존 관리 구조와 일치시키기 위해 이러한 그룹으로 분류됩니다. 주문자 기능을 업데이트하는 것은 주문 조직이 응용 프로그램 조직과 독립적으로 관리하는 것입니다. 마찬가지로 응용 프로그램 기능을 업데이트하는 것은 응용 프로그램 관리자 만 관리 할 수있는 것입니다. "Orderer"와 "Application"사이의 기능을 분리함으로써 가상의 네트워크는 v1.6 피어 어플리케이션 네트워크를 지원하면서 v1.6 주문 서비스를 실행할 수 있습니다.

그러나 일부 기능은 'Application'및 'Orderer'그룹을 교차합니다. 이전에 보았 듯이 새로운 MSP 역할 유형을 추가하는 것은 주문자 및 응용 프로그램 관리자가 모두 동의하고 인식해야하는 것입니다. 주문자는 거래가 주문서를 통과 할 수 있도록하기 위해 MSP 역할의 의미를 이해해야하며 동료는 트랜잭션을 확인하기 위해 역할을 이해해야합니다. 이러한 종류의 기능 (응용 프로그램과 주문자 구성 요소 모두에 걸쳐 있음)은 최상위 "채널"그룹에 정의됩니다.

주문자 및 응용 프로그램 기능이 버전 1.1 및 v1.4에 각각 정의되어있는 동안 채널 기능은 버전 v1.3에 정의 될 수 있습니다. "채널"그룹 수준에서 기능을 사용한다고해서 더 구체적인 "주문자"및 "응용 프로그램"그룹 수준에서이 동일한 기능을 사용할 수 있음을 의미하지는 않습니다.

기능 설정

기능은 채널 구성의 일부로 설정됩니다 (초기 구성의 일부로 - 잠시 후에 - 또는 재구성의 일부로).

채널 재구성의 다양한 측면을 통해 이야기하는 두 개의 문서가 있습니다. 먼저 채널에 조직 추가 프로세스를 안내하는 자습서가 있습니다 . 또한 채널 구성 업데이트를 통해 가능한 다양한 종류의 업데이트에 대한 개요와 서명 프로세스에 대한 전체적인 내용을 제공하는 문서도 있습니다 .

새 채널은 기본적으로 주문자 시스템 채널의 구성을 복사하므로 주문자 시스템 채널의 주문자 및 채널 기능 및 채널 생성 트랜잭션에서 지정한 응용 프로그램 기능을 사용하도록 새 채널이 자동으로 구성됩니다. 그러나 이미 존재하는 채널은 재구성해야합니다.

Capabilities 값의 스키마는 다음과 같이 protobuf에 정의됩니다.

message Capabilities {
      map<string, Capability> capabilities = 1;
}

message Capability { }
{
    "capabilities": {
        "V1_1": {}
    }
}

초기 구성의 기능

릴리스 아티팩트의 config 디렉토리에 분산 된 configtx.yaml 파일에는 기능 유형 (채널, 주문자 및 애플리케이션)에 대해 가능한 기능을 나열하는 기능 섹션이 있습니다.

기능을 활성화하는 가장 간단한 방법은 v1.1 샘플 프로파일을 선택하고 네트워크에 맞게 사용자 정의하는 것입니다. 예 :

SampleSingleMSPSoloV1_1:
    Capabilities:
        <<: *GlobalCapabilities
    Orderer:
        <<: *OrdererDefaults
        Organizations:
            - *SampleOrg
        Capabilities:
            <<: *OrdererCapabilities
    Consortiums:
        SampleConsortium:
            Organizations:
                - *SampleOrg

루트 수준 (채널 기능 용) 및 주문자 수준 (주문자 기능 용)에 정의 된 기능 섹션이 있습니다. 위의 샘플은 YAML 참조를 사용하여 YAML의 맨 아래에 정의 된대로 기능을 포함합니다.

발주자 시스템 채널을 정의 할 때 응용 프로그램 섹션이 없으므로 해당 기능은 응용 프로그램 채널을 만드는 동안 정의됩니다. 채널 생성시 새로운 채널의 응용 프로그램 기능을 정의하려면 응용 프로그램 관리자가 SampleSingleMSPChannelV1_1 프로파일 다음에 채널 생성 트랜잭션을 모델링해야합니다.

SampleSingleMSPChannelV1_1:
     Consortium: SampleConsortium
     Application:
         Organizations:
             - *SampleOrg
         Capabilities:
             <<: *ApplicationCapabilities

여기서 응용 프로그램 섹션에는 YAML 끝에 정의 된 ApplicationCapabilities 섹션을 참조하는 Capabilities라는 새로운 요소가 있습니다.

Channel 및 Orderer 섹션의 기능은 주문 시스템 채널의 정의에서 상속되며 채널 생성 과정에서 주문자가 자동으로 포함합니다.

CouchDB as the State Database

 상태 데이터베이스 옵션

상태 데이터베이스 옵션에는 LevelDB 및 CouchDB가 포함됩니다. LevelDB는 피어 프로세스에 포함 된 기본 키 - 값 상태 데이터베이스입니다. CouchDB는 선택적 외부 상태 데이터베이스입니다. CouchDB는 LevelDB 키 - 값 저장소와 마찬가지로 체인 코드로 모델링 된 모든 이진 데이터를 저장할 수 있습니다 (CouchDB 첨부 기능은 JSON이 아닌 바이너리 데이터에 내부적으로 사용됩니다). 그러나 JSON 문서 저장소 인 CouchDB는 체인 코드 값 (예 : 자산)을 JSON 데이터로 모델링 할 때 체인 코드 데이터에 대한 추가 쿼리를 추가적으로 지원합니다.

LevelDB 및 CouchDB는 키 가져 오기 및 설정 (자산)과 키 기반 쿼리와 같은 핵심 체인 코드 작업을 지원합니다. 키는 범위별로 쿼리 할 수 ​​있으며 복합 키는 여러 매개 변수에 대해 등가 쿼리를 사용할 수 있도록 모델링 할 수 있습니다. 예를 들어 소유자인 asset_id의 복합 키를 사용하여 특정 엔터티가 소유 한 모든 자산을 쿼리 할 수 ​​있습니다. 이러한 키 기반 쿼리는 원장에 대한 읽기 전용 쿼리 및 원장을 업데이트하는 트랜잭션에 사용할 수 있습니다.

자산을 JSON으로 모델링하고 CouchDB를 사용하는 경우 chaincode 내의 CouchDB JSON 쿼리 언어를 사용하여 체인 코드 데이터 값에 대해 복잡한 리치 쿼리를 수행 할 수도 있습니다. 이러한 유형의 쿼리는 원장의 내용을 이해하는 데 탁월합니다. 이러한 유형의 쿼리에 대한 제안 응답은 일반적으로 클라이언트 응용 프로그램에 유용하지만 일반적으로 주문 서비스에 대한 트랜잭션으로 제출되지는 않습니다. 실제로 체인 코드 실행과 풍부한 쿼리에 대한 커밋 시간 사이에 결과 집합이 안정적이라는 보장이 없으므로 응용 프로그램이 결과 집합이 체인 코드 실행 시간과 안정성 사이에서 안정적임을 보장 할 수없는 경우 리치 쿼리가 업데이트 트랜잭션에 사용하기에 적합하지 않습니다. 커밋 시간, 또는 후속 트랜잭션의 잠재적 변경을 처리 할 수 ​​있습니다. 

예를 들어, CouchDB는 피어와 함께 별도의 데이터베이스 프로세스로 실행되므로 설정, 관리 및 작업과 관련하여 추가 고려 사항이 있습니다. 기본 임베디드 LevelDB로 시작하는 것을 고려해 볼 수 있으며 추가로 복잡한 리치 쿼리가 필요한 경우 CouchDB로 이동하십시오. 체인 코드 자산 데이터를 JSON으로 모델링하는 것이 좋습니다. 그러면 나중에 필요할 경우 복잡한 리치 쿼리를 수행 할 수 있습니다.

JSON 문서는 최상위 레벨에서 다음 필드 이름을 사용할 수 없습니다. 내부 용으로 예약되어 있습니다.
  • _deleted
  • _id
  • _rev
  • ~version

Chaincode에서 CouchDB 사용

대부분의 체인 코드 shim API는 LevelDB 또는 CouchDB 상태 데이터베이스와 함께 사용할 수 있습니다. GetState, PutState, GetStateByRange, GetStateByPartialCompositeKey입니다. 또한 CouchDB를 상태 데이터베이스로 활용하고 체인 코드에서 JSON으로 자산을 모델링 할 때 GetQueryResult API를 사용하고 CouchDB 쿼리 문자열을 전달하여 상태 데이터베이스의 JSON에 대해 풍부한 쿼리를 수행 할 수 있습니다. 쿼리 문자열은 CouchDB JSON 쿼리 구문을 따릅니다.

marbles02 패브릭 샘플은 chaincode에서 CouchDB 쿼리를 사용하는 방법을 보여줍니다. 그것은 소유자 ID를 chaincode에 전달하여 매개 변수화 된 쿼리를 보여주는 queryMarblesByOwner () 함수를 포함합니다. 그런 다음 JSON 쿼리 구문을 사용하여 "대리석"의 docType 및 소유자 ID와 일치하는 JSON 문서의 상태 데이터를 쿼리합니다.

{"selector":{"docType":"marble","owner":<OWNER_ID>}}

JSON 쿼리를 효율적으로 만들기 위해서는 CouchDB의 인덱스가 필요하며 정렬 된 모든 JSON 쿼리에 필요합니다. 인덱스는 / META-INF / statedb / couchdb / indexes 디렉토리의 chaincode와 함께 패키지화 할 수 있습니다. 각 색인은 확장자가 * .json 인 자체 텍스트 파일에 정의되어야하며 색인 정의는 CouchDB 색인 JSON 구문에 따라 JSON으로 형식이 지정됩니다. 예를 들어 위의 대리석 쿼리를 지원하기 위해 docType 및 owner 필드에 대한 샘플 인덱스가 제공됩니다.

{"index":{"fields":["docType","owner"]},"ddoc":"indexOwnerDoc", "name":"indexOwner","type":"json"}

체인 코드의 META-INF / statedb / couchdb / indexes 디렉토리에있는 인덱스는 배포용 체인 코드로 패키지됩니다. 체인 코드가 피어에 설치되고 피어의 채널 중 하나에서 인스턴스화되면 피어의 채널 및 체인 코드 특정 상태 데이터베이스 (CouchDB를 사용하도록 구성된 경우)에 인덱스가 자동으로 배포됩니다. 먼저 체인 코드를 설치 한 다음 채널에 체인 코드를 인스턴스화하면 체인 코드 인스턴스화시 색인이 배치됩니다. 체인 코드가 이미 채널에서 인스턴스화 된 경우 나중에 체인 코드를 피어에 설치하면 체인 코드 설치시 색인이 배치됩니다.

배포시 인덱스는 체인 코드 쿼리에 의해 자동으로 활용됩니다. CouchDB는 쿼리에서 사용되는 필드에 따라 사용할 인덱스를 자동으로 결정할 수 있습니다. 또는 selector 쿼리에서 인덱스는 use_index 키워드를 사용하여 지정할 수 있습니다.

동일한 인덱스가 설치되는 체인 코드의 후속 버전에도 존재할 수 있습니다. 색인을 변경하려면 동일한 색인 이름을 사용하지만 색인 정의를 변경하십시오. 설치 / 인스턴스 생성시, 인덱스 정의는 피어의 상태 데이터베이스에 다시 배포됩니다.

많은 양의 데이터가 있고 나중에 체인 코드를 설치하면 설치시 인덱스 생성에 약간의 시간이 걸릴 수 있습니다. 마찬가지로 대량의 데이터가 이미 있고 체인 코드의 후속 버전을 인스턴스화하는 경우 인덱스 생성에 약간의 시간이 걸릴 수 있습니다. 인덱스가 초기화되는 동안 체인 코드 쿼리가 시간 초과 될 수 있으므로이 때 상태 데이터베이스를 쿼리하는 체인 코드 함수를 호출하지 마십시오. 트랜잭션 처리 중에 블록이 원장에게 커밋됨에 따라 인덱스가 자동으로 새로 고쳐집니다.

CouchDB 설정

stateDatabase 구성 옵션을 goleveldb에서 CouchDB로 변경하여 CouchDB를 상태 데이터베이스로 사용할 수 있습니다. 또한 couchDBAddress는 피어가 사용할 CouchDB를 가리 키도록 구성해야합니다. CouchDB가 사용자 이름과 암호로 구성되어 있으면 사용자 이름과 암호 등록 정보에 관리자 사용자 이름과 암호가 입력되어야합니다. 추가 옵션은 couchDBConfig 섹션에 제공되며 문서화되어 있습니다. core.yaml에 대한 변경 사항은 피어를 재시작 한 후 즉시 적용됩니다.

docker 환경 변수를 전달하여 core.yaml 값을 무시할 수도 있습니다 (예 : CORE_LEDGER_STATE_STATEDATABASE 및 CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS)

다음은 core.yaml의 stateDatabase 섹션입니다.

state:
  # stateDatabase - options are "goleveldb", "CouchDB"
  # goleveldb - default state database stored in goleveldb.
  # CouchDB - store state database in CouchDB
  stateDatabase: goleveldb
  couchDBConfig:
     # It is recommended to run CouchDB on the same server as the peer, and
     # not map the CouchDB container port to a server port in docker-compose.
     # Otherwise proper security must be provided on the connection between
     # CouchDB client (on the peer) and server.
     couchDBAddress: couchdb:5984
     # This username must have read and write authority on CouchDB
     username:
     # The password is recommended to pass as an environment variable
     # during start up (e.g. LEDGER_COUCHDBCONFIG_PASSWORD).
     # If it is stored here, the file must be access control protected
     # to prevent unintended users from discovering the password.
     password:
     # Number of retries for CouchDB errors
     maxRetries: 3
     # Number of retries for CouchDB errors during peer startup
     maxRetriesOnStartup: 10
     # CouchDB request timeout (unit: duration, e.g. 20s)
     requestTimeout: 35s
     # Limit on the number of records to return per query
     queryLimit: 10000

Docker에서 호스팅되는 CouchDB Docker로 압축 된 스크립팅 환경 압축 된 스크립팅 환경 변수는 COUCHDB_USER 및 COUCHDB_PASSWORD 환경 변수에 전달됩니다.

Fabric과 함께 제공된 도커 이미지 외부의 CouchDB 설치의 경우 local.ini 파일을 관리자 아이디와 비밀번호로 설정해야합니다.

Docker 작성 스크립트는 컨테이너 작성시 사용자 이름과 암호 만 설정합니다. 컨테이너를 만든 후에 사용자 이름이나 암호를 변경하면 local.ini 파일을 편집해야합니다.

Peer channel-based event services

 개요

이전 버전의 Fabric에서는 피어 이벤트 서비스를 이벤트 허브라고했습니다. 이 서비스는 해당 블록이 속한 채널에 관계없이 새로운 블록이 피어의 원장에 추가 될 때마다 이벤트를 보내고 이벤트 피어를 실행하는 조직의 구성원 (예 : 이벤트에 연결되어있는 구성원만 액세스 할 수있었습니다 ).

v1.1부터는 이벤트를 제공하는 두 가지 새로운 서비스가 있습니다. 이러한 서비스는 완전히 다른 디자인을 사용하여 채널별로 이벤트를 제공합니다. 즉, 이벤트 등록은 피어 대신 채널 수준에서 발생하므로 피어 데이터에 대한 액세스를 세부적으로 제어 할 수 있습니다. 이벤트 수신 요청은 피어 조직 외부의 ID (채널 구성에 의해 정의 됨)로부터 허용됩니다. 또한 연결 안정성 문제 또는 피어가 이미 실행중인 네트워크에 참여했기 때문에 손실 된 이벤트를 수신 할 수있는 뛰어난 안정성과 방법을 제공합니다.

사용 가능한 서비스

  • Deliver

이 서비스는 커미트 된 전체 블록을 원장에게 보냅니다. 체인 코드에 의해 이벤트가 설정되면, 블록의 ChaincodeActionPayload에서 찾을 수 있습니다.

  • DeliverFiltered

이 서비스는 "필터링 된"블록, 장부에 커밋 된 블록에 대한 최소한의 정보 집합을 보냅니다. 동료의 소유자가 외부 클라이언트가 주로 거래 및 거래 상태에 대한 정보를 받기를 원하는 네트워크에서 사용하기위한 것입니다. 체인 코드에 의해 이벤트가 설정되면 필터링 된 블록의 FilteredChaincodeAction에서 찾을 수 있습니다.

이벤트 등록 방법

두 서비스의 이벤트 등록은 전달 시작 정보 메시지가 들어있는 봉투를 원하는 시작 및 정지 위치, 탐색 동작 (준비가되지 않았 으면 실패 또는 준비가되지 않은 경우)까지 포함하는 피어에게 보냄으로써 수행됩니다. 원장에서 가장 오래된 (즉, 첫 번째) 블록 또는 가장 새로운 (즉, 마지막) 블록을 나타내는 데 사용할 수있는 헬퍼 변수 SeekOldest 및 SeekNewest가 있습니다. 서비스가 이벤트를 무기한으로 보내도록하려면 SeekInfo 메시지에 MAXINT64의 중지 위치가 있어야합니다.

상호 TLS가 피어에서 활성화되어 있으면 TLS 인증서 해시를 봉투의 채널 헤더에 설정해야합니다.

기본적으로 두 서비스 모두 채널 판독기 정책을 사용하여 요청 클라이언트에 이벤트를 인증할지 여부를 결정합니다

전달 응답 메시지 개요(Overview of deliver response messages)

이벤트 서비스는 DeliverResponse메시지를 다시 보냅니다.

각 메시지에는 다음 중 하나가 포함됩니다.

  • status - HTTP 상태 코드입니다. 오류가 발생하면 두 서비스 모두 적절한 실패 코드를 반환합니다. 그렇지 않으면 서비스가 완료되면 SeekInfo 메시지에 의해 요청 된 모든 정보를 전송하고 200 - SUCCESS를 반환합니다.
  • block - Deliver 서비스에 의해서만 반환됩니다.
  • 필터링 된 블록 - DeliverFiltered 서비스에 의해서만 반환됩니다.

필터링 된 블록에는 다음이 포함됩니다.

  • 채널 ID.
  • 번호 (즉, 블록 번호).
  • 필터링 된 트랜잭션의 배열.
  • 트랜잭션 ID.
    • type (e.g. ENDORSER_TRANSACTIONCONFIG.)
    • transaction validation code.
  • 필터링 된 트랜잭션 작업.
    • 필터링 된 체인 코드 동작의 배열입니다.
      • 트랜잭션에 대한 chaincode 이벤트 (페이로드가 누락 된 상태).

Read-Write set semantics

 트랜잭션 시뮬레이션 및 읽기 - 쓰기 세트

endorser 에서 트랜잭션을 시뮬레이션하는 동안 트랜잭션에 대해 읽기 - 쓰기 세트가 준비됩니다. 읽기 집합에는 시뮬레이션 중에 트랜잭션이 읽는 고유 키 및 커밋 된 버전의 목록이 포함됩니다. 쓰기 세트에는 고유 키 목록 (읽기 세트에있는 키와 중복 될 수 있음)과 트랜잭션이 작성하는 새 값 목록이 들어 있습니다. 트랜잭션에 의해 수행 된 갱신이 키를 삭제하는 것이면 키의 h 제 표시자가 (새 값 대신에) 설정됩니다.

또한 트랜잭션이 키에 여러 번 값을 쓰는 경우 마지막으로 기록 된 값만 유지됩니다. 또한 트랜잭션이 키에 대한 값을 읽는 경우 트랜잭션이 읽기 전에 해당 값을 갱신하더라도 커밋 된 상태의 값이 반환됩니다. 즉, 읽기 - 쓰 기 의미론은 지원되지 않습니다.

앞서 언급했듯이 키의 버전은 읽기 세트에만 기록됩니다. 쓰기 세트에는 고유 키 목록과 트랜잭션에 의해 설정된 최신 값이 포함됩니다.

버전을 구현하기위한 다양한 계획이있을 수 있습니다. 버전 관리 체계에 대한 최소한의 요구 사항은 주어진 키에 대해 반복되지 않는 식별자를 생성하는 것입니다. 예를 들어, 버전에 대해 단조롭게 증가하는 숫자를 사용하면 이러한 스키마가 될 수 있습니다. 현재 구현에서는 커밋 트랜잭션의 높이가 트랜잭션에 의해 수정 된 모든 키의 최신 버전으로 사용되는 블록 체인 높이 기반 버전 관리 체계를 사용합니다. 이 체계에서 트랜잭션의 높이는 튜플로 표시됩니다 (txNumber는 블록 내의 트랜잭션 높이입니다). 이 계획은 증분 번호 체계보다 많은 장점을 가지고 있습니다. 주로 설계된 선택, 트랜잭션 시뮬레이션 및 유효성 검사와 같은 다른 구성 요소를 사용하여 효율적인 설계를 선택할 수 있습니다.

다음은 가상 트랜잭션의 시뮬레이션으로 준비된 읽기 쓰기 세트의 예입니다. 단순화를 위해 그림에서 버전을 나타내는 데 필요한 증분 숫자를 사용합니다.

<TxReadWriteSet>
  <NsReadWriteSet name="chaincode1">
    <read-set>
      <read key="K1", version="1">
      <read key="K2", version="1">
    </read-set>
    <write-set>
      <write key="K1", value="V1"
      <write key="K3", value="V2"
      <write key="K4", isDelete="true"
    </write-set>
  </NsReadWriteSet>
<TxReadWriteSet>

또한 트랜잭션이 시뮬레이션 중에 범위 쿼리를 수행하는 경우 범위 쿼리와 그 결과가 쿼리 정보로 읽기 / 쓰기 집합에 추가됩니다.

Transaction validation and updating world state using read-write set

커미터는 읽기 쓰기 세트의 읽기 세트 부분을 사용하여 영향을받는 키의 버전과 값을 업데이트하기 위해 읽기 쓰기 세트의 쓰기 세트 부분과 트랜잭션의 유효성을 검사합니다.

유효성 검사 단계에서 트랜잭션의 읽기 세트에있는 각 키의 버전이 전 세계 상태의 동일한 키에 대한 버전과 일치 할 경우 트랜잭션이 유효한 것으로 간주됩니다. 이전의 모든 유효한 트랜잭션 (이전의 동일한 트랜잭션 블록)이 커밋 (커밋 - 상태)됩니다. 읽기 - 쓰기 세트에 하나 이상의 query-info도 포함되어 있으면 추가 유효성 검사가 수행됩니다.

이 추가 검증은 쿼리 정보에 캡처 된 결과의 수퍼 범위 (즉, 범위의 합집합)에 키가 삽입 / 삭제 / 업데이트되지 않았 음을 보장해야합니다. 즉, 커밋 된 상태에서 유효성 검사 중에 범위 쿼리 (시뮬레이션 중에 수행 한 트랜잭션)를 다시 실행하면 시뮬레이션시 트랜잭션이 관찰 한 것과 동일한 결과가 나타납니다. 이 확인은 트랜잭션이 커밋 중에 팬텀 항목을 관찰하는 경우 트랜잭션이 유효하지 않은 것으로 표시되어야 함을 보장합니다. 이 팬텀 보호는 범위 쿼리 (즉, 체인 코드의 GetStateByRange 함수)로 제한되며 다른 쿼리 (즉, 체인 코드의 GetQueryResult 함수)에는 아직 구현되지 않았습니다. 다른 쿼리는 유령의 위험이 있으므로 응용 프로그램이 시뮬레이션과 유효성 검사 / 커밋 시간 사이에 결과 집합의 안정성을 보장 할 수없는 경우 주문에 제출되지 않은 읽기 전용 트랜잭션에서만 사용해야합니다.

트랜잭션이 유효성 검사를 통과하면 커미터는 쓰기 상태를 사용하여 세계 상태를 업데이트합니다. 업데이트 단계에서 쓰기 세트에있는 각 키의 경우 동일한 키에 대한 월드 상태의 값이 쓰기 세트에 지정된 값으로 설정됩니다. 또한, 세계 상태의 키의 버전이 최신 버전을 반영하도록 변경됩니다.

Example simulation and validation

이 섹션은 예제 시나리오를 통한 의미 이해에 도움이됩니다. 이 예제의 목적을 위해, 세계 상태에서 키 k의 존재는 튜플 (k, ver, val)로 표현되며, 여기서 ver은 값을 val로 갖는 키 k의 최신 버전입니다.

이제 세계 상태의 동일한 스냅 샷에서 시뮬레이션 된 다섯 개의 트랜잭션 T1, T2, T3, T4 및 T5를 고려해보십시오. 다음은 트랜잭션이 시뮬레이션되는 세계 상태의 스냅 샷과 이러한 각 트랜잭션이 수행하는 읽기 및 쓰기 활동의 순서를 보여줍니다.

World state: (k1,1,v1), (k2,1,v2), (k3,1,v3), (k4,1,v4), (k5,1,v5)
T1 -> Write(k1, v1'), Write(k2, v2')
T2 -> Read(k1), Write(k3, v3')
T3 -> Write(k2, v2'')
T4 -> Write(k2, v2'''), read(k2)
T5 -> Write(k6, v6'), read(k5)

이제 이러한 트랜잭션이 T1, .., T5 순서로 정렬되어 있다고 가정합니다 (단일 블록 또는 다른 블록에 포함될 수 있음)

  1. T1은 읽기를 수행하지 않기 때문에 유효성 검사를 통과합니다. 또한, 월드 상태의 키 (k1, k2)의 튜플은 (k1,2, v1 '), (k2,2, v2')
  2. 앞의 트랜잭션 (T1)에 의해 수정 된 키 k1을 읽음으로써 T2의 유효성 검사에 실패합니다.
  3. T3은 읽기를 수행하지 않기 때문에 유효성 검사를 통과합니다. 또한, 세계 상태에서 키의 튜플은 (k2,3, v2 '')로 업데이트되고,
  4. 이전 트랜잭션 T1에 의해 수정 된 키 k2를 읽으므로 T4가 유효성 검사에 실패합니다.
  5. T5는 앞선 트랜잭션에 의해 수정되지 않은 키 k5를 읽으므로 유효성 검사를 통과합니다.

Note : 여러 읽기 / 쓰기 세트가있는 트랜잭션은 아직 지원되지 않습니다.

Gossip data dissemination protocol

Hyperledger 패브릭은 트랜잭션 실행 (승인 및 커밋) 피어 및 트랜잭션 주문 노드에서 작업 부하를 나누어 블록 체인 네트워크 성능, 보안 및 확장 성을 최적화합니다. 이러한 네트워크 운영 분리는 데이터 무결성 및 일관성을 보장하기 위해 안전하고 신뢰할 수 있으며 확장 가능한 데이터 보급 프로토콜을 필요로합니다. 이러한 요구 사항을 충족시키기 위해 Hyperledger Fabric은 gossip data dissemination protocol을 구현 합니다 .

Gossip protocol

피어들은 gossip을 활용하여 원장과 채널 데이터를 확장 가능한 방식으로 방송합니다. gossip  메시지는 계속되고 채널의 각 피어는 여러 피어에서 지속적으로 최신의 일관된 원장 데이터를 수신합니다. 각각의 gossip  메시지에 서명함으로써 위조 된 메시지를 보내는 비잔틴 참가자가 쉽게 식별되고 원치 않는 목표에 대한 메시지 배포를 막을 수 있습니다. 지연, 네트워크 파티션 또는 블록 손실로 이어지는 기타 원인으로 인해 영향을받은 피어는 이러한 누락 된 블록을 소유 한 피어에게 연락하여 현재 원장 상태로 동기화됩니다.

gossip  기반 데이터 보급 프로토콜은 Hyperledger 패브릭 네트워크에서 세 가지 기본 기능을 수행합니다.

  1. 사용 가능한 구성원 피어를 계속 식별하고 결국 오프라인이 된 피어를 감지하여 피어 검색 및 채널 구성원을 관리합니다.
  2. 채널의 모든 피어간에 원장 데이터를 보급합니다. 나머지 채널과 동기화되지 않은 데이터가있는 피어는 누락 된 블록을 식별하고 올바른 데이터를 복사하여 동기화합니다.
  3. 원장 데이터의 피어 - 투 - 피어 상태 이전 업데이트를 허용하여 새로 연결된 피어를 최대 속도로 가져옵니다.

gossip 기반 방송은 다른 피어로부터 채널의 메시지를 수신 한 피어가 작동 한 다음 이 메시지를 채널의 무작위로 선택된 여러 피어로 전달합니다.이 숫자는 구성 가능한 상수입니다. 피어는 메시지 전달을 기다리는 대신 끌어 오기 메커니즘을 사용할 수도 있습니다. 이 주기가 반복되어 채널 구성원의 결과로 원장과 상태 정보가 지속적으로 최신 상태로 유지됩니다. 새로운 블록을 보급하기 위해 채널 의 리더 피어는 주문 서비스에서 데이터를 가져 와서 동료에게 gossip  전파를 시작합니다.

Leader election

리더 선거 (leader election) 메커니즘은 주문 서비스와의 연결을 유지하고 자체 조직의 친구들간에게 새로 도착한 블록의 배포를 시작할 각 조직마다 하나의 피어 를 선출 하는 데 사용됩니다 . 리더 선거를 활용하면 시스템에서 주문 서비스의 대역폭을 효율적으로 활용할 수 있습니다. 리더 선거 모듈에는 두 가지 작동 모드가 있습니다.

  1. 정적(Static) - 시스템 관리자는 조직의 한 피어를 리더가되도록 수동으로 구성합니다 (예 : 주문 서비스와 열린 연결을 유지하는 것).
  2. 다이나믹(Dynamic) - 피어는 리더 선출 절차를 실행하여 조직의 한 피어를 선택하여 리더가되고, 주문 서비스에서 블록을 가져오고, 조직의 다른 피어에게 블록을 보급합니다.

Static leader election

정적 리더 선거를 사용하면 조직 내의 리더 피어 집합을 수동으로 정의 할 수 있습니다. 하나의 노드를 리더 또는 모든 사용 가능한 피어로 정의 할 수 있으므로 주문에 너무 많은 피어를 연결해야합니다 서비스가 비효율적 인 대역폭 사용을 유발할 수 있습니다. 정적 리더 선택 모드를 사용하려면 core.yaml 섹션에서 다음 매개 변수를 구성하십시오.

peer:
    # Gossip related configuration
    gossip:
        useLeaderElection: false
        orgLeader: true

또는 이러한 매개 변수를 환경 변수로 구성하고 재정의 할 수 있습니다.

export CORE_PEER_GOSSIP_USELEADERELECTION=false
export CORE_PEER_GOSSIP_ORGLEADER=true

1. 다음 구성은 피어를 대기 모드로 유지 합니다. 즉 피어가 리더가 되려고하지 않습니다.

export CORE_PEER_GOSSIP_USELEADERELECTION=false
export CORE_PEER_GOSSIP_ORGLEADER=false

2. true 값으로 CORE_PEER_GOSSIP_USELEADERELECTION 및 CORE_PEER_GOSSIP_USELEADERELECTION을 설정하면 모호하며 오류가 발생합니다.

3. 정적 구성에서 조직 관리자는 실패 또는 충돌시 리더 노드의 고 가용성을 제공해야합니다.

Dynamic leader election

역동적 인 리더 선거를 통해 조직 동료는 주문 서비스에 연결하고 새로운 블록을 꺼낼 피어 하나 를 선출 할 수 있습니다 . 리더는 각 조직의 동료를 위해 독립적으로 선출됩니다.

선출 된 리더는 활동의 증거로 다른 동료들에게 하트 비트 메시지 를 보내는 책임이 있습니다 . 한 명 이상의 동료가 일정 기간 동안 하트 비트 업데이트를 받지 못하면 새로운 리더 선출 절차를 시작하여 결국 새로운 리더를 선출하게됩니다. 최악의 경우 네트워크 파티션의 경우 조직을 위해 한 명 이상의 능동적 인 리더가 있으므로 탄력성과 가용성을 보장하여 조직의 동료가 계속 발전 할 수 있도록합니다. 네트워크 파티션이 치유되면 지도자 중 하나가 리더십을 포기할 것이므로 안정된 상태에서 각 조직의 네트워크 파티션이 없으면 주문 서비스에 연결하는  하나의 능동적 인 리더 가있게 됩니다 .

다음 구성은 리더 하트 비트 메시지의 빈도를 제어 합니다.

peer:
    # Gossip related configuration
    gossip:
        election:
            leaderAliveThreshold: 10s

동적 리더 선거를 사용하려면 core.yaml 내에 다음 매개 변수를 구성해야합니다.

peer:
    # Gossip related configuration
    gossip:
        useLeaderElection: true
        orgLeader: false

또는 이러한 매개 변수를 환경 변수로 구성하고 재정의 할 수 있습니다.

export CORE_PEER_GOSSIP_USELEADERELECTION=true
export CORE_PEER_GOSSIP_ORGLEADER=false

Gossip messaging

온라인 피어는 공개 키 인프라 (PKI) ID 및 보낸 사람의 메시지 서명을 포함하는 "활성"메시지를 지속적으로 브로드 캐스트하여 가용성을 나타냅니다 . 피어는 이러한 살아있는 메시지를 수집하여 채널 멤버쉽을 유지합니다. 피어가 특정 피어로부터 살아있는 메시지를 수신하지 않으면이 "죽은"피어는 결국 채널 멤버쉽에서 제거됩니다. "살아있는"메시지는 암호로 서명되기 때문에 악의적 인 피어는 루트 인증 기관 (CA)이 승인 한 서명 키가 없기 때문에 절대로 다른 피어를 사칭 할 수 없습니다.

수신 된 메시지를 자동으로 전달하는 것 외에도 상태 조정 프로세스 는 각 채널의 피어간에 world state 를 동기화 합니다. 각 피어는 불일치가 확인되면 자체 상태를 복구하기 위해 채널의 다른 피어에서 계속 블록을 가져옵니다. 가십 거리의 데이터 보급을 유지하기 위해 고정 연결이 필요하지 않기 때문에이 프로세스는 노드 충돌에 대한 내구성을 포함하여 공유 원장에 데이터 일관성 및 무결성을 안정적으로 제공합니다.

채널이 분리되어 있기 때문에 한 채널의 피어는 다른 채널에서 정보를 보내거나 공유 할 수 없습니다. 모든 피어가 여러 채널에 속할 수 있지만 분할 메시징은 피어의 채널 구독을 기반으로 메시지 라우팅 정책을 적용하여 채널에없는 피어로 블록이 전파되는 것을 방지합니다.

노트:

1. 지점 간 메시지의 보안은 피어 TLS 계층에서 처리되며 서명이 필요하지 않습니다. 피어는 CA에서 할당 한 인증서로 인증됩니다. TLS 인증서도 사용되지만 가십 계층에서 인증 된 것은 피어 인증서입니다. 원장 블록은 주문 서비스에서 서명 한 다음 채널의 리더 피어에게 전달합니다. 

2. 인증은 피어에 대한 멤버쉽 서비스 공급자의 관리를받습니다. 피어가 처음으로 채널에 연결되면 TLS 세션이 멤버 자격 정보와 바인딩됩니다. 이는 본질적으로 네트워크와 채널의 구성원 자격과 관련하여 연결 피어에 대한 각 피어를 인증합니다.