본문 바로가기

Hyperledger Fabric/Document

[HYPERLEDGER FABRIC v1.0]3. 튜토리얼(1)

 Building Your First Network(첫번째 네트워크 구축)

Install prerequisites(필수 구성 요소 설치)

cd /opt/gopath/src/github.com/hyperledger
git clone https://github.com/hyperledger/fabric-samples.git
cd fabric-samples

먼저 hyperledger fabric samples에서 다음을 다운로드 합니다.

curl -sSL https://goo.gl/iX9dek | bash

위의 curl 명령은 네트워크를 설정하고 위에 작성한 복제 된 레포에 배치해야하는 모든 플랫폼 특정 2 진 파일을 다운로드하고 추출하는 bash 스크립트를 다운로드하고 실행합니다. 4 개의 플랫폼 별 바이너리를 검색합니다.

  • cryptogen,
  • configtxgen,
  • configtxlator, 및
  • peer

bin현재 작업 디렉토리 의 서브 디렉토리에 위치시킵니다.


Want to run it now?(지금 실행하고 싶습니까?)

cd first-network
./byfn.sh -h

./byfn.sh 스크립트의 도움말 텍스트는 다음과 같습니다 .

./byfn.sh -h
용법:
   byfn.sh -m up | down | restart [-c <채널 이름>] 생성 [-t <시간 초과>]
   byfn.sh -h | --help (이 메시지를 출력하십시오)
     -m <mode> - 'up', 'down', 'restart'또는 'generate'중 하나
       - 'up'- 도커로 네트워크 구성 - 구성
       - 'down'- 도커로 네트워크 정리 - 작성
       - 'restart'- 네트워크 재시작
       - 'generate'- 필수 인증서 및 생성 창 생성
       - c <채널 이름> - 사용할 구성 이름 (기본값은 "mychannel")
       - t <timeout> - CLI 시간 종료 기간 (마이크로 초) (기본값은 10000)

일반적으로, 먼저 필요한 인증서를 생성하고
창세기 블록, 다음 네트워크를 가져와. 예 :

   byfn.sh -m generate -c <채널 이름>
   byfn.sh -m up -c <채널 이름>


Generate Network Artifacts(네트워크 아티팩트 생성)

./byfn.sh -m generate

이 첫 번째 단계는 모든 다양한 네트워크 엔터티에 대한 모든 인증서와 키, 주문 서비스를 부트 스트랩하는 데 사용되는 기원 블록 및 채널을 구성하는 데 필요한 구성 트랜잭션 모음을 생성합니다.


Bring Up the Network(네트워크 시작하기)

다음 명령을 사용하여 네트워크를 가동시킬 수 있습니다.

./byfn.sh -m up


Bring Down the Network(네트워크 다운)

마지막으로 한 번에 한 단계 씩 네트워크 설정을 탐색 할 수 있도록 모든 항목을 가져와 봅시다. 다음은 컨테이너를 죽이고, 암호 자료와 네 가지 아티팩트를 제거하고, Docker 레지스트리에서 체인 코드 이미지를 삭제합니다.

./byfn.sh -m down


Run the tools(도구 실행)

configtxgen 및 cryptogen 명령을 사용하여 수동으로 인증서/키와 다양한 구성 아티팩트를 생성 할 수 있습니다. 또는, 목표를 달성하기 위해 byfn.sh 스크립트를 적용 할 수도 있습니다.

Manually generate the artifacts(아티팩트 수동 생성)

../bin/cryptogen generate --config=./crypto-config.yaml

다음으로, 우리는 configtxgen 툴에게 인제 스트 될 필요가있는 configtx.yaml 파일을 찾을 곳을 알려줄 필요가 있습니다.

먼저, 환경 변수를 설정하여 configtx.config 파일이 configtx.yaml 구성 파일을 찾을 위치를 지정해야합니다.

export FABRIC_CFG_PATH=$PWD

그러면 우리는 orderer genesis 블록을 생성 할 configtxgen 도구를 호출 할 것입니다.

../bin/configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block

중간 인증서, 인증서 해지 목록 (crls) 및 MSP 구성과 관련된 로그 경고를 무시할 수 있습니다. 우리는이 샘플 네트워크에있는 것을 사용하지 않습니다. 다음에는 채널 트랜잭션 이슈를 생성해야합니다. 이 안내에서 사용할 수있는 환경 변수로 $CHANNEL_NAME을 (를) 바꾸거나 CHANNEL_NAME을 (를) 설정해야합니다.

export CHANNEL_NAME=mychannel

# this file contains the definitions for our sample channel
../bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME

다음으로 우리가 구성중인 채널에서 Org1의 앵커 피어를 정의합니다. 다시 말하지만 다음 명령에 대해 $ CHANNEL_NAME을 바꾸거나 환경 변수를 설정하십시오.

../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP

이제 Org2에 대한 앵커 피어를 동일한 채널에서 정의합니다.

../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP


Start the network(네트워크 시작)

도커 작성 스크립트를 활용하여 네트워크를 확대 할 것입니다. 도커 작성 파일은 이전에 다운로드 한 이미지를 참조하고 이전에 생성 된 genesis.block으로 주문자를 부트 스트랩합니다.

first-network 폴더내의 docker-compose-cli.yaml에 들어가 command 부분을 주석 처리합니다.

...
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
# command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME}; sleep $TIMEOUT'
volumes:
...

주석을 달지 않은 상태에서 그 스크립트는 네트워크가 시작될 때 모든 CLI 명령을 실행합니다. 섹션. 그러나 각 호출의 구문과 기능을 노출하기 위해 수동으로 명령을 수행하려고합니다. TIMEOUT 변수에 적당한 값(초 단위로 지정)을 전달하십시오. 그렇지 않으면 기본적으로 CLI 컨테이너가 60 초 후에 종료됩니다.

네트워크 시작 :

# 당신이 당신의 고정 표시기-작성 스크립트가있는 <your_platform> 디렉토리에 있는지 확인 
CHANNEL_NAME=$CHANNEL_NAME TIMEOUT=30 docker-compose -f docker-compose-cli.yaml up -d

네트워크의 실시간 로그를 보려면 -d플래그를 제공하지 마십시오 . 로그 스트림을 보내려면 CLI 호출을 실행하기 위해 두 번째 터미널을 열어야합니다.


