시스템 Chaincode 플러그인

시스템 Chaincode는 user의 Chaincode같이 분리된 Docker 컨테이너에서 실행되는 것과는 달리 피어 프로세스의 일부로 특별하게 작동하는 Chaincode입니다.

그러므로 시스템 Chaincode는 피어의 리소스에 더 많이 접근 할 수 있고, 유저 chaincode로 실행하기 어렵거나 불가능한 특징들을 실행하는 것에 사용됩니다.

시스템 Chaincode의 예시로는 Endorsing 제안의 ESCC(Endorser System Chaincode), 원장과 다른 fabric과 관련된 쿼리의 QSCC(Query System Chaincode) 마지막으론 커밋이 일어난 시점에 동시에 실행되는 VSCC(Validation System Chaincode)가 있습니다.

다른 유저 Chaincode들과는 달리, 시스템 Chaincode는 SDK나 CLI의 제안을 통해서 설치되거나 인스턴스화 되지 않습니다. 피어가 시작되는 순간에 등록되고 실행됩니다.

시스템 Chaincode가 피어와 연결되는 방법은 두가지가 있습니다.

Go 플러그인에서 정적이거나 동적으로 연결될 수 있습니다.

이번 튜토리얼은 시스템 Chaincode를 플러그인으로서 어떻게 개발하고 불러오는지를 배울 계획입니다.

플러그인 개발하기

시스템 Chaincode는 Go언어로 쓰여지고 Go 플러그인으로 불려집니다.

플러그인은 외부의 심볼와 main 패키지를 포함하고, 아래의 커맨드로 빌드합니다.

go build -buildmode=plugin

이미 존재하는 QSCC같은 Chaincode는 접근 관리 같은 전형적으로 시스템 Chaincode를 통해 실행되는 확실한 특징을 위한 탬플릿으로 취급 받습니다.

존재하는 시스템 Chaincode는 또한 로깅이나 테스팅 같은 최고의 예시로 참고할 수 있도록 취급받습니다.

- 주의 사항

임포트 된 패키지: Go 스탠다드 라이브러리는 플러그인이 반드시 호스트 어플리케이션에서 요구되는 버전과 같은 것을 포함해야합니다.

플러그인 설정하기

플러그인은 chaincode.systemPlugin 섹션에서 core.yaml로 설정 할 수 있습니다.

chaincode:
  systemPlugins:
    - enabled: true
      name: mysyscc
      path: /opt/lib/syscc.so
      invokableExternal: true
      invokableCC2CC: true

시스템 Chaincode는 반드시 chaincode.system 섹션에 core.yaml로 리스트가 될 수 있습니다.

chaincode:
  system:
    mysyscc: enable


출처 : http://hyperledger-fabric.readthedocs.io/en/release-1.1/systemchaincode.html

Chaincode는 Go로 쓰여진 프로그램으로, Java와 같은 다른 프로그래밍 언어로 구현 가능합니다.  

ChainCode는 규정된 인터페이스를 실행합니다.

Chaincode는 Endorsing Peer Process와 격리된  안전한 Docker container에서 실행됩니다.

어플리케이션에서 제출한 트랜잭션을 통해, Chaincode는 원장 State 초기화 및 관리를 합니다.

 

Chaincode는 네트워크의 구성원으로부터 동의된 비즈니스 로직을 일반적으로 다루고, Smart Contract와 유사합니다.

Chaincode는 트랜잭션 제안에 업데이트 또는 쿼리를 하기 위해서 호출될 수 있습니다.

Chaincode에 의해 생성된 상태(state)의 범위는 해당 체인코드로 한정되며, 다른 체인코드에 의해서 직접 access할 수 없습니다.

그러나, 동일 네트워트 상에서 적절한 권한이 주어지면 체인 코드는 다른 체인코드를 호출하여 해당 상태(state) 상태에 acess할 수 있습니다.

 

 이번 섹션에선 블록체인 네트워크 Operator 관점에서 Chaincode를 알아볼 것입니다.

Operator 관점에선 Noah라고 불리는데, Noah의 관심점은, Chaincode의 생애주기 오퍼레이션에 중점을 둘 예정입니다;

이는 패키징, 설치, 인스턴스화 그리고 업그레이드 같은 블록체인 내부의 Chaincode의 operational한 생애주기입니다.

Chaincode 생애주기

Hyperledger Fabric API는 피어, Orderer 및 MSP와 같은 블록 체인 네트워크의 다양한 노드와의 상호 작용을 가능하게 합니다.

또한 인증 피어 노드에 Chaincode를 패키징, 설치, 인스턴스화 및 업그레이드 할 수있게 합니다. 

Hyperledger Fabric 언어 - 특히 SDK는,  Hypercode Fabric API의 특성을 추상화하여 응용 프로그램 개발을 용이하게하지만 Chaincode의 수명주기를 관리하는 데 사용할 수 있습니다. 또한 Hyperledger 패브릭 API는 CLI를 통해 직접 액세스 할 수 있습니다.  이 문서에서는 CLI를 사용합니다.

 

우리는 chaincode의 라이프 사이클을 관리 할 수있는 네 개의 명령 - packageinstallinstantiate, 및 upgrade 을 제공 합니다.

향후 버전에서는 Chaincode를 실제로 제거하지 않고도 Chaincode를 비활성화하고 다시 활성화하는 트랜잭션을  stop하고 start하는 트랜잭션을 추가할 것입니다. Chaincode가 성공적으로 설치되고 인스턴스화 된 후에는 Chaincode가 활성화되어 실행 중인 invoke 트랜잭션을 통해 트랜잭션을 처리 할 수 ​​있습니다. Chaincode는 설치 후 언제든지 업그레이드 할 수 있습니다.

패키징

chaincode 패키지는 다음 세 부분으로 구성됩니다.

  • ChaincodeDeploymentSpec또는 CDS에 의해 정의 된 Chaincode , 
    CDS는 코드와 이름 및 버전과 같은 기타 속성의 chaincode 패키지를 정의합니다
  • • Endorsement에 사용 된 동일한 정책에 의해 구문 적으로 설명 될 수 있고 Endorsement Policy에 설명되어있는 선택적 인스턴스 정책. 그리고
  • Chaincode를 "소유하고있는"엔티티에 의한 일련의 서명.

서명은 다음과 같은 용도로 사용됩니다.

  • Chaincode의 소유권을 확립하고,
  • 패키지의 내용을 검증 할 수 있으며,
  • 패키지 변조를 탐지 할 수 있습니다.

채널상의 Chaincode의 인스턴스 생성 트랜잭션 생성자는 Chaincode의 인스턴스화 정책에 대해 유효성이 검사됩니다.

패키지 만들기

Chaincode를 패키징하는 데는 두 가지 방법이 있습니다. 하나는 Chaincode의 소유자를 여러 명 갖고 싶어하므로 여러 ID로 서명 된 chaincode 패키지가 있어야합니다. 이 작업 과정에서는 초기에 서명 된 Chaincode 패키지 (a SignedCDS)를 생성해야하며, 서명 된 Chaincode 패키지 는 연속적으로 서명을 위해 다른 각 소유자에게 전달됩니다.

더 간단한 워크 플로우는 install 트랜잭션을 _ 행하는 노드의 ID의 서명 만 갖는 SignedCDS를 전개 할 때 사용 됩니다.

먼저 복잡한 사례를 다룰 것입니다. 그러나 아직 여러 소유자를 걱정할 필요가없는 경우 아래 Chaincode 설치 섹션으로 건너 뛸 수 있습니다 .

서명 된 chaincode 패키지를 만들려면 다음 명령을 사용하십시오.

peer chaincode package -n mycc -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -v 0 -s -S -i "AND('OrgA.admin')" ccpack.out

이 -s옵션은 단순히 원시 CDS를 작성하는 것이 아니라 여러 소유자가 서명 할 수있는 패키지를 작성합니다.  이때 -s가 지정되면, -S 옵션은 다른 소유자가 로그인해야 위하여려고하는 경우에 지정해야합니다. 그렇지 않으면, 프로세스는 CDS뿐만 아니라 인스턴스화 정책 만 포함하는 SignedCDS를 작성합니다.

 

이 -S옵션은에있는 localMspid속성 의 값으로 식별되는 MSP를 사용하여 패키지에 서명하도록 프로세스에 지시합니다 core.yaml.

이 -S옵션은 선택 사항입니다. 그러나 패키지가 서명없이 작성된 경우, signpackage명령을 사용하여 다른 소유자가 서명 할 수 없습니다 .

선택적 -i옵션은 chaincode에 대한 인스턴스화 정책을 지정할 수있게합니다. 인스턴스화 정책은 승인 정책과 동일한 형식을 가지며 Chaincode를 인스턴스화 할 수있는 ID를 지정합니다. 위의 예에서 OrgA의 관리자 만이 chaincode를 인스턴스화 할 수 있습니다. 정책이 제공되지 않으면 기본 정책이 사용되며 피어의 MSP의 관리자 ID 만 Chaincode를 인스턴스화 할 수 있습니다.

패키지 서명

작성시 서명 된 Chaincode 패키지는 검사 및 서명을 위해 다른 소유자에게 양도 될 수 있습니다. 워크 플로는 Chaincode 패키지의 대역 외 서명을 지원합니다.

ChaincodeDeploymentSpec는 선택적으로 만들기 위해 공동 소유자에 의해 서명 될 수있습니다.

SignedChaincodeDeploymentSpec (또는 SignedCDS을). SignedCDS는 3 가지 요소를 포함합니다 :

  1. CDS에는 Chaincode의 소스 코드, 이름 및 버전이 들어 있습니다.
  2. Endorsement Policy로 표현 된 Chaincode의 인스턴스 정책.
  3. 배서의 수단으로 정의 된 Chaincode 소유자 목록 .

노트

이 인증 정책은 일부 채널에서 Chaincode가 인스턴스화 될 때 적절한 MSP 보안 주체를 제공하기 위해 대역 외로 결정됩니다. 인스턴스화 정책이 지정되지 않은 경우 기본 정책은 채널의 모든 MSP 관리자입니다.

각 소유자는 ChaincodeDeploymentSpec을 해당 소유자의 신원 (예 : 인증서)과 결합하고 결합 된 결과에 서명함으로써 ChaincodeDeploymentSpec을 승인합니다.

Chaincode 소유자는 다음 명령을 사용하여 이전에 작성한 서명 된 패키지에 서명 할 수 있습니다.

peer chaincode signpackage ccpack.out signedccpack.out

여기서 ccpack.outsignedccpack.out는 입력 및 출력 패키지입니다. signedccpack.out로컬 MSP를 사용하여 서명 된 패키지에 대한 추가 서명을 포함합니다.

Chaincode 설치

install 트랜잭션은 ChaincodeDeploymentSpec 또는 CDS의 형태로 정리된 포맷으로 Chaincode 소스코드를 패키징 해줍니다.

그리고 피어 노드에 설치하고 해당 Chaincode를 실행할 것입니다.

노트

Chaincode를 실행할 채널의  엔드 피어 노드에 Chaincode를 설치해야합니다 .

단순히 ChaincodeDeploymentSpec이 주어진 Install API일 때, 기본적으로 인스턴스화 정책과 빈 오너 리스트를 가지게 될 것입니다.

노트

