* 본 포스팅은 하이퍼레저 패브릭 docs를 번역한 내용으로, 번역 과정에서 잘못된 부분이 있을 수 있습니다.
상세 내용은 하단 링크를 참조 부탁드리며, 잘못된 내용에 대한 피드백은 언제든 환영합니다 : )
https://hyperledger.github.io/composer/latest/tutorials/queries
이 튜토리얼에서는 developer tutorial에 이어 쿼리를 설명할 것입니다. native query language는 특정 기준에 부합하는 결과를 리턴하거나 결과 집합에 있는 자산을 업데이트 혹은 제거하는 연산을 수행하는 트랜잭션에 의해 호출될 수 있습니다.
쿼리는 비즈니스 네트워크 정의 부모 폴더 내 쿼리 파일(.qry)에 정의되어 있습니다. 쿼리는 어떤 자산 혹은 참가자들을 선택할지 기준이 정의된 WHERE절을 포함하고 있습니다.
이 튜토리얼은 Developer-tutorial에서 개발 및 배포한 tutorial-network 비즈니스 네트워크를 사용합니다.
Prerequisites
이 튜토리얼을 시작하기 전:
- 개발환경 설치를 완료하세요.
https://ralee-world.tistory.com/entry/Hyperledger-Composer-Installing?category=719808
- developer tutorial을 완료하세요.
https://ralee-world.tistory.com/entry/Developer-Tutorial
Step One: Updating the business network
developer tutorial에서 생성된 비즈니스 네트워크를 업데이트해야 합니다. 업데이트된 버전의 비즈니스 네트워크는 두 개의 이벤트와 하나의 추가적인 트랜잭션을 가집니다.
Update the model file
모델 파일은 이벤트와 새 트랜잭션을 포함하도록 업데이트되어야 합니다.
1. tutorial-network의 모델 파일(.cto)파일을 여세요.
2. 아래 내용을 따라 이벤트와 트랜잭션을 추가하세요.
event TradeNotification {
--> Commodity commodity
}
transaction RemoveHighQuantityCommodities {
}
event RemoveNotification {
--> Commodity commodity
}
3. 모델에 변경된 내용을 저장하세요.
Update transaction logic to use queries and events
이제 도메인 모델이 업데이트 되었으므로, 우리는 이제 트랜잭션이 처리를 위해 제출될 때 실행되는 추가적인 비즈니스 로직을 작성할 수 있습니다. 이 튜토리얼에서 우리는 아래처럼 이벤트와 비즈니스 로직을 추가합니다.
1. 트랜잭션 처리 함수 파일(lib/logic.js)을 여세요.
2. 트랜잭션 내용을 아래 JavaScript코드로 변경하세요.
/**
* Track the trade of a commodity from one trader to another
* @param {org.example.mynetwork.Trade} trade - the trade to be processed
* @transaction
*/
async function tradeCommodity(trade) {
// set the new owner of the commodity
trade.commodity.owner = trade.newOwner;
let assetRegistry = await getAssetRegistry('org.example.mynetwork.Commodity');
// emit a notification that a trade has occurred
let tradeNotification = getFactory().newEvent('org.example.mynetwork', 'TradeNotification');
tradeNotification.commodity = trade.commodity;
emit(tradeNotification);
// persist the state of the commodity
await assetRegistry.update(trade.commodity);
}
/**
* Remove all high volume commodities
* @param {org.example.mynetwork.RemoveHighQuantityCommodities} remove - the remove to be processed
* @transaction
*/
async function removeHighQuantityCommodities(remove) {
let assetRegistry = await getAssetRegistry('org.example.mynetwork.Commodity');
let results = await query('selectCommoditiesWithHighQuantity');
for (let n = 0; n < results.length; n++) {
let trade = results[n];
// emit a notification that a trade was removed
let removeNotification = getFactory().newEvent('org.example.mynetwork','RemoveNotification');
removeNotification.commodity = trade;
emit(removeNotification);
await assetRegistry.remove(trade);
}
}
3. logic.js 파일 변경 내용을 저장하세요.
첫 번째 함수인 tradeCommodity는 들어오는 Trade 트랜잭션 내 commodity의 owner 속성을 변경할 것입니다. (새로운 참가자를 소유자로) 그리고 해당 효과에 대한 알림을 생략할 것입니다. 그리고나서 수정된 commodity를 다시 Commodity 객체를 저장하는 asset registry에 저장합니다.
두 번째 함수는 named query라고 불리는 'selectCommoditiesWithHighQuantity' (queries.qry 파일에 정의된) 쿼리로 quantity > 60인 모든 Commodity asset 기록을 리턴합니다. 이벤트는 생략하며 해당 Commodity를 AssetRegistry에서 제거합니다.
Step Two: Create a query definition file
이 쿼리는 queries.qry 파일 내 정의된 트랜잭션 처리 로직에 의해 사용됩니다. 각 쿼리 엔트리는 리소스 및 어느 쿼리가 실행될지를 결정하는 기준을 정의합니다.
1. tutorial-network 폴더 내, queries.qry파일을 생성하세요.
2. queries.qry 파일 내 아래 코드를 붙여넣으세요.
/** Sample queries for Commodity Trading business network
*/
query selectCommodities {
description: "Select all commodities"
statement:
SELECT org.example.mynetwork.Commodity
}
query selectCommoditiesByExchange {
description: "Select all commodities based on their main exchange"
statement:
SELECT org.example.mynetwork.Commodity
WHERE (mainExchange==_$exchange)
}
query selectCommoditiesByOwner {
description: "Select all commodities based on their owner"
statement:
SELECT org.example.mynetwork.Commodity
WHERE (owner == _$owner)
}
query selectCommoditiesWithHighQuantity {
description: "Select commodities based on quantity"
statement:
SELECT org.example.mynetwork.Commodity
WHERE (quantity > 60)
}
3. queries.qry 파일을 저장하세요.
Step Three: Regenerate your business network archive
비즈니스 네트워크 내 파일을 변경한 후, 비즈니스 네트워크는 비즈니스 네트워크 아카이브 (.bna)로 리패키징되어 하이퍼레저 패브릭 객체에 재배포되어야 합니다. 배포된 네트워크를 업그레이드 하기 위해서는 새로운 버전 및 버전 번호가 필요합니다.
1. tutorial-network 폴더에서 package.json 파일을 여세요.
2. version 속성을 0.0.1에서 0.0.2로 업데이트하세요.
3. 커맨드라인을 사용해 tutorial-network폴더로 이동하세요.
4. 아래 명령어를 실행하세요.
composer archive create --sourceType dir --sourceName . -a tutorial-network@0.0.2.bna
Step Four: Deploy the updated business network definition
우리는 수정된 네트워크가 블록체인의 가장 최신 버전이 되도록 배포해야 합니다. 우리는 이미 배포된 비즈니스 네트워크를 업데이트 하기 위해 새로 생성된 비즈니스 네트워크 아카이브 파일을 사용하고 있습니다. 이는 developer tutorial에서 사용한 것과 동일한 비즈니스 네트워크 이름을 갖고 있습니다.
1. 터미널로 이동해 tutorial-network@0.0.2.bna 파일을 포함하고 있는 디렉토리로 이동하세요.
2. 업데이트된 비즈니스 네트워크를 설치하기 위해 아래 명령어를 실행하세요.
composer network install --card PeerAdmin@hlfv1 --archiveFile tutorial-network@0.0.2.bna
3. 네트워크를 새 버전으로 업그레이드하기 위해 아래 명령어를 실행하세요.
composer network upgrade -c PeerAdmin@hlfv1 -n tutorial-network -V 0.0.2
4. 아래 명령어를 실행하기 전 현재 비즈니스 네트워크의 버전을 확인하세요.
composer network ping -c admin@tutorial-network | grep Business
Step Five: Regenerate the REST APIs for the updated Business Network
우리는 이제 새로 업데이트된 비즈니스 네트워크와 추가된 쿼리를 통합하고, 이 비즈니스 네트워크용 REST API를 노출시킬 것입니다.
1. 커맨드라인을 사용해 tutorial-network 폴더로 이동하세요.
2. REST 서버를 실행하기 위해 아래 명령어를 실행하세요.
composer-rest-server
3. 카드 이름에 admin@tutorial-network를 입력하세요.
4. 생성된 API에서 네임스페이스를 사용할 지 물으면 'never use namespaces'를 선택하세요.
5. 생성된 API를 보호할지 물으면 No를 선택하세요.
6. 이벤트 발행이 가능하게 할지 물으면 Yes를 선택하세요.
7. TLS security를 사용할지 물으면 No를 선택하세요.
Step Six: Test the REST APIs and create some data
웹 브라우저를 열어 http://localhost:3000/explorer 로 이동하세요. LoopBack API 익스플로러 화면이 보일 것입니다. 이는 생성된 REST API를 확인하고 테스트할 수 있게 해줍니다.
우리는 Query라고 적힌 REST Endpoint가 추가된 것을 확인할 수 있습니다. 아래로 내려가면 tutorial-network 비즈니스 네트워크에 정의한 REST Query operation 리스트가 나옵니다.
계속 진행하기 전, 우리는 쿼리를 충분히 검증할 수 있는 데이터를 생성해야 합니다. 제공된 JSON 샘플 데이터를 사용해 REST API를 사용하는 3개의 Trader(참가자)와 몇몇 Commodities(자산)을 생성하세요.
1. 먼저 REST 익스플로러에 있는 'Trader'를 클릭한 후 /Trader에 있는 'POST' 함수를 클릭하세요. 그리고나서 스크롤을 아래로 내리면 파라미터 섹션이 있습니다. 아래 Trader 객체를 생성하세요.
{
"$class": "org.example.mynetwork.Trader",
"tradeId": "TRADER1",
"firstName": "Jenny",
"lastName": "Jones"
}
2. 참가자 생성을 위해 'Try it out'을 클릭하세요. 아래로 스크롤하면 'Response Code'가 나오는데, 이는 200 (SUCCESS)이어야 합니다.
3. 아래 JSON을 복사해 또 다른 trader를 생성하세요.
{
"$class": "org.example.mynetwork.Trader",
"tradeId": "TRADER2",
"firstName": "Jack",
"lastName": "Sock"
}
4. 아래 JSON을 복사해 세 번째 trader를 생성하세요.
{
"$class": "org.example.mynetwork.Trader",
"tradeId": "TRADER3",
"firstName": "Rainer",
"lastName": "Valens"
}
5. 이제 스크롤 맨 위로 올라가 REST 익스플로러에 있는 'Commodity' 객체를 선택하세요.
6. POST를 선택하고 스크롤을 아래로 내려 파라미터 섹션으로 이동하세요. 위에서 한 것과 동일하게 두 개의 Commodity 자산을 생성하되, 하나는 TRADER1이 또 다른 하나는 TRADER2가 소유하도록 합니다.
{
"$class": "org.example.mynetwork.Commodity",
"tradingSymbol": "EMA",
"description": "Corn",
"mainExchange": "EURONEXT",
"quantity": 10,
"owner": "resource:org.example.mynetwork.Trader#TRADER1"
}
{
"$class": "org.example.mynetwork.Commodity",
"tradingSymbol": "CC",
"description": "Cocoa",
"mainExchange": "ICE",
"quantity": 80,
"owner": "resource:org.example.mynetwork.Trader#TRADER2"
}
Step Seven: Perform queries using the commodity trading REST API explorer
이제 몇몇 자산과 참가자가 생성되었으므로 우리는 생성된 쿼리 REST operation을 사용해 쿼리를 테스트할 수 있습니다.
Perform a simple REST query
이제 우리는 자산과 참가자가 있으므로 쿼리를 실행해 볼 수 있습니다.
실행해볼 수 있는 가장 단순한 REST 쿼리는 named query인 selectCommodities입니다.
'Query' REST Endpoint 탭을 확장해 모델 내 정의된 named query들을 볼 수 있습니다.
이 쿼리들은 이제 REST 쿼리로 노출되며 /GET operation이 생성됩니다. 쿼리에 대산 설명 (우리가 모델 정의에 작성한) 은 오른쪽에 보여집니다.
1. selectCommodities 쿼리 탭을 확장하세요.
2. 'Try it Out' 버튼을 클릭하세요.
그러면 모든 존재하는 Commodity들이 리턴될 것입니다. - 2개의 자산이 리턴되어야 합니다.
Perform Filtered REST Queries
이제 교환을 통해 이뤄진 모든 Commodity를 선택해 봅시다. - 예를 들어 메인 거래인 'EURONEXT'
1. query endpoint탭을 확장하고 'selectCommoditiesByExchange'를 선택한 후 스크롤을 아래로 내려 파라미터 섹션으로 이동하세요.
2. 'Exchange' 파라미터에 'EURONEXT'를 입력하세요.
3. 'Try it Out'을 클릭하세요.
결과는 'EURONEXT'에 의해 교환된 commodity만을 반환하며 이는 response body에 담겨있습니다.
Perform Transaction update using results from naemd Query
마지막으로, 우리가 쿼리 파일에 정의한 Quantity > 60 이상인 Commodity를 선택하는 간단한 쿼리를 회상해봅시다. 쿼리는 트랜잭션 함수를 사용할 때 매우 강력합니다. 쿼리를 사용하면 트랜잭션 로직은 자산 혹은 참가자 집합을 업데이트하거나, 생성/삭제 등의 행위를 수행할 수 있습니다.
우리는 selectCommoditiesWithHighQuantity 쿼리를 removeHighQuantityCommodities 트랜잭션에서 사용합니다. 만일 이 /GET operation을 REST 익스플로러에서 실행시키면, quantity가 60보다 큰 자산을 볼 수 있습니다.
이제 high quantity Commodities를 삭제하기 위해 쿼리를 사용해 봅시다.
먼저 얼마나 많은 Commodity들이 존재하는지 확인하세요 ('Commodity' /GET operation 사용). 그러면 적어도 두 개의 Commodities를 확인할 수 있을 것이며 그 중 하나 (Cocoa)는 quantity가 60보다 클 것입니다.
REST Endpoint의 /selectCommoditiesWithHighQuantity를 클릭한 후 /GET을 클릭하고 스크롤을 아래로 내려 'Try it Out' 버튼을 누르세요. 실제 쿼리를 확인해봅시다. 기준을 만족시키는 하나의 Commodity가 있을 것입니다.
이제 어느 Commodity를 삭제할 지 결정하는 'High Quantity' 쿼리 정의를 사용해 REST 트랜잭션을 실행시켜봅시다.
RemoveHighQuantityCommodities REST Endpoint를 클릭해 /POST operation이 보이게 하세요.
POST를 클릭하고 스크롤을 아래로 내리면 파라미터 섹션이 보입니다. 'Try it Out'을 클랙하세요.
참고: 'data' 섹션에 있는 어떤 데이터도 입력하지 않아도 됩니다.
스크롤을 아래로 내리면 트랜잭션 처리 함수 내부적으로 'remove'를 호출 (블록체인 트랜잭션) 하고 world state를 업데이트하는 트랜잭션 id를 볼 수 있습니다. - Reponse Code는 200dldjdi gkqslek.
마지막으로 우리 Commodities의 status를 확인해 봅시다. 'Commodity' REST Operation으로 돌아가 다시 한번 'Try it Out' 버튼을 사용해 /GET operation을 수행해보세요.
결과는 Commodidy 자산인 'Cocoa'가 사라져있을 것입니다. 즉, Commodity 자산의 quantity 가 60 이하인 것만 남아 있을 것입니다. 여기서는 'Corn'이 남아있습니다. named query는 트랜잭션 업데이트를 수행하고 (high quantity commodities를 제거하는) 비즈니스 로직을 수행했습니다.
'● STUDY ● > Hyperledger' 카테고리의 다른 글
Deploying a Hyperledger Composer blockchain business network to Hyperledger Fabric (multiple organizations) (0) | 2019.07.19 |
---|---|
Deploying a Hyperledger Composer blockchain business network to Hyperledger Fabric for a single organization (0) | 2019.07.18 |
Hyperledger Caliper 시작하기 (0) | 2019.07.16 |
Composer Developer Tutorial (0) | 2019.07.15 |
Fabric Performance and Scalability & Conclusion (0) | 2019.07.14 |