티스토리 뷰

반응형

해당 글은 Hyperledger Fabric 페이지의 게시글을 번역 및 정리한 자료입니다.

원본 사이트 : http://hyperledger-fabric.readthedocs.io/en/release-1.1/readwrite.html


이 튜토리얼에서는 권한이 부여 된 조직의 블록 체인 네트워크에서 private data를 저장 및 검색 할 수 있도록 컬렉션을 사용하는 방법을 보여줍니다.

이 자습서의 정보는 private data 저장소 및 해당 사용 사례에 대한 지식을 전제로 합니다. 자세한 내용은 개인 정보(private data)를 확인하십시오.

이 튜토리얼에서는 Fabric으로 private data를 정의, 구성 및 사용하는 방법에 대해 다음 단계를 안내합니다.

  1. 컬렉션 정의 JSON 파일 만들기
  2. chaincode API를 사용하여 private data 읽기 및 쓰기
  3. 컬렉션에 체인 코드 설치 및 인스턴스화
  4. private data 저장
  5. private data를 인증된 peer로 쿼리
  6. private data를 인증되지 않은 peer로 쿼리
  7. private data 삭제
  8. private data에 인덱스 사용

이 자습서에서는 private data 수집을 작성, 배포 및 사용하는 방법을 보여주기 위해 marbles private data 샘플 (BYFN 자습서 네트워크에서 실행)을 사용합니다. marbles private data 샘플은 첫 번째 네트워크 구축 (BYFN) 자습서 네트워크에 배포됩니다. Sample, Binaries 및 Docker Images 설치 작업을 완료해야합니다. 그러나 BYFN 자습서를 실행하는 것은 이 자습서의 전제 조건은 아닙니다. 이 튜토리얼에서는 네트워크를 사용하는 데 필요한 명령을 제공합니다. 각 단계에서 어떤 일이 일어나는지 설명하고 샘플을 실제로 실행하지 않고 자습서를 이해할 수 있습니다.



Build a collection definition JSON file

채널에서 데이터를 사유화하는 첫 번째 단계는 private data에 대한 액세스를 정의하는 컬렉션 정의를 작성하는 것입니다.

컬렉션 정의는 누가 데이터를 유지할 수 있는지, 얼마나 많은 피어가 데이터가 배포되는지, private data를 보급하는 데 필요한 피어의 수 및 private data가 private database 에 보존되는 기간을 설명합니다. 나중에 우리는 체인 코드 API인 PutPrivateData와 GetPrivateData를 사용하여 컬렉션을 보호되는 private data에 매핑하는 방법을 보여줍니다.

컬렉션 정의는 다섯 가지 속성으로 구성됩니다.

  • name : 콜렉션의 이름.
  • policy : 수집 데이터를 보존 할 수 있는 조직 피어를 정의합니다.
  • requiredPeerCount : 체인 코드를 보증하기 위한 조건으로 private data를 보급하는 데 필요한 피어의 수
  • maxPeerCount : 데이터 중복성을 위해 현재 피어 투 피어가 데이터를 배포하려고 시도하는 다른 피어의 수입니다. 승인하는 피어가 다운되면 private data를 가져 오기 요청이 있으면 이러한 다른 피어를 커밋 시간에 사용할 수 있습니다.
  • blockToLive : 가격이나 개인 정보와 같은 매우 민감한 정보의 경우이 값은 데이터가 블록 단위로 private database 에 저장되는 기간을 나타냅니다. 데이터는 private database 에서 이 지정된 수의 블록에 대해 살아 있고 이후에는 제거되어 네트워크에서이 데이터를 더 이상 사용하지 않게됩니다. private data를 무기한 유지하려면 즉, private data를 절대 지우지 않으려면 blockToLive 속성을 0으로 설정합니다.

private data의 사용법을 설명하기 위해 marbles private data 예제에는 collectionMarbles 및 collectionMarblePrivateDetails의 두 가지 private data 컬렉션 정의가 포함되어 있습니다. collectionMarbles 정의의 policy 특성은 채널의 모든 구성원 (Org1 및 Org2)이 private database에 private data를 가질 수 있게 합니다. collectionMarblesPrivateDetails 컬렉션을 사용하면 Org1의 구성원만 private database에 private data를 가질 수 있습니다.

정책 정의 작성에 대한 자세한 내용은 보안 정책 주제를 참조하십시오.

// collections_config.json