Environment variables(환경변수)

peer0.org1.example.com에 대한 다음 CLI 명령이 작동하려면 아래에 나와있는 네 가지 환경 변수로 명령을 시작해야합니다. peer0.org1.example.com에 대한 이러한 변수는 CLI 컨테이너로 구워 지므로 전달하지 않고 조작 할 수 있습니다. 그러나 다른 동료 또는 주문자에게 전화를 보내려면이 값을 적절하게 제공해야합니다. docker-compose-base.yaml에서 특정 경로를 검사합니다.

first-network의 base 폴더 내의 docker-compose-base.yaml 파일에서 peer0.org1.example.com에 대한 환경변수를 다음과 같이 수정합니다.

# Environment variables for PEER0

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
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


Create & Join Channel(채널 만들기 및 가입)

docker exec 명령을 사용하여 CLI 컨테이너에 들어갑니다.

docker exec -it cli bash

성공한 경우 다음이 표시됩니다.

root@0d78bb69300d:/opt/gopath/src/github.com/hyperledger/fabric/peer#

configtxgen 도구를 사용하여 채널 구성 artifact-channel.tx를 생성했던 것을 기억하십시오. 우리는 채널 생성 요청의 일부로 이 이슈를 발주자에게 전달할 것입니다.

  • 참고 이 명령의 일부로 전달할 -- cafile 을 확인하십시오. 이것은 발주자의 루트 인증서에 대한 로컬 경로이므로 TLS 핸드 셰이크를 확인할 수 있습니다.

채널 이름을 -c 플래그로 지정하고 채널 구성 트랜잭션을 -f 플래그로 지정합니다. 이 경우에는 channel.tx이지만 다른 이름으로 구성 트랜잭션을 마운트 할 수 있습니다

export CHANNEL_NAME=mychannel

# channel.tx 파일은 CLI 컨테이너 내의 channel-artifacts 디렉토리에 마운트됩니다.
# 결과적으로 파일의 전체 경로를 전달합니다.
# TLS 핸드 셰이크를 확인하기 위해 주문자 ca-cert의 경로도 전달합니다.
# $ CHANNEL_NAME 변수를 적절히 대체해야합니다.

peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

이 명령은 채널에 참여할 때 사용하는 기원 블록 <channel-ID.block>을 반환합니다. channel.tx에 지정된 구성 정보가 들어 있습니다.

[참고] 이러한 나머지 수동 명령은 CLI 컨테이너에 남아 있습니다. peer0.org1.example.com이 아닌 다른 피어를 대상으로 할 때는 모든 명령 앞에 해당 환경 변수를 사용하는 것을 기억해야합니다.

이제 peer0.org1.example.com채널 에 참여합시다 .

# By default, this joins ``peer0.org1.example.com`` only
# the <channel-ID>.block was returned by the previous command
# peer channel join -b <channel-ID.block>
peer channel join -b mychannel.block

네 개의 환경 변수를 적절히 변경하여 다른 피어를 필요에 따라 채널에 참여시킬 수 있습니다.


Install & Instantiate(설치 및 인스턴스화)

  • 참고 기존의 단순한 체인 코드를 활용할 것입니다. 독자적인 체인 코드를 작성하는 방법을 배우려면, 개발자용 Chaincode 자습서를 참조하십시오.

응용 프로그램은 chaincode를 통해 블록 체인 원장과 상호 작용합니다. 따라서 트랜잭션을 실행하고 보증하는 모든 피어에 체인 코드를 설치한 다음 채널에서 체인 코드를 인스턴스화 해야합니다. 먼저 샘플 Go 코드를 네 개의 피어 노드 중 하나에 설치합니다. 이 명령은 피어의 파일 시스템에 소스 코드를 저장합니다.

peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02

그런 다음 채널에서 체인 코드를 인스턴스화합니다. 이렇게하면 채널에서 체인 코드가 초기화되고 체인 코드에 대한 승인 정책이 설정되며 대상 피어에 대해 체인 코드 컨테이너가 시작됩니다. -P 인수를 기록하십시오. 이것은 우리의 정책으로,이 체인 코드에 대한 트랜잭션의 유효성을 검증하는 데 필요한 보증 수준을 지정합니다. 아래 명령에서 정책을 `-P "OR ( 'Org0MSP.member', 'Org1MSP.member')`로 지정했음을 알 수 있습니다. 즉, Org1 OR Org2에 속한 동료 (즉, 단 하나의 승인)로부터 "보증"해야합니다. 구문을 `AND`로 변경하면 두 가지 보증이 필요합니다.

# $CHANNEL_NAME 환경 변수를 바꿔야합니다.(바꾸지 않을 경우 export CHANNEL_NAME=mychannel 명령을 실행하세요.) 
# mycc라는 이름으로 체인 코드를 설치하지 않았다면, 그 인수도 수정하십시오 
peer chaincode instantiate -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --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 $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "OR ('Org1MSP.member','Org2MSP.member')"

정책 구현에 대한 자세한 내용은 보증 정책 문서를 참조하십시오.


Query(쿼리)

체인 코드가 올바르게 인스턴스화되고 상태 DB가 채워 졌는지 확인하기 위해 a의 값을 쿼리합니다. 쿼리의 구문은 다음과 같습니다.

# -C 및 -n 플래그를 적절하게 설정하십시오. 
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}' 
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","b"]}'


Invoke(호출)

이제 10을 a에서 b로 이동합시다. 이 트랜잭션은 새 블록을 잘라내어 상태 DB를 업데이트합니다. 호출 구문은 다음과 같습니다.

# -C 및 -n 플래그를 적절하게 설정하십시오. 
peer chaincode invoke -o orderer.example.com:7050  --tls $CORE_PEER_TLS_ENABLED --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 $CHANNEL_NAME -n mycc -c '{"Args":["invoke","a","b","10"]}'


Query(쿼리)

우리의 이전 호출이 제대로 실행되었는지 확인합시다. 키 a를 100으로 초기화하고 이전 호출을 사용하여 10을 제거했습니다. 따라서 a에 대한 쿼리는 90을 나타내야합니다. 쿼리 구문은 다음과 같습니다.

# -C 및 -n 플래그를 적절하게 설정하십시오. 
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}' 
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","b"]}'

다음과 같은 결과가 나와야합니다.