Chaincode는 Chaincode 소유 구성원의 피어 노드를 승인하는 경우에만 설치해야 네트워크의 다른 구성원으로부터 Chaincode 논리의 기밀성을 보호 할 수 있습니다. Chaincode가없는 멤버는 Chaincode의 트랜잭션을 승인 할 수 없습니다. 즉, Chaincode를 실행할 수 없습니다. 그러나 이들은 여전히 ​​장부에 대한 트랜잭션의 유효성을 검사하고 커밋 할 수 있습니다.

Chaincode를 설치하기 위해선, SignedProposal을 시스템 Chaincode 섹션에서 설명된 lifecycle system chaincode를 전송하십시오.

예를 들어, CLI를 사용하여 Simple Asset Chaincode 섹션에 설명 된 sacc 샘플 체인 코드 를 설치하려면 명령이 다음과 같아야합니다.

peer chaincode install -n asset_mgmt -v 1.0 -p sacc

CLI는 내부적으로 sacc에 SignedChaincodeDeploySpec을 만들고, 로컬 피어에 전송합니다. 이는 LSCC에서 install 메소드로 불립니다.

인자 -p는 chaincode의 경로를 의미하고, 유저의 GOPATH에 있어야합니다.(예:GOPATH/src/sacc) CLI 섹션을 확인하시면 커맨드 옵션에 완벽한 설명이 되어 있습니다.

피어에 설치하기 위해선, SignedProposal의 서명이 로컬 MSP 관리자 중 하나여야만 합니다.

인스턴스화

instantiate 트랜잭션이 호출 (LSCC)를 작성하고 채널에 chaincode를 초기화 할 수 있습니다. 이것은 Chaincode 채널 바인딩 프로세스입니다. Chaincode는 여러 채널에 바인딩되어 각 채널에서 개별적으로 독립적으로 작동 할 수 있습니다. 즉, Chaincode를 설치하고 인스턴스화 할 수있는 다른 채널 수에 관계없이 State는 트랜잭션이 제출 된 채널과 격리되어 있습니다.lifecycle System Chaincode

instantiate 트랜잭션 생성자는 SignedCDS에 포함 된 Chaincode의 인스턴스화 정책을 충족해야하며 채널 작성자로 채널 작성자로 구성되어야합니다. 채널의 보안이 악성 엔티티가 Chaincode를 배포하거나 구성원을 속여 언 바운드 채널에서 Chaincode를 실행하는 것을 방지하는 데 중요합니다.

예를 들어 기본 인스턴스화 정책은 모든 채널 MSP 관리자이므로 Chaincode 인스턴스 생성 트랜잭션 작성자는 채널 관리자의 구성원이어야합니다. 트랜잭션 제안서가 엔도 서에 도착하면 생성자의 서명을 인스턴스화 정책과 비교하여 검증합니다. 이 작업은 장부에 커밋하기 전에 트랜잭션 유효성 검사 중에 다시 수행됩니다.

또한 인스턴스 생성 트랜잭션은 채널에서 해당 Chaincode에 대한 Endorsement Policy를 설정합니다. Endorsement Policy는 채널 구성원이 승인 한 트랜잭션 결과에 대한 증명 요구 사항을 설명합니다.

예를 들어, 인스턴스화 CLI를 사용하여 SACC chaincode와 함께 State를 john과 0으로 초기화하고, 명령은 다음과 같습니다

peer chaincode instantiate -n sacc -v 1.0 -c '{"Args":["john","0"]}' -P "OR ('Org1.member','Org2.member')"

노트

Endorsement Policy에 유의하십시오 .이 경우 모든 트랜잭션이 sacc 할 수 있도록 Org1 또는 Org2 구성원의 Endorsement가 필요합니다 . 즉, Org1 또는 Org2는 유효한 트랜잭션이되도록 sacc 에서  를 실행 한 결과에 서명해야 합니다.

성공적으로 인스턴스화 된 후에는 Chaincode가 채널의 활성 State가되며 ENDORSER_TRANSACTION 유형의 모든 트랜잭션 제안을 처리 할 준비가됩니다 . 트랜잭션은 Endorsement 피어에 도착하면서 동시에 처리됩니다.

업그레이드

체인 코드는 SignedCDS의 일부 버전을 변경하여 언제든지 업그레이드 할 수 있습니다. 소유자 및 인스턴스 정책과 같은 다른 부분은 선택 사항입니다. 그러나 체인 코드 이름은 동일해야합니다. 그렇지 않으면 완전히 다른 체인 코드로 간주됩니다.

업그레이드하기 전에 새 버전의 체인 코드를 필요한 endorser에 설치해야합니다. 업그레이드는 체인 코드의 새 버전을 채널에 바인드하는 인스턴스화 트랜잭션과 유사한 트랜잭션입니다. 체인 코드의 이전 버전에 바인딩 된 다른 채널은 여전히 ​​이전 버전과 함께 실행됩니다. 즉, upgrade트랜잭션은 한 번에 하나의 채널 (트랜잭션이 제출되는 채널)에만 영향을줍니다.

노트

체인 코드의 여러 버전이 동시에 활성화 될 수 있으므로 업그레이드 프로세스가 자동으로 이전 버전을 제거하지 않으므로 사용자는 당분간이를 관리해야합니다.

instantiate트랜잭션 과의 미묘한 차이점이 있습니다. upgrade트랜잭션은 새 정책 (지정된 경우)이 아닌 현재 체인 코드 인스턴스화 정책에 대해 검사됩니다. 이것은 현재 인스턴스화 정책에 지정된 기존 구성원 만이 체인 코드를 업그레이드 할 수 있도록하기위한 것입니다.

노트

업그레이드 중에 chaincode Init함수가 호출되어 데이터 관련 업데이트를 수행하거나 다시 초기화하므로 체인 코드를 업그레이드 할 때 State를 다시 설정하지 않도록주의해야합니다.

중지 및 시작

stopstart라이프 사이클 트랜잭션은 아직 구현되지 않았습니다. 그러나 각 endorsers에서 chaincode 컨테이너와 SignedCDS 패키지를 제거하여 체인 코드를 수동으로 중지 할 수 있습니다.  이것은 인증 피어 노드가 실행중인 각 호스트 또는 가상 시스템에서 체인 코드의 컨테이너를 삭제 한 다음 각 인증 피어 노드에서 SignedCDS를 삭제하여 수행됩니다.

참고 : 피어 노드에서 CDS를 삭제하려면 먼저 피어 노드의 컨테이너에 들어가야합니다. 이를 수행 할 수있는 유틸리티 스크립트를 제공해야합니다.
docker rm -f <container id>
rm /var/hyperledger/production/chaincodes/<ccname>:<ccversion>

Stop은 업그레이드를하기 전에 모든 피어의 채널에서 체인 코드를 중지 할 수있는 제어 된 방식으로 업그레이드를 수행하는 워크 플로에서 유용합니다.

CLI

 참고 : 우리는 Hyperledger Fabric 바이너리 용 플랫폼 특정 peer 바이너리를 배포 할 필요성을 평가하고 있습니다. 당분간, 실행중인 도커 컨테이너에서 명령을 간단히 호출 할 수 있습니다.

현재 사용 가능한 CLI 명령을 보려면 실행중인 fabric-peerDocker 컨테이너 에서 다음 명령을 실행하십시오 .

docker run -it hyperledger/fabric-peer bash 
# peer chaincode --help

아래 예제와 비슷한 출력을 보여줍니다 :

Usage:
  peer chaincode [command]

Available Commands:
  install     Package the specified chaincode into a deployment spec and save it on the peer's path.
  instantiate Deploy the specified chaincode to the network.
  invoke      Invoke the specified chaincode.
  list        Get the instantiated chaincodes on a channel or installed chaincodes on a peer.
  package     Package the specified chaincode into a deployment spec.
  query       Query using the specified chaincode.
  signpackage Sign the specified chaincode package
  upgrade     Upgrade chaincode.

Flags:
      --cafile string      Path to file containing PEM-encoded trusted certificate(s) for the ordering endpoint
  -h, --help               help for chaincode
  -o, --orderer string     Ordering service endpoint
      --tls                Use TLS when communicating with the orderer endpoint
      --transient string   Transient map of arguments in JSON encoding

Global Flags:
      --logging-level string       Default logging level and overrides, see core.yaml for full syntax
      --test.coverprofile string   Done (default "coverage.cov")
  -v, --version

Use "peer chaincode [command] --help" for more information about a command.

스크립트 응용 프로그램에서의 사용을 용이하게하기 위해 peer명령은 명령 실패시 항상 0이 아닌 리턴 코드를 생성합니다.

체인 코드 명령의 예 :

peer chaincode install -n mycc -v 0 -p path/to/my/chaincode/v0
peer chaincode instantiate -n mycc -v 0 -c '{"Args":["a", "b", "c"]}' -C mychannel
peer chaincode install -n mycc -v 1 -p path/to/my/chaincode/v1
peer chaincode upgrade -n mycc -v 1 -c '{"Args":["d", "e", "f"]}' -C mychannel
peer chaincode query -C mychannel -n mycc -c '{"Args":["query","e"]}'
peer chaincode invoke -o orderer.example.com:7050  --tls --cafile $ORDERER_CA -C mychannel -n mycc -c '{"Args":["invoke","a","b","10"]}'

시스템 체인 코드

시스템 체인 코드는 일반적인 체인 코드와 같은 격리 된 컨테이너가 아닌 피어 프로세스 내에서 실행된다는 점을 제외하고는 동일한 프로그래밍 모델을 사용합니다. 따라서 시스템 체인 코드는 피어 실행 파일에 내장되어 있으며 위에서 설명한 동일한 수명주기를 따르지 않습니다. 특히 설치 , 인스턴스화 및 업그레이드 는 시스템 체인 코드에 적용되지 않습니다.

시스템 체인 코드의 목적은 피어와 체인 코드 간 gRPC 통신 비용을 단축하고 관리 유연성을 절충하는 것입니다. 예를 들어, 시스템 체인 코드는 피어 이진 파일로만 업그레이드 할 수 있습니다. 또한 컴파일 된 매개 변수 의 고정 세트로 등록해야하며 Endorsement Policy 또는 Endorsement Policy 기능이 없습니다.

시스템 체인 코드는 Hyperbridger Fabric에서 시스템 통합 자에 의해 적절하게 대체되거나 수정 될 수 있도록 여러 시스템 동작을 구현하는 데 사용됩니다.

시스템 체인 코드의 현재 목록 :

  1. LSCC Lifecycle 시스템 체인 코드는 위에서 설명한 라이프 사이클 요청을 처리합니다.
  2. CSCC 구성 시스템 체인 코드는 피어 측의 채널 구성을 처리합니다.
  3. QSCC 쿼리 시스템 체인 코드는 블록 및 트랜잭션 가져 오기와 같은 원장 쿼리 API를 제공합니다.
  4. ESCC 인증 시스템 체인 코드는 트랜잭션 제안 제안서에 서명함으로써 Endorsement를 처리합니다.
  5. VSCC 유효성 검사 시스템 체인 코드는 Endorsement Policy 및 다중 버전 동시성 제어 검사와 같은 트랜잭션 유효성 검사를 처리합니다.

이러한 시스템 체인 코드, 특히 LSCC, ESCC 및 VSCC가 주 트랜잭션 실행 경로에 있으므로 수정 또는 교체 할 때는주의해야합니다. 

VSCC가 장부에 커밋하기 전에 블록의 유효성을 검사 할 때 채널의 모든 피어가 원장 분기 (비 결정 성)를 피하기 위해 동일한 유효성 검사를 계산하는 것이 중요합니다. 