[
  {
       "name": "collectionMarbles",
       "policy": "OR('Org1MSP.member', 'Org2MSP.member')",
       "requiredPeerCount": 0,
       "maxPeerCount": 3,
       "blockToLive":1000000
  },

  {
       "name": "collectionMarblePrivateDetails",
       "policy": "OR('Org1MSP.member')",
       "requiredPeerCount": 0,
       "maxPeerCount": 3,
       "blockToLive":3
  }
]

이 정책에 의해 보안되는 데이터는 체인 코드로 매핑되며 튜토리얼의 뒷부분에 표시됩니다.

이 컬렉션 정의 파일은 관련 chaincode가 피어 체인 코드 인스턴스화 명령을 사용하여 채널에서 인스턴스화 될 때 채널에 배포됩니다. 이 프로세스에 대한 자세한 내용은 아래 3 절에 나와 있습니다.



Read and Write private data using chaincode APIs

채널의 데이터를 사유화하는 방법을 이해하는 다음 단계는 체인 코드에 데이터 정의를 작성하는 것입니다. marbles private data 샘플은 private data를 데이터 액세스 방법에 따라 두 개의 개별 데이터 정의로 나눕니다.

// Org1 및 Org2의 피어는 사이드 데이터베이스에 이 개인 데이터를 갖습니다.
type marble struct {
  ObjectType string `json:"docType"`
  Name       string `json:"name"`
  Color      string `json:"color"`
  Size       int    `json:"size"`
  Owner      string `json:"owner"`
}

// Org1의 피어(peer)만이 사이드 데이터베이스에 이 개인 데이터를 갖습니다.
type marblePrivateDetails struct {
  ObjectType string `json:"docType"`
  Name       string `json:"name"`
  Price      int    `json:"price"`
}

특히 개인 정보에 대한 액세스는 다음과 같이 제한됩니다.

- "이름, 색상, 크기 및 소유자" 채널의 모든 구성원에게 표시됩니다(Org1  Org2).
- Org1 회원만  수있는 '가격'

따라서 두 개의 서로 다른 private data 세트가 marbles private data 샘플에 정의됩니다. 이 데이터를 액세스를 제한하는 수집 정책에 매핑하는 것은 chaincode API에 의해 제어됩니다. 특히 컬렉션 정의를 사용하여 private data를 읽고 쓰는 작업은 여기에서 찾을 수있는 GetPrivateData() 및 PutPrivateData()를 호출하여 수행합니다.

다음 다이어그램은 marbles private data 샘플에서 사용하는 private data 모델을 보여줍니다.

Reading collection data

데이터베이스의 private data를 쿼리하려면 chaincode API GetPrivateData ()를 사용하십시오. GetPrivateData ()는 컬렉션 이름과 데이터 키라는 두 개의 인수를 취합니다.

콜렉션 'collectionMarbles'는 Org1과 Org2의 멤버가 사이드 데이타베이스에 private data 를 가질 수있게하며,

콜렉션 'collectionMarblePrivateDetails'는 Org1의 구성원만 부가 데이터 베 이스에 private data 를 가질 수 있게 합니다. 구현에 대한 자세한 내용은 다음 두 구슬 private data 함수를 참조하십시오.

  • readMarble : name, color, size 및 owner 속성의 값을 조회하기 위한 것
  • readMarblePrivateDetails : 가격 속성의 값을 조회하기 위한 것

이 튜토리얼의 뒷부분에서 peer 명령을 사용하여 데이터베이스 쿼리를 실행하면 이 두 함수가 호출됩니다.


Writing private data

private data 를 사설 데이터베이스에 저장하려면 chaincode API PutPrivateData()를 사용하십시오. API에는 또한 콜렉션의 이름이 필요합니다. marbles private data  샘플에는 두 가지 컬렉션이 포함되어 있으므로 chaincode에서 두 번 호출됩니다.

1. collectionMarbles라는 콜렉션을 사용하여 private data 이름, 색상, 크기 및 소유자를 작성하십시오.

2. collectionMarblePrivateDetails 컬렉션을 사용하여 private data 가격을 기록하십시오.

