Hyberledger Composer로 처음 해보는 블록체인 with 샘플코드

in #blockchain7 years ago (edited)

얼마전에 포스팅했던 글에서 이야기했듯이 현재 블록체인(!= 코인) 기술을 배워보는 중이다. 공부하고 있는 코세라의 블록체인 관련 강좌가 Hyberledger 라는 리눅스 파운데이션에서 만든 오픈소스 블록체인 솔루션을 사용하고 있는데, 3주차에 들어서면서 처음으로 예제코드를 동작시켜 보고 대충 감을 잡을 수 있는 기회가 있어서 공유해본다.

모델 파일, asset과 participant, 그리고 트랜잭션 모델을 정의한다. 잘 알려진바와 같이 블록체인이라는 자체의 개념은 open(public) ledger 다. ledger 즉 한국말로는 장부? 정도가 될 것 같은데, 그래서 장부에 뭔가가 기록될 때는 들어오는 것의 종류(돈, 물품, 등등) 즉 asset, 그리고 내가 A랑 거래를 해서 A가 나한테 뭘 준건지 아니면 내가 뭔가를 A한테 준건지를 기록할 수 있도록 거래에 참여한 사람, 즉 participant, 마지막으로 누가 누구한테 뭘 줬는지의 거래 자체를 정의할 수 있는 트랜잭션이 필요하다.

/**
 * Sample business network definition.
 */
namespace org.acme.sample

asset SampleAsset identified by assetId {
  o String assetId
  --> SampleParticipant owner
  o String value
}

participant SampleParticipant identified by participantId {
  o String participantId
  o String firstName
  o String lastName
}

transaction SampleTransaction {
  --> SampleAsset asset
  o String newValue
}

event SampleEvent {
  --> SampleAsset asset
  o String oldValue
  o String newValue
}

모델링을 하고 나면 그 다음에 필요한 것은 트랜잭션이 어떻게 처리되어야 하는지를 코딩한 트랜잭션 스크립트가 필요하다. 뭔가 길어 보이지만 코딩에 대한 경험이 조금이라도 있는 사람이라면 이 코드가 트랜잭션으로부터 넘겨받은 데이터 중 새로운 데이터값을 받아서 해당 에셋 레지스트리의 값을 업데이트하는 코드라는 걸 알 수 있다.

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Sample transaction processor function.
 * @param {org.acme.sample.SampleTransaction} tx The sample transaction instance.
 * @transaction
 */
function sampleTransaction(tx) {

    // Save the old value of the asset.
    var oldValue = tx.asset.value;

    // Update the asset with the new value.
    tx.asset.value = tx.newValue;

    // Get the asset registry for the asset.
    return getAssetRegistry('org.acme.sample.SampleAsset')
        .then(function (assetRegistry) {

            // Update the asset in the asset registry.
            return assetRegistry.update(tx.asset);

        })
        .then(function () {

            // Emit an event for the modified asset.
            var event = getFactory().newEvent('org.acme.sample', 'SampleEvent');
            event.asset = tx.asset;
            event.oldValue = oldValue;
            event.newValue = tx.newValue;
            emit(event);

        });

}

그 다음에 필요한 것은 바로 접근제어(access control)이다. 블록체인을 이용한 최초의 쓸만한(?) 레퍼런스인 비트코인은 '익명성' 이 특정이자 장점으로까지 내세워지고 있지만, 사실 블록체인 자체는 open ledger라는 걸 다시 한번 생각해 본다면 블록체인에 기록되는 트랜잭션은 사실 누가 누구와 무얼 거래하는지가 정확하게 기록이 되어야 하고 그래야 의미가 있다.
비트코인은 그 익명성 때문에 마약 혹은 무기거래상들이 대금결제시에 본인들의 신분을 숨기기 위한 결제수단으로 널리 사용되었었다는 건 잘 알려진 이야기다.