Query Result: 90
Query Result: 210

키 값 쌍과 후속 호출을 다시 시작하고 조작하십시오.



What’s happening behind the scenes? ( 배후에서 무슨 일이 일어나고있는거야? )

[참고] 이 단계에서는 script.sh가 docker-compose-cli.yaml 파일에서 주석 처리되지 않은 시나리오를 설명합니다. ./byfn.sh -m을 사용하여 네트워크를 정리하고이 명령이 활성 상태인지 확인하십시오. 그런 다음 동일한 도커 작성 프롬프트를 사용하여 네트워크를 다시 시작하십시오.

  • 스크립트 - script.sh -는 CLI 컨테이너에서 구워집니다. 이 스크립트는 제공된 채널 이름에 대해 createChannel 명령을 실행하고 채널 구성에 channel.tx 파일을 사용합니다.
  • createChannel의 결과는 피어의 파일 시스템에 저장되고 channel.tx에서 지정된 채널 구성을 포함하는 기원 블록 (<your_channel_name> .block)입니다.
  • joinChannel 명령은 이전에 생성 된 기원 블록을 입력으로 사용하는 네 개의 모든 피어에 대해 실행됩니다. 이 명령은 피어가 <your_channel_name>에 가입하고 <your_channel_name> .block으로 시작하는 체인을 생성하도록 지시합니다.
  • 이제 우리에게는 4 명의 동료와 2 개의 조직으로 구성된 채널이 있습니다. 이것은 TwoOrgsChannel 프로필입니다.
  • peer0.org1.example.com 및 peer1.org1.example.com은 Org1에 속합니다. peer0.org2.example.com 및 peer1.org2.example.com은 Org2에 속합니다.
  • 이러한 관계는 crypto-config.yaml을 통해 정의되며 MSP 경로는 docker 작성에서 지정됩니다.
  • Org1MSP (peer0.org1.example.com) 및 Org2MSP (peer0.org2.example.com)의 앵커 피어가 업데이트됩니다. Org1MSPanchors.tx 및 Org2MSPanchors.tx 아티팩트를 채널 이름과 함께 주문 서비스에 전달하여이 작업을 수행합니다.
  • chaincode - chaincode_example02 -는 peer0.org1.example.com 및 peer0.org2.example.com에 설치됩니다.
  • 그런 다음 chaincode는 peer0.org2.example.com에서 "인스턴스화"됩니다. 인스턴스화는 채널에 체인 코드를 추가하고 대상 피어에 대한 컨테이너를 시작하며 체인 코드와 연관된 키 값 쌍을 초기화합니다. 이 예제의 초기 값은 [ "a", "100" "b", "200"]입니다. 이 "인스턴스화"는 dev-peer0.org2.example.com-mycc-1.0이라는 이름으로 컨테이너를 시작합니다.
  • 이 인스턴스화는 보증 정책에 대한 인수도 전달합니다. 정책은 -P "OR ( 'Org1MSP.member', 'Org2MSP.member')로 정의됩니다. 이는 모든 트랜잭션이 Org1 또는 Org2에 연결된 동료에 의해 승인되어야 함을 의미합니다.
  • peer0.org1.example.com에 "a"값에 대한 쿼리가 발행됩니다. chaincode는 이전에 peer0.org1.example.com에 설치되었으므로 Org1 peer0의 컨테이너가 dev-peer0.org1.example.com-mycc-1.0이라는 이름으로 시작됩니다. 쿼리의 결과도 반환됩니다. 쓰기 작업이 발생하지 않으므로 "a"에 대한 쿼리는 여전히 "100"값을 반환합니다.
  • "a"에서 "b"로 "10"을 이동하기 위해 호출이 peer0.org1.example.com으로 전송됩니다.
  • chaincode는 peer1.org2.example.com에 설치됩니다.
  • "a"값에 대해 peer1.org2.example.com에 쿼리가 전송됩니다. 그러면 dev-peer1.org2.example.com-mycc-1.0이라는 이름으로 세 번째 chaincode 컨테이너가 시작됩니다. 키 "a"의 값이 10으로 수정 된 이전 트랜잭션을 정확하게 반영하여 값 90이 리턴됩니다.

What does this demonstrate? ( 이것은 무엇을 보여줍니까? )

원장에 대한 읽기 / 쓰기 작업을 성공적으로 수행하려면 피어에 체인 코드를 설치해야합니다 (MUST). 또한 체인 코드 컨테이너는 해당 체인 코드 (예 : "a"값에 대한 쿼리)에 대해 초기화 또는 기존 트랜잭션 (읽기 / 쓰기)이 수행 될 때까지 피어에 대해 시작되지 않습니다. 트랜잭션은 컨테이너를 시작하게합니다. 또한 채널의 모든 피어는 불변의 시퀀스 된 레코드를 블록으로 저장하는 블록 체인과 현재 상태의 스냅 샷을 유지 관리하는 상태 데이터베이스를 포함하는 원장의 정확한 복사본을 유지 관리합니다. 여기에는 chaincode가 설치되어 있지 않은 피어 (위의 예에서 peer1.org1.example.com)가 포함됩니다. 마지막으로 체인 코드는 이미 인스턴스화되었으므로 위의 예에서 peer1.org2.example.com과 같이 설치 한 후에 액세스 할 수 있습니다.



How do I see these transactions? ( 이러한 거래는 어떻게 볼 수 있습니까? )

CLI Docker 컨테이너의 로그를 확인하십시오.

docker logs -f cli

다음과 같은 결과가 나타납니다.

2017-05-16 17:08:01.366 UTC [msp] GetLocalMSP -> DEBU 004 Returning existing local MSP
2017-05-16 17:08:01.366 UTC [msp] GetDefaultSigningIdentity -> DEBU 005 Obtaining default signing identity
2017-05-16 17:08:01.366 UTC [msp/identity] Sign -> DEBU 006 Sign: plaintext: 0AB1070A6708031A0C08F1E3ECC80510...6D7963631A0A0A0571756572790A0161
2017-05-16 17:08:01.367 UTC [msp/identity] Sign -> DEBU 007 Sign: digest: E61DB37F4E8B0D32C9FE10E3936BA9B8CD278FAA1F3320B08712164248285C54
Query Result: 90
2017-05-16 17:08:15.158 UTC [main] main -> INFO 008 Exiting.....
===================== Query on PEER3 on channel 'mychannel' is successful =====================

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


 _____   _   _   ____