따라서 VSCC가 수정되거나 대체 된 경우 특별한 주의가 필요합니다.


출처 : http://hyperledger-fabric.readthedocs.io/en/release-1.1/chaincode4noah.html

Chaincode는 Go와 Node.js로 쓰여진 프로그램입니다. 그리고 규정된 인터페이스를 실행합니다.

차후엔 자바와 같은 다른 프로그래밍 언어들도 지원할 것입니다.

Chaincode는 보안된 Docker container에 허가된 피어 프로세스와 격리되어 실행됩니다.

Chaincode는 어플리케이션에서 제출하여 트랜잭션으로 원장 State 초기화 및 관리를 합니다.

Chaincode는 전형적으로 네트워크의 구성원으로부터 동의된 비즈니스 로직을 다루고, 그래서 Smart Contract와 유사합니다.

Chaincode는 트랜잭션 제안에 업데이트 또는 쿼리를 하기 위해서 호출될 수 있습니다.

허가를 받은 State에서, Chaincode는 state에 액세스 하기 위해서 같은 Channel이나 다른 Channel에서도 또 다른 Chaincode를 호출할 수 있습니다.

만약 다른 Channel에서 호출된 Chaincode일 경우 읽기 전용으로만 접근이 가능하다는 점을 알고 계셔야합니다.

즉, 다른 Channel에서 불려진 Chaincode는 단지 쿼리일 뿐이라는 것을 의미합니다. 이는 이후의 커밋 페이즈에서 State 인증에 참여하지 않는다는 것을 의미하고 있습니다.

다음의 섹션에선, 어플리케이션 개발자의 입장에서 Chaincode를 배워볼 것 입니다.

단순한 어플리케이션의 샘플 코드와 Chaincode Shim API의 각각의 메소드의 목적을 확인하는 것을 보여드리겠습니다.

Chaincode API

각각의 Chaincode 프로그램은 아래의 Chaincode interface로 실행되어야합니다:

  • Go
  • Node.js

해당 인터페이스들의 전달받은 트랜잭션의 반응으로 메소드 콜을 발생시킵니다.

특히 Init 메소드는 Chaincode가 Instantiate나 Upgrade와 같은 트랜잭션 메소드를 어플리케이션 State에 관한 초기화를 포함하여 Chaincode가 필요한 초기화를 위해서 불려집니다.

Invoke 메소드는 Invoke 트랜잭션이 트랜잭션의 제안을 받았을 때 발생하게 됩니다.

다른 "Shim" API에 들어있는 Chaincode는 ChaincodeStubInterface 아래의 언어로 실행됩니다:

  • Go
  • Node.js

이들은 원장에 접근하거나 수정하기위해서 사용되고, Chaincode 간에 호출을 위해서 사용됩니다.

이번 튜토리얼에선, 단순한 "Asset"을 관리하는 Chaincode 어플리케이션을 실행함으로서 이러한 종류의 API 사용을 시연하겠습니다.

Simple Asset Chaincode

아래의 어플리케이션은 원장에 Asset을 Key-Value 페어로 만드는 간단한 샘플 Chaincode 입니다.

code의 디렉토리 설정하기

Go언어로 개발한 경험이 없으시다면, Go언어가 시스템에 적절하게 설정된 State로 설치되어 있어야 합니다.

지금부터, Chaincode 어플리케이션을 위한 하나의 child directory로서 $GOPATH/src/ 디렉토리를 만들겠습니다.

간단히 실행하기 위해선, 아래의 커맨드를 입력하세요.

mkdir -p $GOPATH/src/sacc && cd $GOPATH/src/sacc

코드를 써넣을 소스 코드를 만들어 보겠습니다.

touch sacc.go

시스템 하우스 관리

우선, 하우스 관리를 하면서 시작합시다. 모든 Chaincode들 처럼, Chaincode 인터페이스를 실행해주어야 합니다.

특히, Init과 Invoke 함수를 실행하셔야 합니다.

go언어에 Chaincode 의존성을 추가하십시오.

Chaincode shim package와 peer protobuf package를 임포트 할 것입니다.

다음으로, Simple Asset을 Chaincode Shim Function으로서 추가할 것 입니다.

package main

import (
    "fmt"

    "github.com/hyperledger/fabric/core/chaincode/shim"
    "github.com/hyperledger/fabric/protos/peer"
)

// SimpleAsset implements a simple chaincode to manage an asset
type SimpleAsset struct {
}

Chaincode 초기화

다음으로, Init 함수를 실행할 것입니다.

// Init is called during chaincode instantiation to initialize any data.
func (t *SimpleAsset) Init(stub shim.ChaincodeStubInterface) peer.Response {

}

해당 함수에서 이미 Chaincode 업그레이드가 이루어진다는 것을 확인하세요.

Chaincode를 작성할 때 이전의 것을 업그레이드 할 것입니다.

Init을 적절하게 수정하셔야합니다.

특히, "마이그레이션"이 없으면 아무 것도 초기화 되지 않고, 비어있는 Init 메소드를 제공합니다.

다음으로, Init 호출에서 ChaincodeStubInterface.GetStringArgs 메소드를 통해 매개변수를 돌려받습니다. 그리고 유효성을 체크합니다.

우리의 경우에, Key-Value 쌍을 기대할 수 있습니다.

// Init is called during chaincode instantiation to initialize any
// data. Note that chaincode upgrade also calls this function to reset
// or to migrate data, so be careful to avoid a scenario where you
// inadvertently clobber your ledger's data!
func (t *SimpleAsset) Init(stub shim.ChaincodeStubInterface) peer.Response {
  // Get the args from the transaction proposal
  args := stub.GetStringArgs()
  if len(args) != 2 {
    return shim.Error("Incorrect arguments. Expecting a key and a value")
  }
}

다음 단계는, 호출이 유효할 수 있도록 만들어 냈습니다, 이제 원장에 초기 State를 저장할 것입니다.

이 단계를 진행하기에 앞서, ChaincodeStubInterface.Putstate를 불러내어 Key와 Value를 인자로 전송할 것 입니다.

모든 것이 잘 되었다는 전제하에, 초기화 하는 Response 객체가 성공했을 것입니다.

 1 // Init is called during chaincode instantiation to initialize any
 2 // data. Note that chaincode upgrade also calls this function to reset
 3 // or to migrate data, so be careful to avoid a scenario where you
 4 // inadvertently clobber your ledger's data!
 5 func (t *SimpleAsset) Init(stub shim.ChaincodeStubInterface) peer.Response {
 6   // Get the args from the transaction proposal
 7   args := stub.GetStringArgs()
 8   if len(args) != 2 {
 9     return shim.Error("Incorrect arguments. Expecting a key and a value")
10   }
11 
12   // Set up any variables or assets here by calling stub.PutState()
13 
14   // We store the key and the value on the ledger
15   err := stub.PutState(args[0], []byte(args[1]))
16   if err != nil {
17     return shim.Error(fmt.Sprintf("Failed to create asset: %s", args[0]))
18   }
19   return shim.Success(nil)
20 }

Chaincode 호출

우선, Invoke 함수의 서명을 추가합니다.

// Invoke is called per transaction on the chaincode. Each transaction is
// either a 'get' or a 'set' on the asset created by Init function. The 'set'
// method may create a new asset by specifying a new key-value pair.
func (t *SimpleAsset) Invoke(stub shim.ChaincodeStubInterface) peer.Response {

}

위에서의 Invoke 함수와 함께, ChaincodeStubInterface로부터 인자를 추출해낼 필요가 있습니다.

Invoke 함수의 인자는 호출할 Chaincode 어플리케이션의 함수 이름입니다.

우리의 경우에, 간단히 두 가지의 함수를 가지고 있습니다: set & get

해당 함수들을 통해서 asset의 값을 set할 수 있고, 또한 현재 State를 리턴 받을 수 있습니다.

우리는 우선 ChaincodeStrubInterface.GetFunctionAndParameters를 함수의 이름과 매개변수를 chaincode 어플리케이션 함수에 추출하기 위해서 호출 할 것입니다.

// Invoke is called per transaction on the chaincode. Each transaction is
// either a 'get' or a 'set' on the asset created by Init function. The Set
// method may create a new asset by specifying a new key-value pair.
func (t *SimpleAsset) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
    // Extract the function and args from the transaction proposal
    fn, args := stub.GetFunctionAndParameters()

}

다음으로, 우리는 함수의 이름을 set과 get과 같은 형태로 만들어 낼 것입니다. 그리고 해당되는 Chaincode 어플리케이션 함수를 적절한 Shim.success와 Shim.error 함수를 gRPC protobuf 메시지 형태로 응답하며 시리얼라이즈 출력을 하면서 호출해낼 것 입니다.

// Invoke is called per transaction on the chaincode. Each transaction is
// either a 'get' or a 'set' on the asset created by Init function. The Set
// method may create a new asset by specifying a new key-value pair.
func (t *SimpleAsset) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
    // Extract the function and args from the transaction proposal
    fn, args := stub.GetFunctionAndParameters()

    var result string
    var err error
    if fn == "set" {
            result, err = set(stub, args)
    } else {
            result, err = get(stub, args)
    }
    if err != nil {
            return shim.Error(err.Error())
    }

    // Return the result as success payload
    return shim.Success([]byte(result))
}

Chaincode 어플리케이션 실행하기

씌여진 대로, 우리의 Invoke 함수를 통해서 두개의 함수를 가진 Chaincode 어플리케이션을 실행할 것입니다.

이제 해당하는 함수들을 실행합니다. 위에서 말한 것처럼, 원장에 접근하기 위해선, ChaincodeStubInterface.Putstate와 ChaincodeStubInterface.Getstate 함수를 Chaincode shim API로부터 불러들일 것 입니다.

// Set stores the asset (both key and value) on the ledger. If the key exists,
// it will override the value with the new one
func set(stub shim.ChaincodeStubInterface, args []string) (string, error) {
    if len(args) != 2 {
            return "", fmt.Errorf("Incorrect arguments. Expecting a key and a value")
    }

    err := stub.PutState(args[0], []byte(args[1]))
    if err != nil {
            return "", fmt.Errorf("Failed to set asset: %s", args[0])
    }
    return args[1], nil
}

// Get returns the value of the specified asset key
func get(stub shim.ChaincodeStubInterface, args []string) (string, error) {
    if len(args) != 1 {
            return "", fmt.Errorf("Incorrect arguments. Expecting a key")
    }

    value, err := stub.GetState(args[0])
    if err != nil {
            return "", fmt.Errorf("Failed to get asset: %s with error: %s", args[0], err)
    }
    if value == nil {
            return "", fmt.Errorf("Asset not found: %s", args[0])
    }
    return string(value), nil
}

모든 값을 가져오기

마지막으로 main 함수를 추가해야할 필요가 있습니다. 이 함수는 shim.start 함수를 불러낼 것입니다.

이제 전체 Chaincode 소스코드를 보여드리겠습니다.

package main

import (
    "fmt"

    "github.com/hyperledger/fabric/core/chaincode/shim"
    "github.com/hyperledger/fabric/protos/peer"
)

// SimpleAsset implements a simple chaincode to manage an asset
type SimpleAsset struct {
}