예를 들어, initMarble 함수의 다음 코드에서 PutPrivateData()는 각 private data 집합에 대해 한 번씩 두 번 호출됩니다.

 // ==== Create marble object and marshal to JSON ====
       objectType := "marble"
       marble := &marble{objectType, marbleName, color, size, owner}
       marbleJSONasBytes, err := json.Marshal(marble)
       if err != nil {
               return shim.Error(err.Error())
       }
       //Alternatively, build the marble json string manually if you don't want to use struct marshalling
       //marbleJSONasString := `{"docType":"Marble",  "name": "` + marbleName + `", "color": "` + color + `", "size": ` + strconv.Itoa(size) + `, "owner": "` + owner + `"}`
       //marbleJSONasBytes := []byte(str)

       // === Save marble to state ===
       err = stub.PutPrivateData("collectionMarbles", marbleName, marbleJSONasBytes)
       if err != nil {
               return shim.Error(err.Error())
       }

       // ==== Save marble private details ====
       objectType = "marblePrivateDetails"
       marblePrivateDetails := &marblePrivateDetails{objectType, marbleName, price}
       marblePrivateDetailsBytes, err := json.Marshal(marblePrivateDetails)
       if err != nil {
               return shim.Error(err.Error())
       }
       err = stub.PutPrivateData("collectionMarblePrivateDetails", marbleName, marblePrivateDetailsBytes)
       if err != nil {
               return shim.Error(err.Error())
}

요약하면, collection.json 에 대한 위의 정책 정의는 Org1 및 Org2의 모든 피어가 private database에 구슬 private data  name, color, size, owner를 저장하고 처리 (보증, 커밋, 쿼리) 할 수있게합니다. 그러나 Org1의 peer 만이 추가 private database에 price private data를 저장하고 거래 할 수 있습니다.

데이터 개인 정보 보호의 추가 혜택으로 컬렉션이 사용 중이므로, private data 자체가 아닌 private data 해시만 orderer 를 통해 진행되므로 private data를 orderer로부터 비밀로 유지합니다.



Start the network

이제 private data 를 사용하는 방법을 설명하는 몇 가지 명령을 단계별로 실행할 준비가 되었습니다.

Try it yourself

아래의 marbles private data 체인 코드를 설치하고 인스턴스화하기 전에 BYFN 네트워크를 시작해야합니다. 이 자습서에서는 초기 상태에서 작동하려고합니다. 다음 명령은 활성 또는 비활성 docker 컨테이너를 제거하고 이전에 생성된 아티팩트를 제거합니다. 따라서 다음 명령을 실행하여 이전 환경을 정리하십시오.

cd fabric-samples/first-network
./byfn.sh -m down

다음 명령을 실행하여 CouchDB로 BYFN 네트워크를 시작하십시오.

./byfn.sh up -c mychannel -s couchdb

이렇게하면 두 개의 조직(두 개의 피어 노드를 유지 관리하는)과 CouchDB를 상태 데이터베이스로 사용하는 ordering service 로 구성된 mychannel이라는 단일 채널로 구성된 간단한 패브릭 네트워크가 생성됩니다. LevelDB 또는 CouchDB는 콜렉션과 함께 사용될 수 있습니다. CouchDB는 private data 에 인덱스를 사용하는 방법을 보여주기 위해 선택되었습니다.

[노트]

콜렉션이 작동하려면 크로스 조직 가십이 올바르게 구성되어 있어야합니다. "앵커 피어 (anchor peers)"섹션에 특히 주의하면서 가십 데이터 보급 프로토콜에 대한 문서를 참조하십시오. 우리의 튜토리얼은 BYFN 샘플에 이미 구성되어 있기 때문에 가십에 초점을 맞추지 않지만, 채널을 구성 할 때 가십 앵커 피어는 콜렉션이 제대로 작동하도록 구성하는 데 중요합니다.



Install and instantiate chaincode with a collection

클라이언트 애플리케이션은 체인 코드를 통해 블록 체인 원장과 상호 작용합니다. 따라서 트랜잭션을 실행하고 보증할 모든 피어에 체인 코드를 설치하고 인스턴스화해야합니다. 체인 코드는 피어에 설치되고 피어 명령을 사용하여 채널에 인스턴스화됩니다.


Install chaincode on all peers

위에서 설명한 바와 같이 BYFN 네트워크에는 Org1 및 Org2라는 두 개의 조직이 있으며 각 조직에는 두 개의 peer가 있습니다. 따라서 체인 코드는 4 개의 피어에 설치되어야합니다.

  • peer0.org1.example.com
  • peer1.org1.example.com
  • peer0.org2.example.com
  • peer1.org2.example.com

피어 체인 코드 설치 명령을 사용하여 각 피어에 구슬 체인 코드를 설치하십시오.