| ____| | \ | | |  _ \
|  _|   |  \| | | | | |
| |___  | |\  | | |_| |
|_____| |_| \_| |____/

이 로그를 스크롤하여 다양한 트랜잭션을 볼 수 있습니다.



How can I see the chaincode logs? (체인 코드 로그는 어떻게 볼 수 있습니까?)

개별 체인 코드 컨테이너를 검사하여 각 컨테이너에 대해 실행되는 별도의 트랜잭션을 확인합니다. 다음은 각 컨테이너에서 결합 된 출력입니다.

$ docker logs dev-peer0.org2.example.com-mycc-1.0
04:30:45.947 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
ex02 Init
Aval = 100, Bval = 200

$ docker logs dev-peer0.org1.example.com-mycc-1.0
04:31:10.569 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
ex02 Invoke
Query Response:{"Name":"a","Amount":"100"}
ex02 Invoke
Aval = 90, Bval = 210

$ docker logs dev-peer1.org2.example.com-mycc-1.0
04:31:30.420 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
ex02 Invoke
Query Response:{"Name":"a","Amount":"90"}



Understanding the Docker Compose topology ( Docker 작성 토폴로지 이해 )

BYFN 샘플은 docker-compose-base.yaml (기본 폴더에 있음)에서 확장 된 두 가지 Docker Compose 파일을 제공합니다. 우리의 첫 번째 flavor, docker-compose-cli.yaml은 CLI 컨테이너와 함께 주문자, 4 명의 동료를 제공합니다. 이 파일은이 페이지의 지침 전체에 사용됩니다.

[참고] 이 절의 나머지 부분에서는 SDK 용으로 설계된 도커 작성 파일에 대해 설명합니다. 이러한 테스트 실행에 대한 자세한 내용 은 노드 SDK 레포를 참조하십시오.

두 번째 flavor 인 docker-compose-e2e.yaml은 Node.js SDK를 사용하여 end-to-end 테스트를 실행하도록 구성됩니다. SDK의 기능 외에도 fabric-ca 서버를위한 컨테이너가 있다는 것이 가장 큰 차이점입니다. 결과적으로 사용자 등록 및 등록을 위해 REST 호출을 조직 CA에 보낼 수 있습니다.

byfn.sh 스크립트를 먼저 실행하지 않고 docker-compose-e2e.yaml을 사용하려면 4 단계를 약간 수정해야합니다. 조직의 CA에 대한 개인 키를 가리킬 필요가 있습니다. crypto-config 폴더에서이 값을 찾을 수 있습니다. 예를 들어 Org1의 개인 키를 찾으려면이 경로 (crypto-config / peerOrganizations / org1.example.com / ca /)를 따라야합니다. 개인 키는 _sk 뒤에 오는 긴 해시 값입니다. Org2의 경로는 - crypto-config / peerOrganizations / org2.example.com / ca /입니다.

docker-compose-e2e.yaml에서 ca0 및 ca1에 대한 FABRIC_CA_SERVER_TLS_KEYFILE 변수를 업데이트하십시오. 또한 ca 서버를 시작하기 위해 명령에 제공된 경로를 편집해야합니다. 각 CA 컨테이너에 동일한 개인 키를 두 번 제공하고 있습니다.


Using CouchDB ( CouchDB 사용 )

상태 데이터베이스는 기본값 (goleveldb)에서 CouchDB로 전환 할 수 있습니다. 동일한 체인 코드 기능을 CouchDB에서 사용할 수 있지만 체인 코드 데이터를 JSON으로 모델링 할 때 상태 데이터베이스 데이터 내용에 대해 풍부하고 복잡한 쿼리를 수행 할 수있는 추가 기능이 있습니다.

기본 데이터베이스 (goleveldb) 대신 CouchDB를 사용하려면 네트워크 시작 docker-compose-couch.yaml을 시작할 때를 제외하고 앞에서 설명한 아티팩트 생성 절차와 동일한 절차를 따르십시오.

CHANNEL_NAME=$CHANNEL_NAME TIMEOUT=<pick_a_value> docker-compose -f docker-compose-cli.yaml -f docker-compose-couch.yaml up -d

chaincode_example02 는 이제 CouchDB를 사용하여 작동합니다.

[참고] fabric-couchdb 컨테이너 포트를 호스트 포트에 매핑하는 것을 선택하는 경우, 보안 관련 사항을 알고 있는지 확인하십시오. 개 _ 환경에서 포트를 맵핑하면 CouchDB REST API를 사용할 수 있으며 CouchDB 웹 인 터 페이스 (Fauxton)를 통해 데이터베이스를 볼 수 있습니다. 프로덕션 환경에서는 CouchDB 컨테이너에 대한 외부 액세스를 제한하기 위해 포트 매핑을 구현하지 않을 수 있습니다.

위에서 설명한 단계를 사용하여 CouchDB 상태 데이터베이스에 chaincode_example02 체인 코드를 사용할 수 있지만 CouchDB 쿼리 기능을 사용하려면 JSON으로 모델링 된 데이터가있는 체인 코드 (예 : marbles02)를 사용해야합니다. marbles02 chaincode는 fabric / examples / chaincode / go 디렉토리에서 찾을 수 있습니다.

위 의 Create & Join 채널 섹션 에서 설명한대로 동일한 프로세스를 따라 채널을 만들고 가입하십시오 . 피어 (들)를 채널에 가입시킨 후 다음 단계를 사용하여 marbles02 체인 코드 와 상호 작용하십시오.

  • peer0.org1.example.com에 체인 코드를 설치하고 인스턴스화하십시오.
# 인스턴스화 명령에 따라 $ CHANNEL_NAME 변수를 수정해야합니다.

peer chaincode install -n marbles -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/marbles02
peer chaincode instantiate -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --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 $CHANNEL_NAME -n marbles -v 1.0 -c '{"Args":["init"]}' -P "OR ('Org0MSP.member','Org1MSP.member')"
  • 일부 구슬을 만들고 주위로 이동하십시오.
# $ CHANNEL_NAME 변수를 적절히 수정해야합니다.