// Init is called during chaincode instantiation to initialize any
// data. Note that chaincode upgrade also calls this function to reset
// or to migrate data.
func (t *SimpleAsset) Init(stub shim.ChaincodeStubInterface) peer.Response {
    // Get the args from the transaction proposal
    args := stub.GetStringArgs()
    if len(args) != 2 {
            return shim.Error("Incorrect arguments. Expecting a key and a value")
    }

    // Set up any variables or assets here by calling stub.PutState()

    // We store the key and the value on the ledger
    err := stub.PutState(args[0], []byte(args[1]))
    if err != nil {
            return shim.Error(fmt.Sprintf("Failed to create asset: %s", args[0]))
    }
    return shim.Success(nil)
}

// Invoke is called per transaction on the chaincode. Each transaction is
// either a 'get' or a 'set' on the asset created by Init function. The Set
// method may create a new asset by specifying a new key-value pair.
func (t *SimpleAsset) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
    // Extract the function and args from the transaction proposal
    fn, args := stub.GetFunctionAndParameters()

    var result string
    var err error
    if fn == "set" {
            result, err = set(stub, args)
    } else { // assume 'get' even if fn is nil
            result, err = get(stub, args)
    }
    if err != nil {
            return shim.Error(err.Error())
    }

    // Return the result as success payload
    return shim.Success([]byte(result))
}

// Set stores the asset (both key and value) on the ledger. If the key exists,
// it will override the value with the new one
func set(stub shim.ChaincodeStubInterface, args []string) (string, error) {
    if len(args) != 2 {
            return "", fmt.Errorf("Incorrect arguments. Expecting a key and a value")
    }

    err := stub.PutState(args[0], []byte(args[1]))
    if err != nil {
            return "", fmt.Errorf("Failed to set asset: %s", args[0])
    }
    return args[1], nil
}

// Get returns the value of the specified asset key
func get(stub shim.ChaincodeStubInterface, args []string) (string, error) {
    if len(args) != 1 {
            return "", fmt.Errorf("Incorrect arguments. Expecting a key")
    }

    value, err := stub.GetState(args[0])
    if err != nil {
            return "", fmt.Errorf("Failed to get asset: %s with error: %s", args[0], err)
    }
    if value == nil {
            return "", fmt.Errorf("Asset not found: %s", args[0])
    }
    return string(value), nil
}

// main function starts up the chaincode in the container during instantiate
func main() {
    if err := shim.Start(new(SimpleAsset)); err != nil {
            fmt.Printf("Error starting SimpleAsset chaincode: %s", err)
    }
}

Chaincode 만들기

Chaincode를 컴파일 하겠습니다.

go get -u --tags nopkcs11 github.com/hyperledger/fabric/core/chaincode/shim
go build --tags nopkcs11

오류가 없다는 전제하에, Chaincode를 테스팅 하는 다음단계로 나아가실 수 있습니다.

개발자 모드로 테스팅하기

일반적으로 Chaincode는 피어에 의해서 시작되고 관리됩니다. 그러나 개발자 모드에선 Chaincode는 사용자에 의해서 만들어지고 제작됩니다.

이 모드는 개발 도중 빠른 코딩/빌드/실행/디버그 사이클을 돌려보는 것에 매우 유용합니다.

우리는 샘플 개발자 네트워크에서 이미 만들어진 Orderer와 채널 아티팩트를 사용해서 개발자 모드를 시작할 것입니다.

마찬가지로, 사용자는 바로 Chaincode를 컴파일 하고 실행해보실 수 있습니다.

Hyperledger Fabric Sample 설치하기

앞의 과정이 문제없이 해결되셨다면, Hyperledger Sample을 설치하십시오.

Docker의 chaincode-docker-devmode 디렉토리의 fabric-samples를 복사하십시오.

cd chaincode-docker-devmode

Docker 이미지 다운로드 하기

개발자 모드를 위해선 제공된 Docker Compose 스크립트를 이용해서 4개의 Docker 이미지를 활용해야 합니다.

만약 fabric-samples 디렉토리에 복사본을 설치하셨다면 DownloadPlatform-specific Binaies의 지시를 따르시면 됩니다.

그러면, 로컬에 설치된 Docker 이미지를 가질 수 있습니다.

만약 수동으로 받아온 이미지라면 latest를 붙이셔야만 합니다.

docker images
REPOSITORY                     TAG                                  IMAGE ID            CREATED             SIZE
hyperledger/fabric-tools       latest                           b7bfddf508bc        About an hour ago   1.46GB
hyperledger/fabric-tools       x86_64-1.1.0                     b7bfddf508bc        About an hour ago   1.46GB
hyperledger/fabric-orderer     latest                           ce0c810df36a        About an hour ago   180MB
hyperledger/fabric-orderer     x86_64-1.1.0                     ce0c810df36a        About an hour ago   180MB
hyperledger/fabric-peer        latest                           b023f9be0771        About an hour ago   187MB
hyperledger/fabric-peer        x86_64-1.1.0                     b023f9be0771        About an hour ago   187MB
hyperledger/fabric-javaenv     latest                           82098abb1a17        About an hour ago   1.52GB
hyperledger/fabric-javaenv     x86_64-1.1.0                     82098abb1a17        About an hour ago   1.52GB
hyperledger/fabric-ccenv       latest                           c8b4909d8d46        About an hour ago   1.39GB
hyperledger/fabric-ccenv       x86_64-1.1.0                     c8b4909d8d46        About an hour ago   1.39GB

docker image를 발급해서 로컬 Docker Registry에 올리십시오. 아래와 같은 것을 확인하실 수 있을 것입니다.

이제 3개의 터미널을 열어 chaincode-docker-devmode 디렉토리로 모든 터미널을 이동해주십시오.

터미널1 네트워크 시작하기

docker-compose -f docker-compose-simple.yaml up

위의 커맨드는 singleSampleMSPSolo의 Orderer 정보와 함께 네트워크를 시작합니다.

그리고 피어를 개발자 모드로 실행합니다.

남은 두개의 컨테이너는 chaincode 환경과 CLI 환경을 위한 것입니다.

채널을 만들고 참여하기 위한 기능들은 CLI환경에서 제공합니다.

그렇기 때문에 바로 Chaincode 호출로 넘어갈 수 있습니다.

터미널2 빌드& 스타트 Chaincode

docker exec -it chaincode bash

입력하신 이후 아래와 같은 결과를 보실 수 있습니다.

root@d2629980e76b:/opt/gopath/src/chaincode#

Chaincode를 컴파일 하십시오.

cd sacc
go build

Chaincode를 실행하세요.

CORE_PEER_ADDRESS=peer:7052 CORE_CHAINCODE_ID_NAME=mycc:0 ./sacc

Chaincode가 피어와 함께 실행되었고, Chaincode 로그는 성공적인 등록을 피어와 마쳤을 것입니다.

이 단계에서 Chaincode가 어떤 채널과도 연관되지 않았다는 것을 아셔야합니다.

이 과정은 다음에 나올 Instantiate 커맨드에서 완료하실 수 있습니다.

터미널3 Chaincode 사용하기

비록 --peer-chaincodedev모드에 있더라도, Chaincode를 설치하셔야 chaincode 라이프 싸이클을 정상적으로 확인할 수 있습니다.

이 요구사항은 앞으로 사라질 예정입니다.

CLI 컨테이너에서 아래와 같은 명령으로 불러낼 수 있습니다.

docker exec -it cli bash
peer chaincode install -p chaincodedev/chaincode/sacc -n mycc -v 0
peer chaincode instantiate -n mycc -v 0 -c '{"Args":["a","10"]}' -C myc

이제 a 값에 20을 할당하세요.

peer chaincode invoke -n mycc -c '{"Args":["set", "a", "20"]}' -C myc

마지막으로 쿼리 a를 실행하시고, 20이라는 값을 확인하세요

peer chaincode query -n mycc -c '{"Args":["query","a"]}' -C myc

새로운 Chaincode 테스팅하기

기본적으로, 여러분은 sacc만 마운팅하셨을 겁니다. 그러나 chaincode(chaincode 컨테이너를 의미함)에 다른 chaincode를 올림으로서 테스트해보실 수 있습니다.

이 지점 이후로 Chaincode 컨테이너로 접근 가능하실 것 입니다.

Chaincode 암호화

특정 시나리오에서는 전체 또는 부분적으로 키와 연관된 값을 암호화하는 것이 유용 할 수 있습니다. 예를 들어 개인의 주민등록번호 또는 주소가 원장에게 쓰여진 경우에 데이터가 일반 텍스트로 나타나지 않게 할 수 있습니다. 시리얼 코드 암호화는 상품 공장과 BCCSP wrapper 와 엔티티 확장을 활용하여 암호화 및 타원 곡선형 디지털 서명과 같은 암호화 작업을 수행함으로써 수행됩니다. 예를 들어 암호화하려면 chaincode의 호출자가 transient 필드를 통해 암호화 키를 전달합니다. 그러면 동일한 키가 후속 쿼리 작업에 사용되어 암호화 된 State 값을 적절히 해독 할 수 있습니다.

자세한 정보 및 샘플 은 디렉토리 내의 Encc 예제를 참조하십시오 fabric/examplesutils.go 도우미 프로그램을 확인해보십시오. 이 유틸리티는 chaincode shim API 및 Entities 확장을 로드하고 샘플 암호화 체인 코드가 활용 하는 새로운 클래스의 기능 (예 encryptAndPutStategetStateAndDecrypt)을 빌드합니다 . 따라서 체인 코드는 및 추가 된 기능 Get과 Put 함께 추가된 기능인 Encrypt와 Decript를 포함해서 기본 shim API와 결합 할 수 있습니다.

Go언어로 씌여진 Chaincode의 외부 의존성 관리

여러분의 Chaincode가 Go에서 제공하는 라이브러리에서 제공하는 패키지가 아닌 다른 패키지를 요구할 경우에, Chaincode에 패키지를 포함하실 수 있습니다.

이러한 의존성을 관리하거나 배포할 수 있는 다양한 툴이 있습니다.

governor라는 라이브러리를 이용해서 시연을 하겠습니다.

govendor init
govendor add +external  // Add all external package, or
govendor add github.com/external/pkg // Add specific external package

이렇게 임포트한 외부 의존성 파일은 vendor 디렉토리에 보관됩니다. peer chaincode package와 peer chaincode install과 같은 명령어는 Chaincode 패키지에 의존성과 관련된 코드를 포함합니다.


출처 : http://hyperledger-fabric.readthedocs.io/en/release-1.1/chaincode4ade.html

 Chaincode란 무엇입니까?

Chaincode는 프로그램입니다. Go, node.js, 그리고 마지막엔 자바와 같은 다른 프로그래밍 언어도 지원합니다.

이러한 Chaincode는 Interface로 규정되어 실행됩니다.

Chaincode는 보안된 Docker container에 허가된 피어 프로세스와 격리되어 실행됩니다.

Chaincode는 어플리케이션에서 제출하여 트랜잭션으로 원장 State 초기화 및 관리를 합니다.

Chaincode는 전형적으로 네트워크의 구성원으로부터 동의된 비즈니스 로직을 다루고, 그래서 Smart Contract로 간주됩니다.

Chaincode에서 만들어진 State는 배타적인 Chaincode이고 다른 Chaincode와 직접적으로 액세스가 가능하지 않은 범위에서 만들어집니다.

그러나, 같은 네트워크 안에서 적절한 허가를 얻은 Chaincode는 다른 Chaincode를 불러내어 State에 접근 가능 합니다.

두 개의 페르소나들