아무튼 그래서 participant에 대한 정부가 필요한 동시에 이 블록체인 '네트워크'에 접근하는 participant들이 무엇을 할 수 있고 무엇을 할 수 없는지를 컨트롤 할 필요성이 있다. 흔히 블록체인 하면 모든 것들이 블록체인 자체에 기록되고 누구나 그 거래내용을 볼 수 있다 라는 식으로 이야기가 되고 있지만 실제로는 거래 당사자들만이 해당 내용을 볼 수 있어야 하거나 아니면 특정 participant만 블록체인의 내용을 갱신할 수 있고 다른 participant들은 내용 보기만 가능하다던가 하는 권한조정이 필요하다.

즉 블록체인 자체에는 '모든 것들' 이 기록되지만 그렇다고 모두가 그걸 볼 수 있다거나 하는 이야기는 아니라는 것. A와 B가 주택 매매 거래를 했고 그게 만약 주택거래 데이터를 다루는 블럭체인 네트웤에 기록된다면 해당 매매와 전혀 상관없고 그 집의 주인이거나 채권자도 아닌 전혀 다른 C가 해당 트랜잭션을 볼 권리가 있어야 하는가? 볼 필요가 있을까?

/**
 * Sample access control list.
 */
rule EverybodyCanReadEverything {
    description: "Allow all participants read access to all resources"
    participant: "org.acme.sample.SampleParticipant"
    operation: READ
    resource: "org.acme.sample.*"
    action: ALLOW
}

rule EverybodyCanSubmitTransactions {
    description: "Allow all participants to submit transactions"
    participant: "org.acme.sample.SampleParticipant"
    operation: CREATE
    resource: "org.acme.sample.SampleTransaction"
    action: ALLOW
}

rule OwnerHasFullAccessToTheirAssets {
    description: "Allow all participants full access to their assets"
    participant(p): "org.acme.sample.SampleParticipant"
    operation: ALL
    resource(r): "org.acme.sample.SampleAsset"
    condition: (r.owner.getIdentifier() === p.getIdentifier())
    action: ALLOW
}

rule SystemACL {
  description:  "System ACL to permit all access"
  participant: "org.hyperledger.composer.system.Participant"
  operation: ALL
  resource: "org.hyperledger.composer.system.**"
  action: ALLOW
}

rule NetworkAdminUser {
    description: "Grant business network administrators full access to user resources"
    participant: "org.hyperledger.composer.system.NetworkAdmin"
    operation: ALL
    resource: "**"
    action: ALLOW
}

rule NetworkAdminSystem {
    description: "Grant business network administrators full access to system resources"
    participant: "org.hyperledger.composer.system.NetworkAdmin"
    operation: ALL
    resource: "org.hyperledger.composer.system.**"
    action: ALLOW
}

위의 코드를 대충 보면 억세스 컨트롤을 위한 룰을 여러가지 정의하는데, 어떤 participant를 위한​ 룰인지, 그리고 어떤 오퍼레이션에 대한 것인지(읽기/쓰기/삭제/전부? 등등), 그리고 어떤 리소스에 대한 것인지, 그리고 그걸 ALLOW한다는 내용. 예제 코드에는 나와 있지 않지만 액션에는 ALLOW 뿐만 아니라 DENY도 가능하다.

자 이렇게 하고 나면 위에서 정의했던 participant와 asset의 실제 데이터가 필요하다.
대략 다음과 같은 걸 participant registry에 등록하고 ( 처음 정의는 OOP에서 클래스 정의를, 그리고 이건 인스턴스를 생성한다고 생각하면 된다)

{
  "$class": "org.acme.sample.SampleParticipant",
  "participantId": "0828",
  "firstName": "Tobias",
  "lastName": "Hunter"
} 

그 다음에는 asset registry에다가 다음과 같은 SampleAsset을 생성한다

{
  "$class": "org.acme.sample.SampleAsset",
  "assetId": "assetId:1",
  "owner": "resource:org.acme.sample.SampleParticipant#0828",
  "value": "new value"
}

그리고 나서 트랜잭션을 실행시키려고 하면 다음과 같은 형태의 트랜잭션이 블록체인 네트웤에 전송될 거라는 JSON 포맷을 보여준다.

{
 "$class": "org.acme.sample.SampleTransaction",
 "asset": "resource:org.acme.sample.SampleAsset#assetId:1",
 "newValue": "new value",
}