peer chaincode invoke -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --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 $CHANNEL_NAME -n marbles -c '{"Args":["initMarble","marble1","blue","35","tom"]}'
peer chaincode invoke -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --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 $CHANNEL_NAME -n marbles -c '{"Args":["initMarble","marble2","red","50","tom"]}'
peer chaincode invoke -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --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 $CHANNEL_NAME -n marbles -c '{"Args":["initMarble","marble3","blue","70","tom"]}'
peer chaincode invoke -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --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 $CHANNEL_NAME -n marbles -c '{"Args":["transferMarble","marble2","jerry"]}'
peer chaincode invoke -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --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 $CHANNEL_NAME -n marbles -c '{"Args":["transferMarblesBasedOnColor","blue","jerry"]}'
peer chaincode invoke -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --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 $CHANNEL_NAME -n marbles -c '{"Args":["delete","marble1"]}'
  • docker-compose에서 CouchDB 포트를 매핑하도록 선택한 경우 브라우저를 열고 다음 URL로 이동하여 CouchDB 웹 인터페이스 (Fauxton)를 통해 상태 데이터베이스를 볼 수 있습니다. http://localhost:5984/_utils
  • 데이터베이스 mychannel(또는 고유 한 채널 이름)와 그 안에있는 문서를 볼 수 있습니다.



[참고] 아래 명령에 대해서는 $ CHANNEL_NAME 변수를 적절하게 업데이트해야합니다.

CLI에서 정기적 인 쿼리를 실행할 수 있습니다 (예 : 읽기 marble2).

peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["readMarble","marble2"]}'

출력에는 marble2다음 과 같은 세부 정보가 표시되어야합니다.

Query Result: {"color":"red","docType":"marble","name":"marble2","owner":"jerry","size":50}

특정 구술의 기록을 검색할 수 있습니다.(  예 marble1)

peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["getHistoryForMarble","marble1"]}'

결과물은  marble1에 트랜잭션을 표시해야합니다.

Query Result: [{"TxId":"1c3d3caf124c89f91a4c0f353723ac736c58155325f02890adebaa15e16e6464", "Value":{"docType":"marble","name":"marble1","color":"blue","size":35,"owner":"tom"}},{"TxId":"755d55c281889eaeebf405586f9e25d71d36eb3d35420af833a20a2f53a3eefd", "Value":{"docType":"marble","name":"marble1","color":"blue","size":35,"owner":"jerry"}},{"TxId":"819451032d813dde6247f85e56a89262555e04f14788ee33e28b232eef36d98f", "Value":}]

대리석 필드를 소유자jerry별로 쿼리하는 것과 같이 데이터 내용에 대한 풍부한 쿼리를 수행 할 수도 있습니다.

peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarblesByOwner","jerry"]}'

결과물에는 jerry 소유의 두 대리석이 표시되어야합니다.

Query Result: [{"Key":"marble2", "Record":{"color":"red","docType":"marble","name":"marble2","owner":"jerry","size":50}},{"Key":"marble3", "Record":{"color":"blue","docType":"marble","name":"marble3","owner":"jerry","size":70}}]


A Note on Data Persistence ( 데이터 지속성에 대한 참고 사항 )

피어 컨테이너 또는 CouchDB 컨테이너에서 데이터 지속성이 필요한 경우, 한 가지 옵션은 docker-host의 디렉토리를 컨테이너의 관련 디렉토리에 마운트하는 것입니다. 예를 들어, docker-compose-base.yaml 파일의 피어 컨테이너 스펙에 다음 두 행을 추가 할 수 있습니다.

volumes:
 - /var/hyperledger/peer0:/var/hyperledger/production

CouchDB 컨테이너의 경우 CouchDB 컨테이너 사양에 다음 두 줄을 추가 할 수있다.

volumes:
 - /var/hyperledger/couchdb0:/opt/couchdb/data


Troubleshooting ( 문제 해결 )

  • 항상 네트워크를 새로 시작하십시오. 아티팩트, 암호, 컨테이너 및 체인 코드 이미지를 제거하려면 다음 명령을 사용하십시오.
./byfn.sh -m down
  • 컨테이너와 이미지를 지우지 않으면 오류가 발생합니다.
  • Docker 오류가 표시되면 먼저 도커 버전 ( 선행 조건 )을 확인한 다음 Docker 프로세스를 다시 시작하십시오. Docker의 문제점은 종종 즉시 인식되지 않습니다. 예를 들어, 컨테이너에 마운트 된 암호 자료에 액세스 할 수 없으므로 오류가 발생할 수 있습니다.
  • 그들이 지속되면 이미지를 제거하고 처음부터 시작하십시오.
docker rm -f $(docker ps -aq)
docker rmi -f $(docker images -q)
  • 작성, 인스턴스 작성, 호출 또는 조회 명령에 오류가있는 경우 채널 이름 및 체인 코드 이름을 올바르게 갱신했는지 확인하십시오. 제공된 샘플 명령에는 자리 표시 자 값이 있습니다.
  • 아래 오류가 표시되면
Error: Error endorsing chaincode: rpc error: code = 2 desc = Error installing chaincode code mycc:1.0(chaincode /var/hyperledger/production/chaincodes/mycc.1.0 exits)
  • 이전 실행에서 체인 코드 이미지 (예 dev-peer1.org2.example.com-mycc-1.0또는 dev-peer0.org1.example.com-mycc-1.0) 가있을 가능성이 큽니다 . 그들을 제거하고 다시 시도하십시오
docker rmi -f $(docker images | grep peer[0-9]-peer[0-9] | awk '{print $3}')
  • 다음과 유사한 내용이 표시되는 경우
Error connecting: rpc error: code = 14 desc = grpc: RPC failed fast due to transport failure
Error: rpc error: code = 14 desc = grpc: RPC failed fast due to transport failure
  • "최신"으로 태그가 다시 지정된 "1.0.0"이미지에 대해 네트워크를 실행하고 있는지 확인하십시오.
  • 아래 오류가 표시되면
[configtx/tool/localconfig] Load -> CRIT 002 Error reading configuration: Unsupported Config Type ""
panic: Error reading configuration: Unsupported Config Type ""

그런 다음 FABRIC_CFG_PATH 환경 변수를 올바르게 설정하지 않았습니다. configtxgen 도구는 configtx.yaml을 찾으려면이 변수가 필요합니다. 돌아가서 내보내기 FABRIC_CFG_PATH = $ PWD를 실행 한 다음 채널 아티팩트를 다시 만드십시오.

  • 네트워크를 정리하려면 다음 down옵션을 사용하십시오 .