우리는 Chaincode에 두 개의 다른 관점을 제시합니다.

하나는 Chaincode for Developers라는 이름으로 어플리케이션 관점으로부터 개발자가 블록체인 어플리케이션이나 솔루션을 개발하게합니다.

두번째는 Chaincode for Operators라는 이름으로 블록체인 네트워크를 관리하는 업무를 하는 블록체인 네트워크 오퍼레이터로써의 역할을 지향합니다.

그리고 오퍼레이터로서 Hyperledger Fabric API를 설치하고, 인스턴스화 하고, Chaincode를 업그레이드 합니다. 그러나 Chaincode 어플리케이션 개발로서는 포함되지 않습니다.


출처 : http://hyperledger-fabric.readthedocs.io/en/release-1.1/chaincode.html

Upgrading Your Network Components(네트워크 구성 요소 업그레이드)

[Note]
이 문서에서 "업그레이드"라는 용어를 사용할 때는 주로 구성 요소의 버전을 변경하는 것을 말합니다 (예 : v1.0.x 바이너리에서 v1.1 바이너리로 변경). 반면에 "업데이트"라는 용어는 버전이 아니라 채널 구성 또는 배포 스크립트 업데이트와 같은 구성 변경을 의미합니다.

Overview

첫 번째 네트워크 빌드 (BYFN) 자습서는 기본적으로 "최신"바이너리로 기본 설정되어 있기 때문에 v1.1 릴리스 이후에 실행 한 경우 시스템에 v1.1 바이너리와 도구가 설치되어 사용자가 그들을 업그레이 드하십시오.

결과적으로이 튜토리얼에서는 Hyperledger Fabric v1.0.6 바이너리와 업그레이드 할 v1.1 바이너리를 기반으로 한 네트워크를 제공합니다. 또한 기능 요구 사항을 파악하기 위해 채널 구성을 업데이트하는 방법을 보여줍니다.

그러나 BYFN은 다음 구성 요소를 지원하지 않으므로 BYFN 업그레이드 스크립트에서 해당 구성 요소를 다루지 않습니다.

  • Fabric-CA
  • Kafka
  • SDK

이러한 구성 요소를 업그레이드하는 프로세스는 자습서 다음 섹션에서 다룹니다.

높은 수준에서 업그레이드 가이드는 다음 단계를 수행합니다.

  1. 원장과 MSP를 백업하십시오.
  2. Orderer 바이너리를 Fabric v1.1로 업그레이드하십시오.
  3. 피어 바이너리를 Fabric v1.1로 업그레이드하십시오.
  4. v1.1 채널 기능 요구 사항을 사용합니다.
[Note]
프로덕션 환경에서는 orderer 및 peer를 동시에 업그레이드 할 수 있습니다. 즉, peer를 업그레이드하기 전에 orderer를 업그레이드 할 필요가 없습니다. 주의를 기울여야하는 곳은 능력을 발휘하는 것입니다. 모든 orderer 및 peer 는 해당 단계 전에 업그레이드해야합니다 (일부 orderer 가 기능이 활성화되었을 때 업그레이드 된 경우 치명적인 State 포크를 만들 수 있음).

이 자습서에서는 CLI 명령을 사용하여 각 단계를 개별적으로 수행하는 방법을 보여줍니다.

prerequisites(전제 조건)

아직 수행하지 않은 경우, 전제 조건에서 설명한대로 시스템에 모든 종속성이 있는지 확인하십시오.

Launch a v1.0.6 Network(v1.0.6 네트워크 시작)

먼저, Fabric v1.0.6 이미지를 실행하는 기본 네트워크를 프로비저닝합니다. 이 네트워크는 2 개의 피어 노드를 유지 관리하는 두 개의 조직과 "솔로" Ordering Service로 구성됩니다.

로컬 fabric-samples.의 first-network 하위 디렉토리에서 작업 할 것입니다. 지금 해당 디렉토리로 변경하십시오. 또한 사용하기 쉽도록 몇 개의 여분의 터미널을 열고 싶을 것입니다.

Clean up

우리는 알려진 State에서 작업하기를 원하므로  byfn.sh 스크립트를 사용하여 처음에는 정리를합니다. 이 명령은 활성 또는 비활성 도커 컨테이너를 제거하고 이전에 생성 된 아티팩트를 제거합니다. 다음 명령을 실행하십시오.

./byfn.sh -m down

Generate the Crypto and Bring Up the Network(암호화 생성 및 네트워크 활성화)

새로운 환경에서 다음 네 가지 명령을 사용하여 v1.0.6 BYFN 네트워크를 시작하십시오.

git fetch origin

git checkout v1.0.6

./byfn.sh -m generate

./byfn.sh -m up -t 3000 -i 1.0.6

BYFN이 제대로 시작되면 다음과 같이 표시됩니다.

===================== All GOOD, BYFN execution completed =====================

이제 네트워크를 Hyperledger Fabric v1.1로 업그레이드 할 준비가되었습니다.

Get the newest samples(최신 샘플 가져오기)

[Note]
아래 지침은 1.1.0-rc1부터 시작하여 v1.1.x의 가장 최근에 게시 된 버전과 관련이 있습니다. '1.1.x'는 테스트중인 게시 된 릴리스의 버전 식별자로 대체하십시오. 'v1.1.x'를 'v1.1.0'으로 바꾸십시오.

나머지 튜토리얼을 끝내기 전에 v1.1.x 버전의 샘플을 얻는 것이 중요합니다. 다음과 같이 하면 됩니다.

git fetch origin

git checkout v1.1.x

Want to upgrade now?(지금 업그레이드 하시겠습니까?)

BYFN의 모든 구성 요소를 업그레이드하고 기능을 활성화하는 스크립트가 있습니다. 그런 다음 스크립트의 단계를 수행하고 업그레이드 프로세스에서 각 코드가 수행하는 작업을 설명합니다.

스크립트를 실행하려면 다음 명령을 실행하십시오.

# Note, replace '1.1.x' with a specific version, for example '1.1.0'.
# Don't pass the image flag '-i 1.1.x' if you prefer to default to 'latest' images.
# '1.1.x'를 특정 버전으로 바꾸십시오 (예 : '1.1.0').
# 이미지 플래그 '-i 1.1.x'를 지나치지 마십시오. 'latest'이미지를 기본값으로 사용하는 것이 좋습니다.

./byfn.sh upgrade -i 1.1.x

업그레이드가 성공하면 다음이 표시됩니다.

===================== All GOOD, End-2-End UPGRADE Scenario execution completed =====================

네트워크를 수동으로 업그레이드하려면  ./byfn.sh -m down을 다시 실행하고 – ./byfn.sh upgrade -i 1.1.x까지의 단계를 수행하십시오. 그런 다음 다음 섹션으로 진행하십시오.

[Note]
이 섹션에서 실행하는 명령 중 많은 부분이 출력되지 않습니다. 일반적으로 출력이 좋은 출력이 없다고 가정합니다.

Upgrade the Orderer Containers(Orderer 컨테이너 업그레이드)

[Note]
귀하의 Orderer 업그레이드에 관심을 기울이십시오. 그들이 정확하게 완료되지 않은 경우 - 특히 일부 Orderer 만 업그레이드하고 다른 사용자는 업그레이드하지 않은 경우 - 주 fork 가 만들어 질 수 있습니다 (즉, 원장이 더 이상 일관성이 없음). 이것은 반드시 피해야합니다.

Orderer  컨테이너는 롤링 방식으로 업그레이드해야 합니다 (한 번에 하나씩). 높은 수준에서 Orderer 업그레이드 프로세스는 다음과 같이 진행됩니다.

1. Orderer를 중지 시키십시오.

2. Orderer의 원장과 MSP를 백업하십시오.

3. 최신 이미지로 Orderer를 다시 시작하십시오.

4. 업그레이드가 완료되었는지 확인하십시오.

BYFN을 활용 한 결과, 우리는 솔로 Orderer 설정을 가지므로,이 과정은 한 번만 수행 할 것입니다. 그러나 Kafka 설정에서이 프로세스는 각 Orderer에 대해 수행되어야합니다.

[Note]
이 튜토리얼에서는 docker 배포를 사용합니다. 원시 배치(native deployments)의 경우, 파일 순서대로 파일을 릴리스 아티팩트의 파일로 대체하십시오. orderer.yaml을 i 업하고 릴리스 아티팩트의 orderer.yaml 파일로 YY십시오. 그런 다음 수정 된 변수를 백업 된 orderer.yaml에서 새 변수로 이식합니다. diff와 같은 유틸리티를 사용하면 도움이 될 수 있습니다. 혼란을 줄이기 위해 General.TLS.ClientAuthRequired 변수가 General.TLS.ClientAuthEnabled로 변경되었습니다 (피어 구성에서 지정한 것처럼). 이 변수의 이전 이름이 여전히 orderer.yaml 파일에 존재하면, 새  orderer 2 진이 시작되지 않습니다.

Orderer 아래로 내림으로써 업그레이드 프로세스를 시작합시다.

docker stop orderer.example.com

export LEDGERS_BACKUP=./ledgers-backup

# Note, replace '1.1.x' with a specific version, for example '1.1.0'.
# Set IMAGE_TAG to 'latest' if you prefer to default to the images tagged 'latest' on your system.
# '1.1.x'를 특정 버전으로 바꾸십시오 (예 : '1.1.0').
# 시스템에서 '최신'태그가 붙은 이미지를 기본값으로 사용하려면 IMAGE_TAG를 'latest'로 설정하십시오.

export IMAGE_TAG=`uname -m`-1.1.x

파일 백업을 넣을 디렉토리 변수를 만들었으며 이동하려는  IMAGE_TAG을 내 보냈습니다.

orderer 가 내려 가면 원장과 MSP를 백업 할 수 있습니다.

mkdir -p $LEDGERS_BACKUP

docker cp orderer.example.com:/var/hyperledger/production/orderer/ ./$LEDGERS_BACKUP/orderer.example.com

생산 네트워크( production network)에서 이 프로세스는 각 Kafka 기반의 Orderer에 대해 롤링 방식으로 반복됩니다.

이제 우리의 새로운 패브릭 이미지로 orderer 를 다운로드하고 다시 시작하십시오.

docker-compose -f docker-compose-cli.yaml up -d --no-deps orderer.example.com

이 샘플에서는 "solo" Ordering Service를 사용하기 때문에 네트워크에 다시 Order한 Orderer가 동기화해야하는 다른 Orderer가 없습니다. 그러나 Kafka를 활용 한 프로덕션 네트워크에서는 다른 Orderer를 따라 잡았는지 확인하기 위해 Orderer를 다시 시작한 후  peer channel fetch <blocknumber>를 실행하는 것이 좋습니다.

Upgrade the Peer Containers(피어 컨테이너 업그레이드)

다음으로, 피어 컨테이너를 Fabric v1.1로 업그레이드하는 방법을 살펴 보겠습니다. 피어 컨테이너는 orderer처럼 롤링 방식으로 업그레이드 해야 합니다 (한 번에 하나씩). orderer 업그레이드 중에 언급 한 바와 같이 orderer 및 피어는 동시에 업그레이드 할 수 있지만이 자습서에서는 프로세스를 분리했습니다. 높은 수준에서 다음 단계를 수행합니다.

  1. 피어를 중지하십시오.
  2. 피어의 원장과 MSP를 백업하십시오.
  3. 체인 코드 컨테이너 및 이미지를 제거하십시오.
  4. 최신 이미지로 피어를 다시 시작하십시오.
  5. 업그레이드가 완료되었는지 확인하십시오.