Try it yourself

BYFN 네트워크를 시작했다고 가정하고 CLI 컨테이너를 입력하십시오.

docker exec -it cli bash

명령 프롬프트가 다음과 같이 바뀝니다.

root@81eac8493633:/opt/gopath/src/github.com/hyperledger/fabric/peer#

  1. 다음 명령을 사용하여 git 저장소에서 BYFN 네트워크의 피어 peer0.org1.example.com으로 Marbles 체인 코드를 설치하십시오. 기본적으로 BYFN 네트워크를 시작한 후 활성 피어는 다음과 같이 설정됩니다. CORE_PEER_ADDRESS = peer0.org1.example.com : 7051) :
    peer chaincode install -n marblesp -v 1.0 -p github.com/chaincode/marbles02_private/go/
    
    완료되면 다음과 유사한 내용이 표시됩니다.
    install -> INFO 003 Installed remotely response:<status:200 payload:"OK" >
    
  2. CLI를 사용하여 활성 피어를 Org1의 두 번째 피어로 전환하고 체인 코드를 설치하십시오. 다음 명령 전체를 복사하여 CLI 컨테이너에 붙여넣고 실행하십시오.
    export CORE_PEER_ADDRESS=peer1.org1.example.com:7051
    peer chaincode install -n marblesp -v 1.0 -p github.com/chaincode/marbles02_private/go/
    
  3. CLI를 사용하여 Org2로 전환하십시오. 다음 명령 블록을 그룹으로 복사하여 피어 컨테이너에 붙여넣고 한꺼번에 실행하십시오.
    export CORE_PEER_LOCALMSPID=Org2MSP
    export PEER0_ORG2_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
    export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG2_CA
    export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
    
  4. Org2에서 활성 피어를 첫 번째 피어로 전환하고 chaincode를 설치하십시오.
    export CORE_PEER_ADDRESS=peer0.org2.example.com:7051
    peer chaincode install -n marblesp -v 1.0 -p github.com/chaincode/marbles02_private/go/
    
  5. 활성 피어를 org2의 두 번째 피어로 전환하고 chaincode를 설치하십시오.
    export CORE_PEER_ADDRESS=peer1.org2.example.com:7051
    peer chaincode install -n marblesp -v 1.0 -p github.com/chaincode/marbles02_private/go/
    


Instantiate the chaincode on the channel

피어 체인 코드 인스턴스화 명령을 사용하여 채널에서 marbles 체인 코드를 인스턴스화합니다. 채널에서 체인 코드 모음을 구성하려면 컬렉션 JSON 파일의 이름 인 collections_config.json과 함께 플래그 --collections-config를 지정하십시오.

Try it yourself

다음 명령을 실행하여 BYFN 채널 mychannel에서 marbles private data 체인 코드를 인스턴스화합니다.

export 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
peer chaincode instantiate -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -C mychannel -n marblesp -v 1.0 -c '{"Args":["init"]}' -P "OR('Org1MSP.member','Org2MSP.member')" --collections-config  $GOPATH/src/github.com/chaincode/marbles02_private/collections_config.json
[노트]

--collections-config 플래그의 값을 지정할 때 collections_config.json 파일에 대한 완전한 경로를 지정해야합니다. 예를 들면 다음과 같습니다. --collections-config $GOPATH/src/github.com/chaincode/marbles02_private/collections_config.json

인스턴스화가 성공적으로 완료되면 다음과 비슷한 내용이 표시됩니다.

[chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
[chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc



Store private data

marbles private data 샘플에 있는 모든 private data를 처리 할 권한이있는 Org1의 구성원으로 활동하고 Org1 peer에게 다시 전환하여 marbles 추가 요청을 제출합니다.

Try it yourself

다음 명령 세트를 복사하여 CLI 명령 행에 붙여 넣으십시오.

export CORE_PEER_ADDRESS=peer0.org1.example.com:7051
export CORE_PEER_LOCALMSPID=Org1MSP
export 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
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export PEER0_ORG1_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org1.example.com/tls/ca.crt

marbles의 initMarble 함수를 호출하여 private data 가 있는 구슬을 만듭니다. 이름은 marble1이며 색상은 파란색, 크기는 35, 가격은 99입니다. private data인 가격은 공개 데이터 이름, 소유자, 색상, 크기와 별도로 저장됩니다. 이러한 이유 때문에 initMarble 함수는 PutPrivateData() API를 두 번 호출하여 각 컬렉션을 사용하여 개인 데이터를 유지합니다.

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 marblesp -c '{"Args":["initMarble","marble1","blue","35","tom","99"]}'

다음과 유사한 결과가 나타납니다.

[chaincodeCmd] chaincodeInvokeOrQuery->INFO 001 Chaincode invoke successful. result: status:200



Query the private data as an authorized peer

우리 컬렉션 정의는 Org1과 Org2의 모든 구성원이 이름, 색상, 크기, 사이드 데이터베이스에 소유자 private data를 갖도록 허용하며, Org1의 peer만 이 사이드 데이터베이스에 가격 private data를 가질 수 있습니다. Org1에서 권한이 부여 된 피어(peer)로서 우리는 두 가지 private data 집합을 쿼리합니다.

첫 번째 쿼리 명령은 collectionMarbles를 인수로 전달하는 readMarble 함수를 호출합니다.

 // ===============================================
 // readMarble - read a marble from chaincode state
 // ===============================================

 func (t *SimpleChaincode) readMarble(stub shim.ChaincodeStubInterface, args []string) pb.Response {
          var name, jsonResp string
    var err error
    if len(args) != 1 {
                  return shim.Error("Incorrect number of arguments. Expecting name of the marble to query")
           }

name = args[0]
 valAsbytes, err := stub.GetPrivateData("collectionMarbles", name) //get the marble from chaincode state

        if err != nil {
     jsonResp = "{\"Error\":\"Failed to get state for " + name + "\"}"
     return shim.Error(jsonResp)
   } else if valAsbytes == nil {
     jsonResp = "{\"Error\":\"Marble does not exist: " + name + "\"}"
     return shim.Error(jsonResp)
   }

 return shim.Success(valAsbytes)
 }

두 번째 쿼리 명령은 collectionMarblePrivateDetails를 인수로 전달하는 readMarblereadMarblePrivateDetails 함수를 호출합니다.

// ===============================================
// readMarblereadMarblePrivateDetails - read a marble private details from chaincode state
// ===============================================

func (t *SimpleChaincode) readMarblePrivateDetails(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var name, jsonResp string
var err error

if len(args) != 1 {
  return shim.Error("Incorrect number of arguments. Expecting name of the marble to query")
 }

name = args[0]
valAsbytes, err := stub.GetPrivateData("collectionMarblePrivateDetails", name) //get the marble private details from chaincode state

if err != nil {
  jsonResp = "{\"Error\":\"Failed to get private details for " + name + ": " + err.Error() + "\"}"
  return shim.Error(jsonResp)
 } else if valAsbytes == nil {
  jsonResp = "{\"Error\":\"Marble private details does not exist: " + name + "\"}"
  return shim.Error(jsonResp)
 }
return shim.Success(valAsbytes)
}

Now Try it yourself

Org1의 구성원으로서 marble1의 이름, 색상, 크기 및 소유자 private data 를 쿼리합니다.

peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarble","marble1"]}'

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

{"color":"blue","docType":"marble","name":"marble1","owner":"tom","size":35}

Org1의 구성원으로서 marble1의 private data 인 가격을 쿼리하십시오.

peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarblePrivateDetails","marble1"]}'

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

{"docType":"marblePrivateDetails","name":"marble1","price":99}



Query the private data as an unauthorized peer

이제 marbles private data 이름, 색상, 크기, 사이드 데이터베이스에 소유자가 있는 Org2 멤버로 전환합니다. 그러나 사이드 데이터베이스에 marbles 가격 private data가 없습니다.

우리는 두 가지 private data 를 모두 쿼리합니다.


Switch to a peer in Org2

도커 컨테이너 내부에서 다음 명령을 실행하여 marbles 가격 private data 에 대한 권한이 없는 피어로 전환합니다.

Try it yourself

export CORE_PEER_ADDRESS=peer0.org2.example.com:7051
export CORE_PEER_LOCALMSPID=Org2MSP
export PEER0_ORG2_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG2_CA
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp


Query private data Org2 is authorized to

Org2의 피어는 사이드 데이터베이스에 구슬 프라이빗 데이터 (이름, 색상, 크기 및 소유자)의 첫 번째 세트가 있어야하며 collectionMarbles 인수로 호출되는 readMarble() 함수를 사용하여 액세스 할 수 있습니다.

Try it yourself

peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarble","marble1"]}'

다음과 비슷한 결과가 표시됩니다.

{"docType":"marble","name":"marble1","color":"blue","size":35,"owner":"tom"}


Query private data Org2 is not authorized to

Org2의 피어는 marbles 가격의 private data를 사이드 데이터베이스에 보유하지 않습니다. 그들은 이 데이터를 쿼리하려고 할 때 공개 상태와 일치하는 키의 해시를 다시 가져 오지만 비공개 상태는 갖지 않습니다.

Try it yourself

peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarblePrivateDetails","marble1"]}'

다음과 유사한 결과가 나타납니다.

{"Error":"Failed to get private details for marble1: GET_STATE failed:
transaction ID: b04adebbf165ddc90b4ab897171e1daa7d360079ac18e65fa15d84ddfebfae90:
Private data matching public hash version is not available. Public hash
version = &version.Height{BlockNum:0x6, TxNum:0x0}, Private data version =
(*version.Height)(nil)"}"

Org2 회원은 private data 의 공개 해시만 볼 수 있습니다.


Purge Private Data

private data가 off-chain database로 복제 될 때까지 원장에 있어야 하는 경우에는 특정 수의 블록 이후에 데이터를 "제거"할 수 있으며 데이터의 해시만 남겨 둡니다. 거래의 불변 증거로 사용됩니다.

이 예에서는 개인 정보 또는 기밀 정보 (예 : 가격 데이터)를 비롯한 private data 가 있을 수 있으며 거래 당사자는 채널의 다른 조직에 공개하기를 원하지 않습니다. 따라서 제한된 수명을 가지며 컬렉션 정의에서 blockToLive 속성을 사용하여 지정된 블록 수만큼 블록 체인에서 변경되지 않은 상태에서 제거 될 수 있습니다.

우리의 collectionMarblePrivateDetails 정의는 blockToLive 속성 값이 3인 것을 의미합니다. 이 데이터는 세 블록 동안 사이드 데이터베이스에 저장되고 이후에는 제거됩니다. 모든 컬렉션을 묶어서 이 컬렉션 정의를 호출합니다. collectionMarblePrivateDetails는 PutPrivateData() API를 호출하고 collectionMarblePrivateDetails를 인수로 전달할 때 initMarble() 함수의 private data인 가격와 연결됩니다.

체인에 블록을 추가 한 다음 체인에 4개의 새 블록을 추가하는 4개의 새 트랜잭션 (새 marble만들기, 3개의 marble 전송)을 발행하여 가격 정보가 제거되는 것을 확인합니다. 네 번째 거래 (세 번째 marble이전)가 끝나면 가격이 삭제되었는지 확인합니다.

Try it yourself

다음 명령을 사용하여 Org1의 peer0으로 다시 전환하십시오. 다음 코드 블록을 복사하여 붙여넣고 피어 컨테이너 내에서 실행합니다.

export CORE_PEER_ADDRESS=peer0.org1.example.com:7051
export CORE_PEER_LOCALMSPID=Org1MSP
export 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
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export PEER0_ORG1_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org1.example.com/tls/ca.crt

새 터미널 창을 열고 다음 명령을 실행하여이 피어의 private data 로그를 봅니다.

docker logs peer0.org1.example.com 2>&1 | grep -i -a -E 'private|pvt|privdata'

결과는 다음과 유사해야합니다. 목록에서 가장 높은 블록 번호를 기록하십시오. 아래 예에서 가장 높은 블록 높이는 4입니다.

[pvtdatastorage] func1 -> INFO 023 Purger started: Purging expired private data till block number [0]
[pvtdatastorage] func1 -> INFO 024 Purger finished
[kvledger] CommitWithPvtData -> INFO 022 Channel [mychannel]: Committed block [0] with 1 transaction(s)
[kvledger] CommitWithPvtData -> INFO 02e Channel [mychannel]: Committed block [1] with 1 transaction(s)
[kvledger] CommitWithPvtData -> INFO 030 Channel [mychannel]: Committed block [2] with 1 transaction(s)
[kvledger] CommitWithPvtData -> INFO 036 Channel [mychannel]: Committed block [3] with 1 transaction(s)
[kvledger] CommitWithPvtData -> INFO 03e Channel [mychannel]: Committed block [4] with 1 transaction(s)

피어 컨테이너로 돌아가서 다음 명령을 실행하여 marble1 가격 데이터를 쿼리합니다. (쿼리는 트랜잭션 된 데이터가 없으므로 원장에 새 트랜잭션을 생성하지 않습니다.)

peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarblePrivateDetails","marble1"]}'

다음과 유사한 결과가 나타납니다.

{"docType":"marblePrivateDetails","name":"marble1","price":99}

가격 데이터는 여전히 private data 원장에 있습니다.

다음 명령을 실행하여 새로운 marble2를 만듭니다. 이 트랜잭션은 체인에 새 블록을 작성합니다.

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 marblesp -c '{"Args":["initMarble","marble2","blue","35","tom","99"]}'

터미널 창으로 다시 전환하고 이 피어의 private data 로그를 다시보십시오. 블록 높이가 1 증가하는 것을 보아야 합니다.

docker logs peer0.org1.example.com 2>&1 | grep -i -a -E 'private|pvt|privdata'

피어 컨테이너로 돌아가서 다음 명령을 실행하여 marble1 가격 데이터를 다시 쿼리합니다.

peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarblePrivateDetails","marble1"]}'

private data 가 삭제되지 않았으므로 결과는 이전 쿼리와 동일합니다.

{"docType":"marblePrivateDetails","name":"marble1","price":99}

다음 명령을 실행하여 marble2를 "joe"로 전송하십시오. 이 트랜잭션은 체인에 두 번째 새로운 블록을 추가합니다.

터미널 창으로 다시 전환하고 이 피어의 private data 로그를 다시보십시오. 블록 높이가 1 증가하는 것을 보아야합니다.

docker logs peer0.org1.example.com 2>&1 | grep -i -a -E 'private|pvt|privdata'

피어 컨테이너로 돌아가서 다음 명령을 실행하여 marble1 가격 데이터를 쿼리합니다.

peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarblePrivateDetails","marble1"]}'

가격 개인 정보는 계속 볼 수 있습니다.

{"docType":"marblePrivateDetails","name":"marble1","price":99}

다음 명령을 실행하여 marble2를 "tom"으로 전송하십시오. 이 트랜잭션은 체인에 세 번째 새로운 블록을 작성합니다.

터미널 창으로 다시 전환하고이 피어의 개인 데이터 로그를 다시보십시오. 블록 높이가 1 증가하는 것을보아야합니다.

docker logs peer0.org1.example.com 2>&1 | grep -i -a -E 'private|pvt|privdata'

피어 컨테이너로 돌아가서 다음 명령을 실행하여 marble1 가격 데이터를 쿼리합니다.

peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarblePrivateDetails","marble1"]}'

여전히 가격 데이터를 볼 수 있어야 합니다.

{"docType":"marblePrivateDetails","name":"marble1","price":99}

마지막으로 다음 명령을 실행하여 marble2를 "jerry"로 전송합니다. 이 트랜잭션은 체인에서 네 번째로 새로운 블록을 작성합니다. 이 거래가 끝나면 가격 개인 데이터는 제거되어야 합니다.

터미널 창으로 다시 전환하고이 피어의 개인 데이터 로그를 다시보십시오. 블록 높이가 1 증가하는 것을 보아야합니다.

docker logs peer0.org1.example.com 2>&1 | grep -i -a -E 'private|pvt|privdata'

피어 컨테이너로 돌아가서 다음 명령을 실행하여 marble1 가격 데이터를 쿼리합니다.

peer chaincode query -C mychannel -n marblesp -c '{"Args":["readMarblePrivateDetails","marble1"]}'

가격 데이터가 제거되었으므로 더 이상 볼 수 없습니다. 다음과 비슷한 것을보아야합니다.


Using indexes with private data

인덱스는 체인 코드와 함께 META-INF/statedb/couchdb/collections/<collection_name>/indexes 디렉토리에 패키징하여 개인 데이터 수집에 적용 할 수도 있습니다. 여기에 예제 색인이 있습니다.

프로덕션 환경에 체인 코드를 배치하려면 체인 코드가 피어에 설치되고 채널에 인스턴스화 된 후에 체인 코드와 지원 인덱스가 자동으로 하나의 단위로 배치되도록 체인 코드와 함께 인덱스를 정의하는 것이 좋습니다. 연관된 색인은 콜렉션 JSON 파일의 위치를 가리키는 --collections-config 플래그가 지정되면 채널의 체인 코드 인스턴스화시 자동으로 배치됩니다.

반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함