./byfn.sh -m down
  • "active endpoints"이 여전히 있음을 알리는 오류가 표시되면 Docker 네트워크를 정리합니다. 이렇게하면 이전 네트워크를 지우고 새로운 환경에서 시작할 수 있습니다.
docker network prune

다음 메시지가 표시됩니다.

WARNING! This will remove all networks not used by at least one container. Are you sure you want to continue? [y/N]
#경고! 이렇게하면 하나 이상의 컨테이너에서 사용하지 않는 모든 네트워크가 제거됩니다. 계속 하시겠습니까? [y / N]

y를 선택하십시오.

  • 오류가 계속 발생하면 Hyperledger Rocket Chat 의 # fabric-questions 채널에서 로그를 공유하십시오.


Writing Your First Application ( 첫 번째 애플리케이션 작성 )

이 문서의 목표는 작업을 표시하고 Hyperledger 패브릭 네트워크에 대한 첫 번째 응용 프로그램을 작성하기위한 기준을 제공하는 것입니다. 가장 기본적인 수준에서 블록 체인 네트워크의 응용 프로그램은 사용자가 원장 을 쿼리 (포함 된 특정 레코드 요청)하거나 업데이트 (레코드 추가) 할 수있게합니다. Javascript로 구성된이 애플리케이션은 Node.js SDK를 활용하여 네트워크 (원장이있는 곳)와 상호 작용합니다. 이 자습서는 첫 번째 응용 프로그램 작성과 관련된 세 가지 단계를 안내합니다.

1. 테스트 하이퍼 레더 패브릭 블록 체인 네트워크 시작합니다. 원장을 쿼리하고 업데이트하려면 네트워크에 몇 가지 기본 구성 요소가 필요합니다. 이러한 구성 요소 (피어 노드, 주문 노드 및 인증 기관)는 우리 네트워크의 백본 역할을합니다. 몇 가지 관리 명령에 사용되는 CLI 컨테이너도 있습니다. 단일 스크립트가이 테스트 네트워크를 다운로드하고 실행합니다.

2. 앱에서 사용할 샘플 스마트 계약의 매개 변수를 학습합니다. 우리의 현명한 계약에는 다양한 방식으로 원장과 상호 작용할 수있는 다양한 기능이 포함되어 있습니다. 예를 들어, 우리는 전체적으로 또는보다 세분화 된 수준으로 데이터를 읽을 수 있습니다.

3. 레코드를 쿼리하고 갱신 할 수있는 응용 프로그램 개발합니다. 우리는 두 가지 샘플 응용 프로그램을 제공합니다 - 하나는 장부를 쿼리하고 다른 하나는 업데이트하기위한 것입니다. Google 앱은 SDK API를 사용하여 네트워크와 상호 작용하고 궁극적으로 이러한 기능을 호출합니다.

이 튜토리얼을 완료하면 Node.js 용 Hyperledger Fabric SDK를 사용하는 애플리케이션이 Hyperledger 패브릭 네트워크에서 원장과 상호 작용할 수있는 스마트 계약과 함께 프로그래밍되는 방법에 대한 기본적인 이해가 필요합니다.

먼저, 테스트 네트워크를 시작합시다 ...


Getting a Test Network ( 테스트 네트워크 얻기 )

전제 조건 페이지를 방문 하여 시스템에 필요한 종속성이 설치되어 있는지 확인하십시오. 이제 fabric-samples repo를 복제 할 작업 디렉토리를 결정하십시오. clone 명령을 실행하고 fabcar서브 디렉토리 로 변경하십시오.

git clone https://github.com/hyperledger/fabric-samples.git
cd fabric-samples/fabcar

이 하위 디렉토리 fabcar에는 샘플 앱을 실행하기위한 스크립트와 애플리케이션 코드가 들어 있습니다. ls이 디렉토리에서를 발행하십시오 . 다음을보아야합니다.

chaincode    invoke.js       network         package.json    query.js        startFabric.sh

이제 startFabric.sh스크립트를 사용하여 네트워크를 시작하십시오.

[참고] 다음 명령은 Hyperledger Fabric Docker 이미지를 다운로드하고 추출하므로 완료하는 데 몇 분이 걸립니다.

./startFabric.sh

간결함을 위해이 명령으로 어떤 일이 벌어지고 있는지 자세히 설명하지 않겠습니다. 다음은 간단한 개요입니다.

  • 피어 노드, 주문 노드, 인증 기관 및 CLI 컨테이너 시작
  • 채널을 만들고 피어를 채널에 연결합니다.
  • 스마트 컨트랙트 (즉, 체인 코드)를 피어의 파일 시스템에 설치하고 상기 체인 코드를 채널에 인스턴스화합니다. 인스턴스화는 chaincode 컨테이너를 시작합니다.
  • initLedger 함수를 호출하여 10 개의 고유 한 자동차로 채널 원장을 채 웁니다.

[참고] 이러한 작업은 일반적으로 조직 또는 피어 관리자가 수행합니다. 스크립트는 CLI를 사용하여 이러한 명령을 실행하지만 SDK에서도 지원됩니다. 예제 스크립트 는 Hyperledger Fabric Node SDK 레포 를 참조하십시오.

docker ps 명령을 실행하여 startFabric.sh 스크립트에 의해 시작된 프로세스를 표시하십시오. 첫 번째 네트워크 구축 섹션에서 이러한 작업의 세부 사항과 메커니즘에 대해 자세히 배울 수 있습니다. 여기서는 응용 프로그램에만 초점을 맞 춥니 다. 다음 그림은 응용 프로그램이 Hyperledger 패브릭 네트워크와 상호 작용하는 방식을 단순하게 보여줍니다.

자 이제 예제 네트워크와 코드가 생겼으니 다른 조각들이 어떻게 맞는지 살펴 보겠습니다.


How Applications Interact with the Network ( 응용 프로그램이 네트워크와 상호 작용하는 방법 )

응용 프로그램은 API를 사용하여 스마트 계약 ( "체인 코드"라고 함)을 호출합니다. 이러한 현명한 계약은 네트워크에서 호스팅되며 이름과 버전으로 식별됩니다. 예를 들어, chaincode 컨테이너의 제목은 - dev-peer0.org1.example.com-fabcar-1.0입니다. 여기서 이름은 fabcar이고 버전은 1.0이며 실행되는 피어는 dev-peer0.org1.example.com입니다.