우리는 우리 네트워크에서 4 명의 동료를 운영합니다. 각 피어에 대해이 프로세스를 한 번 수행하여 총 4 개의 업그레이드를 수행합니다.

[Note]
다시 말하면,이 튜토리얼은 도커 배치를 사용합니다. 원시 배치(native deployments)의 경우, 파일 피어를 릴리스 아티팩트의 파일 피어로 바꾸십시오. core.yaml을 백업하고 릴리스 아티팩트의 파일로 바꾸십시오. 백업 된 core.yaml에서 수정 된 변수를 새 포트로 이식합니다. diff와 같은 유틸리티를 사용하면 도움이 될 수 있습니다.

다음 명령을 사용하여 첫 번째 피어 를 가져와 봅시다.

export PEER=peer0.org1.example.com

docker stop $PEER

그런 다음 피어의 원장과 MSP 를 백업 할 수 있습니다 .

mkdir -p $LEDGERS_BACKUP

docker cp $PEER:/var/hyperledger/production ./$LEDGERS_BACKUP/$PEER

피어가 중지되고 원장이 백업 된 State에서 피어 체인 코드 컨테이너를 제거합니다.

CC_CONTAINERS=$(docker ps | grep dev-$PEER | awk '{print $1}')
if [ -n "$CC_CONTAINERS" ] ; then docker rm -f $CC_CONTAINERS ; fi

그리고 피어 체인 코드 이미지 :

CC_IMAGES=$(docker images | grep dev-$PEER | awk '{print $1}')
if [ -n "$CC_IMAGES" ] ; then docker rmi -f $CC_IMAGES ; fi

이제 v1.1 이미지 태그를 사용하여 피어를 다시 시작합니다.

docker-compose -f docker-compose-cli.yaml up -d --no-deps $PEER

튜토리얼 후에 CouchDB를 업데이트하는 방법에 대해 더 자세하게 이야기 할 것입니다.

Verify Upgrade Completion(업그레이드 완료 확인)

우리는 첫 번째 피어의 업그레이드를 완료했지만 계속하기 전에 체인 코드 호출로 업그레이드가 제대로 완료되었는지 확인합니다. 다음 명령을 사용하여  a에서b 로  10을 이동합시다.

docker-compose -f docker-compose-cli.yaml up -d --no-deps cli

docker exec -it cli bash

peer chaincode invoke -o orderer.example.com:7050  --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem  -C mychannel -n mycc -c '{"Args":["invoke","a","b","10"]}'

우리의 쿼리는 초기에  a가  90이라는 값을 가지고 있고 우리는 호출을 사용하여  10을 제거했습니다. 따라서 a에 대한 질의는  80을 나타내야합니다.

peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'

우리는 다음을보아야합니다.

Query Result: 80

피어가 올바르게 업그레이드되었는지 확인한 후 피어를 계속 업그레이드하기 전에 이탈을 실행하여 컨테이너에서 나가십시오. 다른 피어 이름을 내 보낸 위의 프로세스를 반복하면이 작업을 수행 할 수 있습니다.

export PEER=peer1.org1.example.com
export PEER=peer0.org2.example.com
export PEER=peer1.org2.example.com

Enable Capabilities for the Channels(채널 기능 활성화)

v1.0.x 패브릭 바이너리는 채널 기능의 개념을 이해할 수 없으므로 처음에는 채널에 기능을 사용할 때 특별히 주의해야합니다.

패브릭 바이너리는 롤링 방식으로 업그레이드 할 수 있고 업그레이드 해야 하지만 ordering admin 는 모든 order 바이너리가 v1.1.x 이상이 될 때까지 v1.1 기능을 사용하지 않도록하는 것이 중요합니다. 어떤 orderer 가 v1.0.x 코드를 실행 중이고 채널에 대한 기능을 사용할 수있는 경우 v1.0.x orderer가 변경을 무효화하고 v1.1.x + orderer가 이를 승인하면 블록 체인이 포크를합니다. 이것은 v1.0에서 v1.1 로의 업그레이드에 대한 예외입니다. v1.1에서 v1.2와 같은 향후 업그레이드의 경우 orderer 네트워크가 업그레이드를보다 정상적으로 처리하고 State 포크를 방지합니다.

포크 가능성을 최소화하기 위해 orderer v1.1 기능을 사용하기 전에 응용 프로그램 또는 채널 v1.1 기능을 사용하려는 시도가 거부됩니다. orderer가 v1.1 기능을 사용할 수있게하는 것은 ordering admin 만 가능하기 때문에 다른 기능의 필수 조건으로 설정하면 ordering admin가 지원할 준비가 되기 전에 응용 프로그램 관리자가 실수로 기능을 사용하는 것을 방지 할 수 있습니다.

[Note]
기능을 사용하도록 설정 한 후에는 기능을 사용하지 않도록 설정하거나 권장하지 않습니다.

기능을 사용하도록 설정하면 해당 채널의 영구 기록의 일부가됩니다. 즉, 기능을 사용하지 않도록 설정 한 후에도 오래된 바이너리는 채널을 사용할 수없는 블록으로 이동할 수있는 블록을 처리 할 수 없으므로 채널에 참여할 수 없습니다.

이러한 이유로 채널 기능을 아무런 수익이 없는 지점으로 사용할 수 있다고 생각하십시오. 테스트 환경에서 새로운 기능을 시험하고 프로덕션 환경에서 사용할 수있게하기 전에 자신감을 가져보십시오.

v1.0.0 피어가 결합 된 채널에서 기능 요구 사항을 활성화하면 피어가 충돌하게됩니다. 이 충돌하는 동작은 의도하지 않은 잘못된 구성 State를 나타내므로 의도적 인 동작입니다.

실패한 v1.0.x 피어에서 표시되는 오류 메시지는 다음과 같습니다.

Cannot commit block to the ledger due to Error validating config which passed
initial validity checks: ConfigEnvelope LastUpdate did not produce the supplied
config result

초기 유효성 검사를 통과 한 구성의 유효성을 검사하는 구성 오류로 인해 원장에게 블록을 적용 할 수 없음 : ConfigEnvelope LastUpdate가 제공된 구성 결과를 생성하지 않았습니다.

우리는 다음 순서대로 기능을 활성화 할 것입니다.

  1. Orderer System Channel
    1. Orderer Group
    2. Channel Group
  2. Individual Channels
    1. Orderer Group
    2. Channel Group
    3. Application Group
[Note]
포크 (fork)의 가능성을 최소화하기 위해서는 먼저 orderer system  기능을 활성화 한 다음 개별 채널 기능을 활성화하는 것이 가장 좋습니다.

각 그룹에 대해 다음 순서로 기능을 활성화합니다.

  1. 최신 채널 설정 가져 오기
  2. 수정 된 채널 구성 만들기
  3. 구성 업데이트 트랜잭션 만들기
[Note]
이 프로세스는 일련의 구성 업데이트 트랜잭션 (각 채널 그룹당 하나씩)을 통해 수행됩니다. 실제 제작 네트워크에서 이러한 채널 구성 업데이트는 각 채널의 관리자가 처리합니다. BYFN은 모두 단일 시스템에 있기 때문에 이러한 각 채널을 업데이트 할 수 있습니다.

채널 구성을 업데이트하는 방법에 대한 자세한 내용은 채널에 조직 추가 또는 채널 구성 업데이트의 문서를 클릭하십시오.

docker exec -it cli bash를 다시 발행하여  cli컨테이너로 돌아가십시오.

이제 다음과 같이 설정된 환경 변수를 확인해 봅시다.

env|grep PEER

또한 jq를 설치해야합니다.

apt-get update

apt-get install -y jq

Orderer System Channel Capabilities(Orderer 시스템 채널 기능)

orderer  시스템 채널에 대한 환경 변수를 설정합시다. 다음 명령을 각각 발행하십시오.

CORE_PEER_LOCALMSPID="OrdererMSP"

CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/users/Admin@example.com/msp

ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

채널 이름을 testchainid다음 과 같이 설정해 보겠습니다 .

CH_NAME=testchainid

Orderer Group(Orderer 그룹)

채널 구성을 업데이트하는 첫 번째 단계는 최신 구성 블록을 얻는 것입니다.

peer channel fetch config config_block.pb -o orderer.example.com:7050 -c $CH_NAME  --tls --cafile $ORDERER_CA

config를 쉽게 편집 할 수 있도록 configtxlator를 사용하여 config 블록을 JSON으로 변환 해 봅시다.

configtxlator proto_decode --input config_block.pb --type common.Block --output config_block.json

이 명령은 jq 를 사용하여 config에서 헤더, 메타 데이터 및 시그니처를 제거합니다.

jq .data.data[0].payload.data.config config_block.json > config.json

그런 다음 orderer group에 기능을 추가하십시오. 다음 명령은 구성 파일의 복사본을 만들고 여기에 새로운 기능을 추가합니다.

jq -s '.[0] * {"channel_group":{"groups":{"Orderer": {"values": {"Capabilities": .[1]}}}}}' config.json ./scripts/capabilities.json > modified_config.json

우리가 여기에서 변화하고있는 것에 주목하십시오.  Capabilities은 channel_group아래의  orderer 그룹의  value로 추가되고 있습니다. 우리가 작업하고있는 특정 채널은이 명령에 명시되어 있지 않지만, 그것이 Orderer 시스템 채널 testchainid라는 것을 기억하십시오. 새 채널을 만들 때 기본적으로 복사 될이 채널의 구성이기 때문에 먼저 업데이트해야합니다.

이제 config 업데이트를 만들 수 있습니다.

configtxlator proto_encode --input config.json --type common.Config --output config.pb

configtxlator proto_encode --input modified_config.json --type common.Config --output modified_config.pb

configtxlator compute_update --channel_id $CH_NAME --original config.pb --updated modified_config.pb --output config_update.pb

구성 업데이트를 트랜잭션으로 패키지화하십시오.

configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate --output config_update.json

echo '{"payload":{"header":{"channel_header":{"channel_id":"'$CH_NAME'", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' | jq . > config_update_in_envelope.json

configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope --output config_update_in_envelope.pb

구성 업데이트 트랜잭션 제출 :

[Note]
이 다음 단계에서는 아래의 명령은 트랜잭션을 서명하고 ordering service에 제출합니다.

우리의 구성 업데이트 트랜잭션은 원래 구성과 수정 된 구성 간의 차이를 나타내지 만, Orderer는 이것을 전체 채널 구성으로 변환합니다.

Channel Group(채널 그룹)

이제 orderer system 수준에서 채널 그룹에 대한 기능을 활성화하는 단계로 넘어 갑니 다.

이전과 마찬가지로 첫 번째 단계는 최신 채널 구성을 얻는 것입니다.

[Note]
이 다음 단계에서는 이 명령 세트는 orderer 그룹의 단계와 완전히 동일합니다.

다음으로 수정 된 채널 구성을 만듭니다.

jq -s '.[0] * {"channel_group":{"values": {"Capabilities": .[1]}}}' config.json ./scripts/capabilities.json > modified_config.json

우리가 여기서 바뀌고있는 것에 주목하십시오 : Capabilities은 최상위 channel_group 의 value 으로 추가됩니다 (이전처럼 testchainid  채널에서).

구성 업데이트 트랜잭션을 만듭니다.