실제로 실행이 되고 나면 처리된 트랜잭션들의 내용을 볼 수 있는데, 방금 막 실행된 트랜잭션을 살펴보면 위에서 봤던 class, asset, 그리고 newValue외에 트랜잭션 id와 트랜잭션이 실행된 시간의 타임스탬프가 추가된 것을 알 수 있다.

{
 "$class": "org.acme.sample.SampleTransaction",
 "asset": "resource:org.acme.sample.SampleAsset#assetId:1",
 "newValue": "new value",
 "transactionId": "a13dbf66-b1fb-416a-9fb3-eaa13940efc4",
 "timestamp": "2018-01-17T06:01:48.868Z"
}

뭔가 사람들이 블록체인이라고 이야기할 때 언뜻 뭔가 거창해 보이고 복잡할 것 같지만 실제로 이미 그런 개념들을 구현하고 추사화시킨 Hyperledger같은 블록체인 기술을 쓰면 사실상 코딩하는 입장에서는 그냥 데이터베이스 엔티티(혹은 OOP의 클래스/엔티티) 모델링해서 정의하고, 그것의 인스턴스를 만들어서 데이터베이스에 업데이트하는 일련의 것들과 크게 다르지 않아 보인다.

다만 블록체인 레이어에서 그 트랜잭션들을 모든 participant들이 동일하게 받아볼 수 있도록 트랜잭션을 관리하고 접근제어를 하고 그외 필요한 것들을 알아서 해 줄 터인데, 블록체인 기술의 장점을 취해서 실제 비즈니스 네트웤에 적용할 사람이라면 개념 정도만 이해하면 됐지 그 세세한 모든 것들을 다 알아야 할 필요는 없다. 마치 자동차 경주 선수가 운전만 잘하면 됐지 굳이 자동차의 엔진과 흡배기와 그 모든 것들을 다 알아야만 하는 것은 아니듯이 말이다.

자, 여기까지가 내 생애 최초의 블럭체인 관련 코딩 경험이다. 진도를 나가면서 또 공유할만하다 싶은 것들은 별도의 포스팅을 통해서 공유할 예정인데, 다만 이런 포스팅을 하면서 자그만 바램이 있다면 사람들이 블럭체인이라는 기술의 핵심이 정말로 무엇이고 뭘 하기 위한 것들인지, 그리고 비록 가상화폐(암호화폐, 버추얼 화폐, 코인, 기타 뭐라 부르든) 가 그 기반에 블록체인 기술을 쓰고는 있지만 사실 블록체인과 그 코인은 크게 상관이 없는 기술이라는 걸 이해하는데 도움이 되었으면 하는 것이다.

물론 코인을 주고받는 행위가 보내는 사람과 받는 사람이 있고(participant), 에셋이 있으며(비트코인 혹은 그 뭐든간에, 그리고 금액), 그리고 그것들의 거래내역인 트랜잭션이 있기 때문에 ledger(장부)에 기록되어 공유되는데 아주 적절한 use case이긴 하지만, 그 외에 또 코인을 채굴한다든지 해시를 쓴다든지 뭐 기타 등등의 것들은 사실 암호학이라든가 암호화폐쪽과 보다 더 밀접한 관계가 있는 내용이고 엄밀히 말한다면 블록체인 자체와는 아무런 상관이 없다.

그냥 '암호화폐' 라는 걸 사람들이 거래를 해야 하는데 그걸 중앙금융기관등을 이용하지 않고 서로 주고받았다는 걸 기록하기에 마침 적절한 블록체인 이라는 기술이 있어서 그 위에다가 암호화폐 거래의 트랜잭션을 태우고 있는 것. 그러니 어디가서 무식하게 "블록체인 = 코인" 이라는 이야기는 하지 말자. 블록체인상의 트랜잭션에는 어떤 에셋이든 올라갈 수 있다. 블록체인은 트랜스포트 레이어이고 코인은 그냥 그 위에서 옮겨다니는 payload일 뿐이다. ㅇㅋ?

Sort:  

좋은 글인데 이해하려면 공부가 더 필요한 흑
감사합니다!

어섭쇼 :D 스팀잇 계정오픈하셨군요 ㅎㅎ

지식 공유 감사합니다. 집에 가서 일독해 보겠습니다.

들러주셔서 감사합니다. :D