API는 SDK (소프트웨어 개발 키트)를 통해 액세스 할 수 있습니다. 이 연습에서는 응용 프로그램을 개발하는 데 사용할 수있는 Java SDK 및 CLI가 있지만 Hyperledger 패브릭 노드 SDK 를 사용할 것입니다.


Querying the Ledger

검색어는 원장에서 데이터를 읽는 방법입니다. 단일 키, 여러 키의 값을 쿼리 할 수 ​​있습니다. 또는 - 원장이 JSON과 같은 풍부한 데이터 저장소 형식으로 작성된 경우 복잡한 키워드 검색을 수행 할 수 있습니다 (예 : 특정 키워드가 포함 된 모든 애셋을 찾습니다).

앞에서 말했듯이 샘플 네트워크에는 활성 체인 코드 컨테이너와 10 개의 다른 자동차가 준비되어있는 원장이 있습니다. 또한 자동차의 세부 사항을 원장에 문의하는 데 사용할 수있는 샘플 자바 스크립트 코드 - query.js가 fabcar디렉토리에 있습니다.

이 응용 프로그램의 작동 방식을 살펴보기 전에 프로그램이 작동하도록 SDK 노드 모듈을 설치해야합니다. 귀하의에서 fabcar디렉토리, 다음을 실행합니다.

npm install

[참고]fabcar디렉토리 에서 모든 후속 명령을 실행합니다.

이제 우리는 자바 스크립트 프로그램을 실행할 수 있습니다. 먼저 query.js 프로그램을 실행하여 원장의 모든 자동차 목록을 반환합시다. 모든 자동차 queryAllCars를 쿼리하는 함수는 앱에 미리로드되어 있으므로 간단히 프로그램을 실행할 수 있습니다.

node query.js

다음과 같이 반환해야합니다.

Query result count =  1
Response is  [{"Key":"CAR0", "Record":{"colour":"blue","make":"Toyota","model":"Prius","owner":"Tomoko"}},
{"Key":"CAR1",   "Record":{"colour":"red","make":"Ford","model":"Mustang","owner":"Brad"}},
{"Key":"CAR2", "Record":{"colour":"green","make":"Hyundai","model":"Tucson","owner":"Jin Soo"}},
{"Key":"CAR3", "Record":{"colour":"yellow","make":"Volkswagen","model":"Passat","owner":"Max"}},
{"Key":"CAR4", "Record":{"colour":"black","make":"Tesla","model":"S","owner":"Adriana"}},
{"Key":"CAR5", "Record":{"colour":"purple","make":"Peugeot","model":"205","owner":"Michel"}},
{"Key":"CAR6", "Record":{"colour":"white","make":"Chery","model":"S22L","owner":"Aarav"}},
{"Key":"CAR7", "Record":{"colour":"violet","make":"Fiat","model":"Punto","owner":"Pari"}},
{"Key":"CAR8", "Record":{"colour":"indigo","make":"Tata","model":"Nano","owner":"Valeria"}},
{"Key":"CAR9", "Record":{"colour":"brown","make":"Holden","model":"Barina","owner":"Shotaro"}}]

이들은 10 대입니다. Adriana 소유의 검은 색 Tesla Model S, Brad 소유 빨간색 포드 머스탱, Pari라는 누군가 소유 한 보라색 Fiat Punto 등등. 원장은 키 / 값 기반이며 구현시 키는 CAR0에서 CAR9까지입니다. 이것은 특히 중요하게 될 것입니다. 이제는 두포에서 어떻게 보이는지 봅시다 (당신이 말장난을 용서한다면). 편집기 (예 : 원자 또는 시각 스튜디오)를 사용하고 query.js 프로그램을 엽니다. 응용 프로그램의 초기 섹션에서는 체인 코드 ID, 채널 이름 및 네트워크 종점과 같은 특정 변수를 정의합니다.

응용 프로그램의 초기 섹션에서는 체인 코드 ID, 채널 이름 및 네트워크 종점과 같은 특정 변수를 정의합니다.

var options = {
      wallet_path : path.join(__dirname, './creds'),
      user_id: 'PeerAdmin',
      channel_id: 'mychannel',
      chaincode_id: 'fabcar',
      network_url: 'grpc://localhost:7051',
}

이것은 쿼리를 구성하는 청크입니다.

// queryCar - requires 1 argument, ex: args: ['CAR4'],
// queryAllCars - requires no arguments , ex: args: [''],
const request = {
   chaincodeId: options.chaincode_id,
   txId: transaction_id,
   fcn: 'queryAllCars',
   args: ['']
}

chaincode_id 변수를 fabcar로 정의하여이 특정 체인 코드를 타겟팅 할 수있게 한 다음 해당 체인 코드 내에 정의 된 queryAllCars 함수를 호출합니다. 이전에 node.js 명령을 발행했을 때이 특정 함수가 호출되어 원장을 조회했습니다. 그러나 이것이 우리가 전달할 수있는 유일한 기능은 아닙니다.

다른 것들을 살펴 보려면 체인 코드 하위 디렉토리로 이동하여 편집기에서 fabcar.go를여십시오. initLedger, queryCar, queryAllCars, createCar 및 changeCarOwner와 같이 호출 할 수있는 다음 함수가 있음을 알 수 있습니다. queryAllCars 함수를 자세히 살펴보고 장부와 상호 작용하는 방법을 살펴 보겠습니다.

func (s *SmartContract) queryAllCars(APIstub shim.ChaincodeStubInterface) sc.Response {

     startKey := "CAR0"
     endKey := "CAR999"

     resultsIterator, err := APIstub.GetStateByRange(startKey, endKey)
}

이 함수는 shimm 인터페이스 함수 인 GetStateByRange를 사용하여 startKey와 endKey의 args간에 원장 데이터를 반환합니다. 이러한 키는 각각 CAR0 및 CAR999로 정의됩니다. 따라서 우리는 이론적으로 1,000 개의 자동차를 만들 수 있습니다 (키에 태그가 올바르게 지정되었다고 가정). queryAllCars는 모든 자동차를 나타냅니다.