[Note]
이 명령 세트는 orderer 그룹의 세 번째 단계와 완전히 동일합니다.

구성 업데이트를 트랜잭션으로 패키지화하십시오.

configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate --output config_update.json

echo '{"payload":{"header":{"channel_header":{"channel_id":"'$CH_NAME'", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' | jq . > config_update_in_envelope.json

configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope --output config_update_in_envelope.pb

구성 업데이트 트랜잭션 제출 :

peer channel update -f config_update_in_envelope.pb -c $CH_NAME -o orderer.example.com:7050 --tls true --cafile $ORDERER_CA

Enabling Capabilities on Existing Channels(기존 채널에서 기능 활성화)

채널 이름을 mychannel다음으로 설정하십시오 .

CH_NAME=mychannel

Orderer Group(Orderer 그룹)

채널 설정 가져 오기 :

peer channel fetch config config_block.pb -o orderer.example.com:7050 -c $CH_NAME  --tls --cafile $ORDERER_CA

configtxlator proto_decode --input config_block.pb --type common.Block --output config_block.json

jq .data.data[0].payload.data.config config_block.json > config.json

Orderer 그룹에 기능을 추가해 보겠습니다. 다음 명령은 구성 파일의 복사본을 만들고 여기에 새로운 기능을 추가합니다.

jq -s '.[0] * {"channel_group":{"groups":{"Orderer": {"values": {"Capabilities": .[1]}}}}}' config.json ./scripts/capabilities.json > modified_config.json

우리가 여기에서 변화하고있는 것에 주목하십시오.  Capabilities은  channel_group 아래의  orderer 그룹의  value로 추가되고 있습니다. 이것은 정확히 우리가 이전에 변경 한 것인데, 지금은  testchainid 대신 채널  mychannel에 config를 사용하고 있습니다.

구성 업데이트 만들기 :

configtxlator proto_encode --input config.json --type common.Config --output config.pb

configtxlator proto_encode --input modified_config.json --type common.Config --output modified_config.pb

configtxlator compute_update --channel_id $CH_NAME --original config.pb --updated modified_config.pb --output config_update.pb

구성 업데이트를 트랜잭션으로 패키지화하십시오.

configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate --output config_update.json

echo '{"payload":{"header":{"channel_header":{"channel_id":"'$CH_NAME'", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' | jq . > config_update_in_envelope.json

configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope --output config_update_in_envelope.pb

구성 업데이트 트랜잭션 제출 :

peer channel update -f config_update_in_envelope.pb -c $CH_NAME -o orderer.example.com:7050 --tls true --cafile $ORDERER_CA

Channel Group(채널 그룹)

[Note]
이 명령 세트는 orderer 반복되는 것처럼 보일 수 있지만, 우리는 다른 그룹에서 동일한 프로세스를 수행하고 있음을 기억하십시오. 앞에서 말했듯이 프로덕션 네트워크에서 이 프로세스는 여러 채널 관리자간에 분열 될 수 있습니다. 세 번째 단계와 완전히 동일합니다.

설정 가져 오기, 디코딩 및 범위 지정 :

peer channel fetch config config_block.pb -o orderer.example.com:7050 -c $CH_NAME --tls --cafile $ORDERER_CA

configtxlator proto_decode --input config_block.pb --type common.Block --output config_block.json

jq .data.data[0].payload.data.config config_block.json > config.json

수정 된 구성 만들기 :

jq -s '.[0] * {"channel_group":{"values": {"Capabilities": .[1]}}}' config.json ./scripts/capabilities.json > modified_config.json

우리가 여기서 바뀌고 있는 것에 주목하십시오.  Capabilities은 최상위 channel_group  (이전처럼  mychannel에서)의  value으로 추가됩니다.

구성 업데이트 만들기 :

configtxlator proto_encode --input config.json --type common.Config --output config.pb

configtxlator proto_encode --input modified_config.json --type common.Config --output modified_config.pb

configtxlator compute_update --channel_id $CH_NAME --original config.pb --updated modified_config.pb --output config_update.pb

구성 업데이트를 트랜잭션으로 패키지화하십시오.

configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate --output config_update.json

echo '{"payload":{"header":{"channel_header":{"channel_id":"'$CH_NAME'", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' | jq . > config_update_in_envelope.json

configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope --output config_update_in_envelope.pb

channel그룹 의 구성을 업데이트하기 때문에 관련 조직 (Org1, Org2 및 OrdererOrg)이 서명해야합니다. 이 작업은 일반적으로 개별 조직 관리자가 수행하지만, BYFN에서는 앞서 말했듯이 이 작업이 우리에게 위임됩니다.

먼저 Org1로 전환하고 업데이트에 서명하십시오.

CORE_PEER_LOCALMSPID="Org1MSP"

CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt

CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp

CORE_PEER_ADDRESS=peer0.org1.example.com:7051

peer channel signconfigtx -f config_update_in_envelope.pb

그리고 Org2와 동일하게하십시오 :

CORE_PEER_LOCALMSPID="Org2MSP"

CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt

CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp

CORE_PEER_ADDRESS=peer0.org1.example.com:7051

peer channel signconfigtx -f config_update_in_envelope.pb

그리고 OrdererOrg :

CORE_PEER_LOCALMSPID="OrdererMSP"

CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/users/Admin@example.com/msp

peer channel update -f config_update_in_envelope.pb -c $CH_NAME -o orderer.example.com:7050 --tls true --cafile $ORDERER_CA

Application Group(응용 프로그램 그룹)

응용 프로그램 그룹의 경우 환경 변수를 하나의 조직으로 재설정해야합니다.

CORE_PEER_LOCALMSPID="Org1MSP"

CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt

CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp

CORE_PEER_ADDRESS=peer0.org1.example.com:7051

이제 최신 채널 구성을 가져 오십시오 (이 프로세스는 지금까지 매우 친숙해야합니다).

peer channel fetch config config_block.pb -o orderer.example.com:7050 -c $CH_NAME --tls --cafile $ORDERER_CA

configtxlator proto_decode --input config_block.pb --type common.Block --output config_block.json

jq .data.data[0].payload.data.config config_block.json > config.json

수정 된 채널 구성 만들기 :

jq -s '.[0] * {"channel_group":{"groups":{"Application": {"values": {"Capabilities": .[1]}}}}}' config.json ./scripts/capabilities.json > modified_config.json

우리가 여기서 바뀌고 있는 것에 주목하십시오.  Capabilities은 최상위 channel_group  (이전처럼  mychannel에서)의  value으로 추가됩니다.

구성 업데이트 트랜잭션 만들기 :

configtxlator proto_encode --input config.json --type common.Config --output config.pb

configtxlator proto_encode --input modified_config.json --type common.Config --output modified_config.pb

configtxlator compute_update --channel_id $CH_NAME --original config.pb --updated modified_config.pb --output config_update.pb

구성 업데이트를 트랜잭션으로 패키지화하십시오.

configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate --output config_update.json

echo '{"payload":{"header":{"channel_header":{"channel_id":"'$CH_NAME'", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' | jq . > config_update_in_envelope.json

configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope --output config_update_in_envelope.pb

Org1이 트랜잭션을 서명합니다.

peer channel signconfigtx -f config_update_in_envelope.pb

환경 변수를 Org2로 설정하십시오.

export CORE_PEER_LOCALMSPID="Org2MSP"

export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt

export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp

export CORE_PEER_ADDRESS=peer0.org2.example.com:7051

Org2는 설정 업데이트 트랜잭션을 서명과 함께 제출합니다.

peer channel update -f config_update_in_envelope.pb -c $CH_NAME -o orderer.example.com:7050 --tls true --cafile $ORDERER_CA

축하! 이제 모든 채널에서 기능을 사용할 수 있습니다.

Verify that Capabilities are Enabled(기능이 활성화되어 있는지 확인)

그러나 이전과 같이  10을  a에서  b로 이동하여 테스트 해 봅시다.

peer chaincode invoke -o orderer.example.com:7050  --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem  -C mychannel -n mycc -c '{"Args":["invoke","a","b","10"]}'

그런 다음  a의 값을 조회하면  70이라는 값이 나타납니다.

peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'

우리는 다음을보아야합니다.

어떤 경우 우리는 모든 채널에 기능을 성공적으로 추가했습니다.

Upgrading Components BYFN Does Not Support(BYFN이 지원하지 않는 구성 요소 업그레이드)

이것이 업데이트 자습서의 끝 부분이지만 BYFN 샘플에서 지원하지 않는 프로덕션 네트워크에있는 다른 구성 요소가 있습니다. 이 섹션에서는 업데이트 프로세스에 대해 설명하겠습니다.

Fabric CA Container(패브릭 CA 컨테이너)

Fabric CA 서버를 업그레이드하는 방법을 배우려면 CA 문서 를 클릭하십시오 .

Upgrade Node SDK Clients(Node SDK 클라이언트 업그레이드)

[Note]
노드 SDK 클라이언트를 업그레이드하기 전에 패브릭 CA를 업그레이드하십시오.

NPM을 사용하여 응용 프로그램의 루트 디렉토리에서 다음 명령을 실행하여  Node.js클라이언트를 업그레이드하십시오.

이 명령은 Fabric 클라이언트와 Fabric-CA 클라이언트의 새 버전을 설치하고 새 버전을 작성합니다 package.json.

Upgrading the Kafka Cluster(카프카 클러스터 업그레이드)

반드시 필요한 것은 아니지만 Kafka 클러스터를 나머지 Fabric과 함께 업그레이드하고 최신 State로 유지하는 것이 좋습니다. Kafka의 최신 버전은 이전 버전의 프로토콜을 지원하므로 나머지 Fabric 이전 또는 이후에 Kafka를 업그레이드 할 수 있습니다.

Kafka 클러스터가 Kafka v0.11.0보다 오래된 경우 충돌 복구를보다 잘 처리하기 위해 복제를 강화하므로이 업그레이드가 특히 권장됩니다.

Kafka 클러스터 브로커를 업그레이드하기 위해 이전 버전에서 Kafka를 업그레이드하는 공식 Apache Kafka 문서를 참조하십시오.

Orderer가 Kafka 브로커 버전보다 오래된 Kafka 프로토콜 버전을 사용하도록 구성된 경우 Kafka 클러스터가 성능에 부정적인 영향을 줄 수 있습니다. Kafka 프로토콜 버전은orderer.yaml 파일의  Kafka.Version 키 또는 Docker 배포의 ORDERER_KAFKA_VERSION 환경 변수를 사용하여 설정됩니다. Fabric v1.0은 카프카 버전 0.9.0.1이 포함 된 샘플 카프카 도커 이미지를 제공했습니다. Fabric v1.1은 Kafka 버전 v1.0.0이 포함 된 샘플 Kafka 도커 이미지를 제공합니다.

[Note] 이전에 설정하지 않은 경우에도 Kafka 클러스터 버전과 일치하도록 Orderer가 사용하는 Kafka 프로토콜 버전을 구성해야합니다. 예를 들어 Fabric v1.0.x와 함께 제공되는 샘플 Kafka 이미지를 사용하는 경우 ORDERER_KAFKA_VERSION 환경 변수를 설정하거나 orderer.yaml의 Kafka.Version 키를 0.9.0.1로 설정하십시오. Kafka 클러스터 버전에 대해 잘 모르는 경우 최대 호환을 위해 Orderer의 Kafka 프로토콜 버전을 0.9.0.1로 구성하고 이후 Kafka 클러스터 버전을 결정한 후 설정을 업데이트 할 수 있습니다.