다음은 앱이 chaincode에서 다른 기능을 호출하는 방법을 나타낸 것입니다.

const request = {
      chaincodeId: options.chaincode_id,
      txId: transaction_id,
      fcn: 'queryCar',
      args: ['CAR4']
}

프로그램을 저장하고 fabcar디렉토리로 다시 이동하십시오 . 이제 프로그램을 다시 실행하십시오.

node query.js

다음을 보아야합니다.

{"colour":"black","make":"Tesla","model":"S","owner":"Adriana"}

Adriana의 검정색 Tesla Model S를 쿼리하는 것까지 모든 자동차를 쿼리하지 않았습니다. queryCar 함수를 사용하여 모든 키 (예 : CAR0)에 대해 쿼리하고 해당 자동차에 맞는 제조업체, 모델, 색 및 소유자를 얻습니다 . 좋습니다. 이제 체인 코드의 기본 쿼리 기능과 쿼리 프로그램의 소수의 매개 변수에 익숙해 져야합니다. 원장을 업데이트 할 시간 ...


Updating the Ledger ( 원장 업데이트 )

이제는 원장 쿼리를 수행하고 약간의 코드를 추가 했으므로 원장을 업데이트 할 준비가되었습니다. 우리가 할 수있는 많은 잠재적 인 업데이트가 있지만 우선 시동기를위한 새로운 자동차를 만들어 보겠습니다.

원장 갱신은 트랜잭션 제안을 생성하는 응용 프로그램으로 시작됩니다. 쿼리와 마찬가지로 채널 ID, 함수 및 트랜잭션을 대상으로하는 특정 스마트 계약을 식별하는 요청이 생성됩니다. 그런 다음 프로그램은 channel.SendTransactionProposalAPI를 호출하여 트랜잭션 제안서를 피어에게 보냅니다.

네트워크 (즉, 인증 피어)는 제안서 응답을 반환합니다.이 응답은 응용 프로그램이 트랜잭션 요청을 작성하고 서명하는 데 사용합니다. 이 요청은 channel.sendTransactionAPI 를 호출하여 주문 서비스로 전송됩니다 . 주문 서비스는 트랜잭션을 블록으로 묶어 유효성 검사를 위해 채널의 모든 피어에게 블록을 전달합니다. (우리의 경우에는 단 하나의 지지자 만 있습니다.)

마지막으로 애플리케이션은 eh.setPeerAddrAPI를 사용하여 피어의 이벤트 리스너 포트에 eh.registerTxEvent연결하고 특정 트랜잭션 ID와 연관된 이벤트를 등록하도록 호출 합니다. 이 API를 사용하면 응용 프로그램이 트랜잭션의 운명 (즉, 성공적으로 커밋되었거나 실패한 트랜잭션)을 알 수 있습니다. 알림 메커니즘으로 생각하십시오.

[참고] 여기서는 트랜잭션의 수명주기에 대해 자세히 다루지 않습니다. 트랜잭션이 궁극적으로 장부에 커밋되는 방법에 대한 자세한 내용 은 트랜잭션 흐름 설명서를 참조하십시오.

처음 호출 할 때의 목표는 단순히 새 자산 (이 경우 자동차)을 만드는 것입니다. 우리는 별도의 자바 스크립트 프로그램 인 invoke.js를 가지고 있습니다. 쿼리와 마찬가지로 편집기를 사용하여 프로그램을 열고 호출을 구성하는 코드 블록으로 이동합니다.

// createCar - requires 5 args, ex: args: ['CAR11', 'Honda', 'Accord', 'Black', 'Tom'],
// changeCarOwner - requires 2 args , ex: args: ['CAR10', 'Barry'],
// send proposal to endorser
var request = {
    targets: targets,
    chaincodeId: options.chaincode_id,
    fcn: '',
    args: [''],
    chainId: options.channel_id,
    txId: tx_id
}

- 당신은 우리가 두 가지 기능 중 하나를 호출 할 수있는 것을 볼 수 있습니다. createCar함수 또는 changeCarOwner함수로. 빨간 시보레 볼트를 만들어 닉이라는 소유자에게 주자. 우리는 CAR9 원장에 달려 있으므로 CAR10여기에서 식별 키로 사용하겠습니다. 업데이트 된 코드 블록은 다음과 같아야합니다.

var request = {
    targets: targets,
    chaincodeId: options.chaincode_id,
    fcn: 'createCar',
    args: ['CAR10', 'Chevy', 'Volt', 'Red', 'Nick'],
    chainId: options.channel_id,
    txId: tx_id
}

저장하고 프로그램을 실행하십시오.

node invoke.js

제안서 응답 및 거래 ID에 대한 일부 출력이 터미널에 있습니다. 그러나 우리가 신경 쓰는 것은이 메시지입니다.

The transaction has been committed on peer localhost:7053

피어는 이 이벤트 알림을 내고 eh.registerTxEvent API 덕분에 애플리케이션이 이벤트 알림을받습니다. 이제 query.js 프로그램으로 돌아가서 CAR10의 arg에 대해 queryCar 함수를 호출하면 다음과 같이 표시됩니다.

Response is  {"colour":"Red","make":"Chevy","model":"Volt","owner":"Nick"}

마지막으로 changeCarOwner 함수를 호출 해 보겠습니다. Nick은 기분이 좋고 Barry라는 남자에게 Chevy Volt를주고 싶다. 따라서 invoke.js를 편집하여 다음을 반영합니다.

var request = {
   targets: targets,
   chaincodeId: options.chaincode_id,
   fcn: 'changeCarOwner',
   args: ['CAR10', 'Barry'],
   chainId: options.channel_id,
   txId: tx_id
}

프로그램을 다시 실행하여 노드 invoke.js를 실행 한 다음 마지막으로 쿼리 응용 프로그램을 실행하십시오. 우리는 여전히 CAR10에 대해 질의를하고 있으므로 다음을 확인해야합니다.

Response is  {"colour":"Red","make":"Chevy","model":"Volt","owner":"Barry"}



추가 리소스

Hyperledger 패브릭 노드 SDK의 환매 특약은 깊은 문서와 샘플 코드를위한 훌륭한 자원이다. Hyperledger Rocket Chat 의 Hyperledger Fabric 커뮤니티 및 구성 요소 전문가에게 문의 할 수도 있습니다.