Upgrading Zookeeper(Zookeeper 업그레이드)

Apache Kafka 클러스터에는 Apache Zookeeper 클러스터가 필요합니다. Zookeeper API는 오래 동안 안정되어 있었으며, 거의 모든 Zookeeper 버전이 Kafka에서 용인되었습니다. Zookeeper의 특정 버전으로 업그레이드하는 특정 요구 사항이있는 경우 Apache Kafka 업그레이드 설명서를 참조하십시오. Zookeeper 클러스터를 업그레이드하려면 Zookeeper 클러스터 업그레이드에 대한 정보를 Zookeeper FAQ에서 찾으실 수 있습니다.

Upgrading CouchDB(CouchDB 업그레이드)

CouchDB를 State 데이터베이스로 사용하는 경우, 피어가 업그레이드되는 것과 동시에 피어의 CouchDB를 업그레이드하십시오. CouchDB를 업그레이드하려면 다음을 수행하십시오.

  1. CouchDB를 중지하십시오.
  2. CouchDB 데이터 디렉토리를 백업하십시오.
  3. CouchDB 데이터 디렉토리를 삭제하십시오.
  4. CouchDB v2.1.1 바이너리를 설치하거나 배치 스크립트를 업데이트하여 새로운 Docker 이미지를 사용하십시오 (CouchDB v2.1.1 사전 구성된 Docker 이미지는 Fabric v1.1과 함께 제공됨).
  5. CouchDB를 다시 시작하십시오.

CouchDB 데이터 디렉토리를 삭제하는 이유는 시작시 v1.1 피어가 블록 체인 트랜잭션에서 CouchDB State 데이터베이스를 재구성하기 때문입니다. v1.1부터는 각 channel_chaincode 조합에 대한 내부 CouchDB 데이터베이스가 있습니다 (피어가 조인 한 각 채널에서 인스턴스화 된 각 체인 코드 용).

Upgrade Chaincodes With Vendored Shim(벤더 된 심으로 체인 코드 업그레이드)

벤더에 체인 코드 심을 제공 할 수있는 여러 가지 타사 도구가 있습니다. 이 도구 중 하나를 사용한 경우 동일한 도구를 사용하여 벤더링을 업데이트하고 체인 코드를 다시 패키징하십시오.

체인 코드가 shim을 공급하는 경우 shim 버전을 업데이트 한 후에는 이미 체인 코드가있는 모든 피어에 설치해야합니다. 같은 이름이지만 새로운 버전으로 설치하십시오. 그런 다음이 체인 코드가 배포 된 각 채널에서 새 버전으로 이동하기 위해 체인 코드 업그레이드를 실행해야합니다.

체인 코드를 판매하지 않은 경우이 단계를 완전히 건너 뛸 수 있습니다.


출처 : http://hyperledger-fabric.readthedocs.io/en/release-1.1/upgrading_your_network_tutorial.html

Hyperledger Fabric 모든 기능

Hyperbelger Fabric은 엔터프라이즈급 네트워크 보안, 확장성, 기밀성 및 성능을 제공하는 모듈형 블록체인 아키텍처 기반의 DLT (distributed ledger technology)의 구현체입니다
Hyperledger Fabric은 아래의 블록체인 네트워크 기능들을 제공합니다.




유저 식별 관리

허가형 네트워크 사용을 위해, Hyperledger Fabric는 네트워크 상의 모든 참여자들의 User ID와 인증을 관리하기 위해 Membership Identity Service를 제공합니다.

특정 네트워크 운영의 인가(authorization)을 통해 Access Control List는 허가 계층을 추가하여 사용할 수 있다.

(원문 : Access control lists can be used to provide additional layers of permission through authorization of specific network operations.)

예를 들면, 특정한 User  ID는 Chaincode 어플리케이션 구동할 수 이지만,  신규 Chaincode 설치도록 제한 할 수 있습니다.




프라이버시와 기밀성


Hyperbelger Fabric은 비즈니스 이해관계에 따라 경쟁하고,사적이고 기밀성을 요하는 트랜잭션을 요구하는 모든 그룹이 하나의 허가형 네트워크에 공존 할 수 있게합니다.

비공개(Privacy) channels은 제한된 메시지 송수신 경로(path)로서, 네트워크 멤버의 특정 하위집단(subset)을 위한 transaction의 프라이버시와 기밀성 제공하는데 사용될 수 있습니다.
Transaction, Member 및 Channel 정보를 포함한 모든 데이터는, 해당 Channel에 대해 명시적으로 액세스 권한이 부여되지 않으면 네트워크의 어떤한 Member도 볼수없고, 접근할 수 없습니다.




효율적인 프로세싱

Hyperledger Fabric은 노드 유형별로 네트워크 역할을 할당합니다 

네트워크에 동시성과 병렬성을 제공하기 위해 Transaction 실행이 Transaction 순서정렬 및 commitment 작업과 분리되어 있습니다.

ordering(순서화) 수행전 트랜잭션을 실행하면 각 피어 노드가 여러 트랜잭션을 동시에 처리 할 수 있습니다.

이 동시 실행(concurrent execution)은 각 피어의 처리 효율성을 증가시키고, ordering service에 트랜잭션 전달을 가속화합니다. 

 

네트워크에 동시성과 병렬성을 제공하기 위해서, 트랜잭션 실행이 트랜잭션 순서와 커밋으로부터 분리되도록 합니다.

트랜잭션을 실행하는 것이 동시에 다양한 트랜잭션을 각각의 피어 노드에서 순서를 만드는 것을 가능하도록 하는 것보다 선행됩니다.

이 동시성은 각각의 피어에서 프로세싱 효율성을 높혀주고, 순서를 매기는 서비스로의 전송을 가속합니다.

병렬 처리를 가능하게하는 것 외에도,업무 분장은 Transaction 실행과 Ledger 유지보수 요청으로 부터 ordering noded의 부담을 줄어들며, Peer Node도 ordering(consensus) 로부터 자유로워진다.

역할이 분기는 인증 및 인가에 필요한 처리를 제한합니다.
모든 피어 노드는 모든 ordering node를 신뢰 할 필요가 없으며, 그 반대의 경우도 동일하다.
그래서 노드의 프로세스는 다른 노드의 검증과 독립적으로 실행할 수 있습니다



 

Chaincode의 모든 기능

Chaincode 어플리케이션은 채널내 Transaction의 유형에 따라 실행될수 있는 로직을 포함하고 있습니다.

예를 들어 자산 소유권 이전을 위한 매개변수를 정의한 ChainCode는, 소유권을 이전하는 모든 Transaction이 동일한 rule 및 요구 사항을 준수하도록 보장합니다.

System Chaincode는 전체 Channel을 위한 operaing 매개변수를 정의하는 Chaincoded와 구별됩니다

life cycle 및 구성 System Channel는 channel에 대한 규칙을 정의하고, Endorsement 및 Validation System Chaincode는 Transaction의 보증(Endorsing) 과 검증에 대한 요구를 정의합니다.

 




모듈러한 디자인

Hyperledger Fabric은 네트워크 설계자 들이 기능 선택을 지원하기 위해 모듈러한 아키텍처로 구현되었습니다.

이것으로 나온 결과물이 어떤 산업이나 퍼블릭 도메인에 적용할 수 있는 전체 블록체인 아키텍쳐입니다.

이를 통해 그 네트워크가 마켓간 상호운영이나 규제, 지리적인 범위 안에서 상호 작동 가능성을 보장하게 됩니다.


출처 : https://hyperledger-fabric.readthedocs.io/en/release-1.1/functionalities.html

 

 

 

[포스팅개정]

2018.06.08 2차 번역 까칠한마녀

BFT

BFT

질문 : ordering Service 의 BFT 버전은 언제 제공 될 예정입니까? 
대답 : 날짜는 아직 미정입니다. 우리는 1.x버전에 출시하기 위해 노력하고 있습니다. Fabric에서 miner버전 업그레이드가있을 것입니다. 
       업데이트를 위해 FAB-33 을 모니터링 하세요.

출처 : http://hyperledger-fabric.readthedocs.io/en/release-1.1/

 

 

[포스팅개정]

2018.06.08 2차 번역 까칠한마녀

Kafka

카프카(Kafka)

질문 : ordering Service에서 노드를 어떻게 제거할 수 있나요?
대답 : 2단계 프로세스가 있습니다. 
1. Peer/ Clients가 연결할 수 없도록 노드의 인증서를 관련 orderer의 MSP CRL에 추가합니다.
2. TLS CRL과 같은 표준 Kafka 액세스 제어 수단 또는 방화벽 기능을 활용하여 노드가 Kafka 클러스터에 연결하지 못하게합니다.

질문 : Kafka/ZK 클러스터를 배포해본적이 없지만, Kafka 기반 Orderer 서비스를 사용하고 싶습니다. 어떻게해야합니까? 대답 : Hyperledger Fabric 문서에서는 일반적으로 독자가 Kafka 클러스터를 설정, 구성 및 관리 할 수있는 운영 지식을 가지고 있다고 가정합니다 (Caveat emptor 참조). 

그러한 전문 지식없이 진행하기를 원한다면 Kafka 기반 ordering Service를 시험하기 전에  최소한 Kafka Quickstart 가이드 의 처음 6 단계를 완료해야 합니다.

질문 : Kafka기반 Ordering service사용을 위한 네트워크를 지원하는 Docker 구성을 어디에서 찾을 수 있습니까? 대답 : CLI 예시를 활용하십시오. (https://github.com/hyperledger/fabric/blob/master/examples/e2e_cli/docker-compose-e2e.yaml)

질문 : Kafka가반 ordering service와 ZooKeeper 종속성이 있는 이유는 무엇입니까? 대답 : broker 간 조정을 위해 Kafka는 내부적으로 zookeeper를 사용합니다.

질문 : BYFN 예제를 수행하는 중에 "service unavailable"오류가 발생했습니다. 어떻게해야합니까? 대답 : ordering service 로그를 확인하십시오. "Rejecting deliver request because of consenter error"로그 메시지는 대개 Kafka 클러스터와의 연결 문제를 나타냅니다. 
Kafka 클러스터가 올바르게 설정되어 있고 ordering service node들이 접근할 수 있는지 확인하십시오.



출처 : http://hyperledger-fabric.readthedocs.io/en/release-1.1/

 

 

[포스팅개정]

2018.06.08 2차 번역 까칠한마녀

Solo

Solo

질문 : Solo를 프로덕션에서 어떻게 배포할 수 있나요? 
대답 : Solo는 프로덕션에 포함되지 않습니다. 그것은 결코 용납하지 않습니다.

출처 : http://hyperledger-fabric.readthedocs.io/en/release-1.1/

 

Endorsement

동의

endorsement 아키텍쳐:

Q. 네트워크 내부의 Peer 중 얼마나 트랜잭션을 동의해야하나요?

A. 동의 해야하는 피어의 수는 Chaincode 설치시에 설정된 Endorsement policy에 의해서 결정됩니다.

Q. 어플리케이션 클라이언트는 모든 피어와 연결되어 있어야만 하나요?

A. 클라이언트는 오직 Chaincode의 Endorsement policy에 의해 설정된 피어 수만큼만 연결될 필요가 있습니다.




출처 : http://hyperledger-fabric.readthedocs.io/en/release-1.1/

+ Recent posts