R3 Corda의 주요 컨셉 이해하기
Understanding the key concepts of R3 Corda
이번에 R3 Corda를 공부할 일이 생겨서 여러 문서를 검색하다가, 한국어로 된 글이 거의 없다는 사실을 발견했습니다. 하이퍼렛저도 문서가 많이 부족하지만, R3 Corda는 백종찬님께서 브런치에 작성하신 글을 제외하고는 한국어 문서를 거의 찾아볼 수 없었습니다.
그래서 이번에는 R3 Corda에 대한 주요 컨셉에 대해 간략하게 소개하는 시간을 가지고자 합니다. 내용이 길어서 총 2부로 글을 작성하고자 합니다. 해당 글은 Corda의 공식 문서 중 Key Concepts 부분을 바탕으로 제가 학습하고 일부를 각색한 것입니다.
R3 Corda란 무엇인가?
기존의 블록체인이 탈중앙화를 통한 거래를 구현하고자 한다면, 코다는 데이터의 보관 위치에 상관없이 다수가 금융계약의 변화를 상호 간 컨트롤할 수 있는 플랫폼을 구현하고자 한다. — Jeff Paik,백종찬님 (https://brunch.co.kr/@jeffpaik/27)
컨소시엄 블록체인의 대표적인 예시로 하이퍼렛저 프로젝트와 R3 Corda가 주로 꼽히고는 합니다. R3 Corda는 특히 금융권에서 컨소시엄 블록체인을 활용하고자 하는 수요를 고려하여 제작한 블록체인 플랫폼입니다. R3는 기존의 퍼블릭 블록체인 플랫폼은 금융권에서 사용하기에 프라이버시 문제, 확장성 문제, 법률적 이슈 부재, 그리고 결제 완결성의 한계 때문에 사용하기 어렵다는 평가를 내렸습니다.
따라서 R3는 코다라는 새로운 플랫폼을 만든 후 이를 오픈소스화했습니다. 엄밀히 말하면 R3는 분산원장의 성격을 띄고는 있으나 엄밀한 정의에 의한 블록체인은 아니라고 말할 수 있습니다. 네트워크 참여자들 간에 필수적으로 정보가 공유될 필요는 없으며 거래 상대방이나 참여 기구만 해당 데이터를 열람할 수 있기 때문입니다.
하지만 보증인 제도와 같은 부분에서 PBFT 알고리즘을 활용할 수 있는 등 여타의 블록체인이 지니고 있는 특성을 많이 도입하여 제작되어진 플랫폼입니다. 앞으로 R3 Corda가 어떠한 기술적 특징이 있는 지 간략하게 소개하는 시간을 가지고자 합니다.
R3 Corda Network 이해하기
3줄 요약
- Corda Network는 Corda와 CorDapps를 구동하는 노드들로 이루어짐
- Corda Network는 허가형 (permissioned) 블록체인이며 문지기 (doorman) 권한을 가진 노드가 접근 권한을 통제함
- 노드 간의 통신은 점대점 구조 (point-to-point) 로 이루어짐
네트워크 구조
Corda Network는 사전에 협의된 노드끼리의 통신망이라고 할 수 있습니다. 각각의 노드는 Java EVM 환경에서 구동되는 Corda 서비스와 CorDapps라고 불리는 디앱을 구동할 수 있습니다.
노드 간의 모든 통신은 직접 연결되며, 미들웨어의 메시지 전달 시 표준 프로토콜로 활용되는 AMQP (Advanced Message Queuing Protocol) 1.0을 활용합니다. 이 과정에서 메시지를 TLS 암호화하여 전송합니다. 따라서 모든 메시지는 이해 관계자끼리만 공유되며, 네트워크 전체에 메시지를 전파하지 않습니다. (no global broadcasts)
각각의 네트워크는 Network Map Service라는 것을 지원하는데, 네트워크 상에 있는 노드와 통신할 수 있도록 모든 노드에 IP 주소를 부여하는 서비스입니다. 해당 서비스는 노드의 신원을 보증하는 역할 역시 도맡게 됩니다. 일종의 전화번호부 역할을 한다고 생각하시면 됩니다. 네트워크 상의 모든 노드에 연락할 수 있는 정보가 담겨 있습니다.
메시지를 받는 노드가 오프라인 상태라면 대기열 (queue) 에 있다가 온라인이 되면 메시지가 전달됩니다. 이는 이메일과 비슷하다고 생각하시면 됩니다. 따라서 모든 메시지는 수신자를 명시해야 하며, 발신자는 수신자와 수신자가 보게 될 내용을 모두 컨트롤할 수 있습니다.
문지기 (The doorman)
Corda Network는 사설 네트워크의 특징을 지니고 있습니다. 각각의 네트워크는 모두 문지기 역할을 하는 노드가 있어서 네트워크 내부의 노드가 지켜야 하는 규정을 강제하고 신규 네트워크 참여자의 신원을 확인하는 (KYC: know-your-customer) 과정을 거치게 됩니다.
네트워크에 참여하기 위해서는 모든 노드는 반드시 문지기 노드와 사전 연략을 취하고 필요한 정보를 공유해야 합니다. 문지기 노드는 네트워크에 새로 참여하고자 하는 노드를 네트워크에 참여시킬 때 Trust Root CA 인증서를 발급합니다. 해당 인증서는 네트워크 내부에서 다른 참여노드와 통신할 때 해당 노드의 신원을 인증하는 역할을 합니다.
네트워크를 시각화해서 보여드린다면 다음과 같습니다.
네트워크 서비스
노드는 다음과 같은 역할을 수행할 수 있습니다.
- 보증인 역할 (notary services): 최소 한 개 노드 이상이 될 수 있고 노드 갯수에는 제한이 없습니다. 보증인은 트랜잭션의 유일성을 최종적으로 확인하는 역할을 맡으며 트랜잭션의 유효성을 검증하는 역할을 합니다. 보증인 노드는 특정한 하나의 노드와 함께 통신하거나, 혹은 여러 개의 노드 묶음과 함께 통신할 수도 있습니다.
- 오라클 역할 (oracle services): 있어도 되고 없어도 되는 노드입니다. 실제 세계에서 일어난 현상을 제대로 반영하여 트랜잭션에 올렸다는 사실을 검증하는 역할입니다. 오라클 문제를 해결하기 위해 나타난 노드 역할입니다.
장부 이해하기
2줄 요약
- 모든 장부는 노드에 따라 볼 수 있는 것이 다르다. 특정 노드가 다른 노드와 어떤 교집합에 있는 지에 따라 내용이 모두 다르다.
- 교집합에 있는 노드는 서로 같은 내용을 공유하고 있으며 이는 공통된 장부 상에 올라와 있다.
소개
Corda에서는 데이터를 중앙에서 관리하는 주체가 없습니다. 그 대신에, 각각의 노드는 자신들이 알고 있는 데이터를 별도의 데이터베이스에 관리합니다. 결과적으로 하나의 노드는 전체 장부의 일부만을 확인할 수 있게 됩니다. 어떠한 노드도 전체 데이터를 열람할 수 없습니다.
예시를 하나 들어보겠습니다. 5개의 노드가 통신하는 네트워크가 있다고 생각해봅시다. 벤 다이어그램으로 표현하면 이해하기 더욱 쉬울 것입니다. 각각의 원 사이에 나타난 교집합은 노드 간에 공통된 사실을 공유한다는 의미입니다.
여기서 Carl과 Demi 그리고 Ed가 3번 항목을 서로 공유하고 있다는 사실을 발견할 수 있습니다. 이와 달리 Alice와 Bob은 3번 항목에 대해 접근할 수 없습니다.
Corda는 네트워크 상에서 특정한 사실을 서로 공유한 노드들끼리만 해당 사실에 대해 접근할 수 있도록 합니다. 해당 사실과 전혀 관계없는 노드는 정보에 절대 접근할 수 없습니다. 정보를 서로 공유하게 되는 노드들은 특정 사실의 업데이트를 동시에 받아봅니다. 다시 말해서 공통된 버전의 사실을 실시간으로 공유하게 되는 것입니다.
위의 그림을 보면, Alice와 Bob은 정확히 같은 사실에 대하여 업데이트를 동시에 받아보게 됩니다. 그림에서는 1과 7이 되겠습니다. Alice는 Bob의 6번과 5번 정보를 접근할 수 있는 권한이 존재하지 않습니다. 따라서 해당 정보는 공유되지 않습니다.
신원 인증
4줄 요약
- Corda Network에 참여하는 모든 노드는 자신의 신원을 사전에 인증해야 합니다. 해당 신원은 법적 지위를 가지거나 서비스 내부에서 신상을 보증하는 역할을 합니다.
- 모든 신원은 X.509 인증서에 의하여 보증되어야 하며 해당 인증서는 문지기 노드 또는 신원이 확실하게 보장된 다른 노드가 서명한 것이어야 합니다.
- 자신의 신원을 인증한 노드는 Network Map에 등재되는 주소를 발급받습니다. 이를 통해 다른 노드와 함께 통신할 수 있게 됩니다.
- 비밀을 유지해야 하는 프라이빗 노드는 통신을 해야 하는 당사자들끼리만 해당 주소가 공개됩니다.
네트워크의 두 가지 신분
Corda에 참여하는 모든 노드는 자신의 신원을 입증해야 합니다. 네트워크 상에서 자신의 신분을 인증한 노드는 자신이 참여하는 서비스나 기구의 법률적 권리와 그 책임을 모두 짊어지게 됩니다. Corda에서는 두 가지 신원을 모두 입증해야 합니다.
- 법률적 신원: 실제로 자신이 누구인가를 인증해야 하는 것을 의미합니다. 일종의 KYC (know-your-customer) 라고 생각하셔도 됩니다. 자신의 실제 신원을 인증했기 때문에 이에 합당한 역할과 책임이 생깁니다. 예를 들어 금융거래를 실제로 네트워크 상에서 이행할 수 있게 됩니다.
- 서비스 신원: 서비스 내부에서 자신이 어떠한 역할을 하는 지에 대해 인증합니다. 법률적 신원은 자신의 실제 신분을 인증하는 것이라면 서비스 신원은 자신이 특정한 단체나 기구에서 어떠한 역할을 맡고 있는 지에 대해 인증하고 확인받는 것입니다.
예를 들어 홍길동은 대한민국 서울 출신의 1998년생임을 네트워크 상에 인증할 수 있을 것입니다. 이는 법률적 신원을 인증하는 것입니다. 이와 별개로 홍길동은 어느 단체의 회장직을 역임하고 있을 수도 있습니다. 해당 단체가 Corda를 활용하고 싶다고 한다면, 네트워크에 회장직을 인증하여야 할 것입니다. 이는 서비스 신원을 인증하는 것입니다.
따라서 Corda의 분산 네트워크에서 하나의 노드가 여러 개의 네트워크에 참여할 수 있게 됩니다. Corda에 참여하는 모든 노드는 자신의 신원이 CompositeKeys
상에 올라가게 됩니다. 이는 서비스에 실제로 참여하고 있는 노드의 서명값을 모아둔 것입니다.
모든 노드는 자신의 신원을 공개할 수도 있고, 아니면 네트워크 상에서 자기 자신을 숨길 수도 있습니다. 이는 자신이 처음 네트워크에 가입했을 때 어떤 종류로 참여했느냐에 따라 달라지게 됩니다. 자신의 네트워크 신원은 X.509 인증서에 담기게 됩니다.
- 신원을 모두 공개하는 노드는 (well-known identities) 법적으로 효력이 있는 서비스를 활용할 수 있는 공개키를 부여받게 됩니다. 따라서 해당 노드에게 발급되는 인증서는 누구나 열람할 수 있습니다. 즉, 해당 노드의 존재 사실을 모든 노드가 확인할 수 있게 됩니다. 따라서 자신의 신원을 숨기고 비밀 통신을 해야하는 경우에는 적합하지 않습니다.
- 비밀 노드 (confidential identities) 는 자신의 신원을 꼭 확인해야만 하는 상대 노드에만 자신의 신분을 밝힐 수 있습니다. 해당 노드의 공개 키는 보증인 노드와 같은 제 3자에게도 보여질 수 있지만 노드의 이름과 X.509 인증서 제공은 철저하게 제한됩니다. 설령 제 3자가 암호화되지 않은 트랜잭션에 접근한다고 하더라도 비밀 노드에 대한 추가적인 정보가 주어지지 않는다면 해당 트랜잭션의 수신자 혹은 발신자가 누구인지 알 수 없습니다.
인증서
노드들은 반드시 공개키의 소유자가 누구인지 인지할 수 있어야 하며, 신원을 확인하는 과정에서 X.509 인증서가 사용됩니다. 첫 번째 노드가 공개 키와 개인 키를 만들고 문지기 노드에게 서명을 요청하는 인증서를 네트워크 상에 제출한다고 해봅시다. 문지기 노드는 신원을 확인하는 절차를 거친 다음에 해당 노드의 인증서를 최종적으로 발급하게 됩니다.
문지기 노드가 서명한 인증서는 해당 노드의 신원을 공식적으로 인증하는 문서 (Node Certificate Authority, CA) 가 됩니다. 문지기 노드가 서명한 CA를 발급받은 노드는 해당 인증서를 바탕으로 TLS 인증서를 포함한 두 개의 문서를 더 만들게 됩니다. 마지막으로 노드는 자신의 주소와 신원이 담긴 문서를 하나 만들어서 Network Map Service에 등록하게 됩니다.
서명된 인증서를 통하여 Corda Network를 이용하는 서비스는 공개 신원과 비공개 신원을 모두 활용할 수 있는 이점을 얻게 됩니다. 서비스의 판단에 따라 특정 노드의 등록 여부를 공개할 수도 있고 그러지 않을 수도 있습니다. 사업 상의 민감한 정보를 통신해야 할 경우에는 특정 노드의 신원을 공개하지 않는 편이 나을 수도 있을 것입니다. 혹은 특정한 노드만 공유할 수 있는 Network Map Service를 별도로 만들어서 비밀 노드와 서로 통신할 수도 있습니다.
이와 달리 공개 노드는 모든 신원이 네트워크 상에서 공개되기 때문에 비밀 정보를 공유하기에는 여러 가지 한계점이 있을 것입니다. 퍼블릭 메인넷을 활용하는 다른 블록체인과는 다르게 비밀 노드를 지정하고 해당 정보를 공유하지 않을 수도 있다는 점에서 R3 Corda는 차이점을 갖습니다.
상태
3줄 요약
- 하나의 상태는 장부 상에서 공유되고 있는 정보를 나타냅니다.
- 모든 상태는 현실 세계의 상황 변화를 반영합니다. 비트코인에서 차용된 UTXO 모델을 그대로 가져오는데, 이전 상태는 모두 장부 상에 기록되고 지워지지 않습니다. 대신 ‘처리됨' (historic) 으로 적히게 됩니다. 새로운 상태는 이전 상태를 복사한 후 해당 상태의 변화를 새롭게 기록해서 장부의 첫 장에 담기게 됩니다.
- 모든 노드의 기록은 장부 상에 저장되며 현재 상태를 검증할 수 있는 이전 상태의 모든 정보가 축적되게 됩니다.
개괄
하나의 상태는 특정 시점에서 트랜잭션의 참여자들끼리 공유된 정보를 나타냅니다. 이는 장부 상에 올라가므로 절대 수정이 불가능합니다. 모든 상태는 임의의 정보를 포함할 수 있으며 어떠한 종류의 정보도 반영할 수 있습니다. 주식 정보나 채권 정보, KYC 데이터, 신원 확인 정보 등 다양합니다.
주지할 점은 하나의 정보를 담기로 정해졌으면 다른 종류의 정보를 담기로 해당 상태가 변경될 수 없다는 점입니다. 예를 들어서 여러 상태를 담은 하나의 묶음이 시큐리티 토큰에 대한 소유권을 보여주는 상태들로 구성되었다고 해봅시다. 이 묶음이 갑자기 KYC 정보나 신원 정보를 담은 상태들의 묶음으로 바뀔 수 없다는 것입니다.
하나의 예시를 들어보겠습니다. Alice가 Bob에게 X달러를 빌렸다고 가정해봅시다. 아래의 그림을 참고해보도록 합시다.
위에 그림에서 표현되어 있는 상태 묶음에는 Alice가 Bob에게 10파운드를 빌렸다는 사실이 나와 있습니다. 위의 상태 묶음에는 빌린 사실 뿐만 아니라 해당 상태가 변화해온 과정 자체를 보여주는 정보들이 담겨있습니다.
상태의 변화 과정
모든 상태는 수정되거나 삭제될 수 없습니다. 하나의 상태 자체는 수정될 수 없으므로 현실 세계의 변화 과정을 직접적으로 반영할 수는 없습니다. 그 대신에, 상태가 누적되는 과정 (state sequence) 을 통해 현실을 드러냅니다.
하나의 상태가 새롭게 반영되어야 한다면, 이전 상태를 그대로 복사하여 새로운 상태를 만듭니다. 이전의 상태는 ‘처리됨' (historic) 으로 표시됩니다. 대신에 새로운 상태에는 이전의 상태에서 어떻게 변화되었는 지에 대해 기록을 한 후 상태의 묶음에서 맨 위에 보여지도록 합니다. 그리고 해당 상태를 최신의 상태라고 기록합니다.
따라서 상태의 변화 과정은 모두 장부 상에서 확인할 수 있게 됩니다. 최신 상태를 드러내는 상태를 검증하기 위해서는 장부 상에 기록된 이전 상태를 하나씩 뜯어보면 됩니다.
상태의 변화 과정을 담는 아래의 그림을 참고하면 도움이 될 것입니다.
상태의 기록 묶음
아까 언급하였듯, 모든 네트워크의 노드는 각자의 상태를 모두 기록하는 묶음 (vault) 이 있습니다. 이러한 묶음을 확인하면 최신 현황을 반영하는 상태가 어떠한 변화를 겪어왔는 지 알아낼 수 있습니다.
컨트랙트
3줄 요약
- 올바른 트랜잭션 (트랜잭션은 상태의 묶음) 은 컨트랙트의 인풋값과 아웃풋 값에 의하여 확인되어야만 합니다.
- 모든 컨트랙트는 Java나 코틀랭처럼 JVM을 지원하는 언어로 쓰여져야 합니다.
- 컨트랙트의 실행은 결정적이며 (deterministic) 트랜잭션의 최종 확정은 트랜잭션 내부의 내용이 올바른 지에 따라 정해집니다.
트랜잭션의 검증
트랜잭션은 모든 참여자의 서명이 있어야 올바르다고 할 수 있습니다. 하지만 특정한 트랜잭션이 필요한 모든 서명을 얻었다고 하더라도 계약의 내용 상으로 참이어야 올바른 트랜잭션이라고 말할 수 있습니다.
컨트랙트 상의 검증 (contract validity) 는 다음과 같은 사항을 일컫습니다.
- 모든 상태는 하나의 계약을 향하고 있어야 하며 또 컨트랙트의 내용과 합치해야 합니다.
- 컨트랙트가 트랜잭션을 입력값으로 받으면, 트랜잭션 내부의 상태가 컨트랙트의 규칙과 합치하여 이루어졌는지 검증합니다.
- 모든 트랜잭션은 컨트랙트의 입력 상태와 출력 상태가 모두 컨트랙트의 규칙과 내용 상에 부합하다고 판단될 때만 참이라고 인식됩니다.
설명한 이야기를 한 번 그림으로 나타내보겠습니다.
모든 컨트랙트는 JVM을 지원하는 언어로 쓰여져야 합니다. JVM으로 컨트랙트가 쓰여졌기 때문에 트랜잭션과 상태의 입력값, 출력값, 명령값, 시간에 대한 정보, 그리고 이와 관련된 부가 정보에 대한 모든 접근 권한을 가질 수 있게 됩니다. 상수와 변수의 지정, 함수의 호출에 대한 모든 실행을 할 수 있으며 유사한 정보를 하나로 묶어 그룹으로 만들 수도 있습니다.
컨트랙트의 규칙과 맞지 않는 트랜잭션은 장부 상에 업데이트되지 않습니다. 따라서 참여 노드끼리 컨트랙트 상으로 올바르지 않은 트랜잭션에 서명하기로 하더라도 장부 상에는 올라가지 않습니다. 이러한 과정을 통해 컨트랙트의 강제성이 실현되게 됩니다.
컨트랙트 샌드박스
모든 트랜잭션은 결정적 상태 (deterministic condition) 로 확증되어야 합니다. 모든 계약은 하나의 트랜잭션을 항상 승인하거나 또는 거절할 수만 있습니다. 또한 모든 트랜잭션은 해당 트랜잭션이 언제 실행되었는지에 대한 정보와 함께 컨트랙트가 실행할 때 담겨야 하는 정보의 양에 대한 서술이 반드시 존재해야 합니다. 이는 네트워크 상의 모든 노드가 장부의 업데이트를 승인하기 위한 필요조건에 해당합니다.
컨트랙트는 트랜잭션의 승인 여부를 판단하기 위해 결정적 샌드박스 (deterministic sandbox) 를 활용합니다. 해당 샌드박스는 비결정적 요소 (a source of non-determinism) 의 요소가 될 수 있는 라이브러리를 컨트랙트에 들어오지 못하도록 막습니다. 궁극적으로 트랜잭션을 검증할 때 필요한 정보만 컨트랙트에 담겨서 실행될 수 있도록 합니다.
컨트랙트의 한계점
컨트랙트 그 자체로는 실제 세계와의 접점을 가지기 쉽지 않습니다. 따라서 컨트랙트는 오직 내부의 정보를 바탕으로 트랜잭션을 검증합니다. (internal validity) 즉, 컨트랙트는 실제 외부 세계에서 합의한 사항에 대해서는 (사전에 컨트랙트에 조건으로 담기지 않은 이상) 확인할 수가 없습니다. 따라서 트랜잭션에 참가하는 노드들은 트랜잭션에 합의한 내용이 제대로 담겼는지에 대해 서로 확인하고 서명을 하여야 합니다.
오라클 문제와 법률 문제
언급했듯이 오라클 문제는 트랜잭션에 참가하는 당사자들끼리 결정되어야 하는 문제입니다. 그런데 트랜잭션이 실제 상황을 반영하는데 여러 가지 변수가 있을 수 있습니다. 예를 들어서 해당 트랜잭션이 환율을 반영해야만 하는 해외송금이라고 가정해봅시다. 이러한 경우에는 오라클 이슈를 해결해줄 수 있는 노드가 반드시 필요합니다. 혹은 법률적 문제를 담은 컨트랙트의 경우 법률적 문서를 컨트랙트 상에 작성한 다음 법률적 판단을 해줄 수 있는 노드가 지정될 수도 있습니다.
컨센서스
3줄 요약
- 장부에 등재되기 위해서는 트랜잭션은 반드시 유효성과 유일성을 입증해야 합니다.
- 유효성은 트랜잭션이 컨트랙트 상에서 유효하다는 것을 보여주는 것입니다.
- 유일성은 이중지불 문제에서 자유롭다는 것을 보여주는 것입니다.
두 가지 형태의 컨센서스
하나의 트랜잭션이 장부 상에 반영되기 위해서는 유일성과 유효성이 검증되어야만 합니다.
- 유효성 검증: 트랜잭션에 참여한 노드끼리 검증을 한 후 서로 서명을 합니다.
- 유일성 검증: 보증인 노드에 의하여 검증됩니다.
유효성 컨센서스
유효성 컨센서스란 컨트랙트의 입력 상태와 출력 상태에 의하여 승인이 되었는지를 판단하고, 또한 필요한 모든 참여자의 서명을 받았는지 확인하는 과정을 의미합니다. 즉, 거래 당사자들끼리 거래내용을 만족하고 올바르게 거래가 처리되었음을 확인하고 각각 서명하여 해당 트랜잭션이 유효하다는 것을 증명하는 행위입니다.
또한 트랜잭션 하나만을 처리해서도 안될 것입니다. 입력 트랜잭션 값을 생성시키도록 한 이전 트랜잭션의 모든 기록을 다 검사해야 합니다. 이를 체인 상을 걷는다 (walking the chain) 이라고 표현합니다. 예를 들어서 장기 국채에 대한 트랜잭션을 어느 노드가 제안했다고 해봅시다. 다음의 경우가 만족했을 때 채권의 거래가 유효하다고 볼 수 있습니다.
- 채권이 다른 사람들에게 거래되었을 때 해당 거래가 올바르게 성사되었는 지?
이 두 가지 경우를 모두 만족하는 지를 보기 위해서는 트랜잭션의 과거 기록을 모두 살펴보아야 합니다. 이 과정을 도표로 시각화하면 다음과 같습니다.
트랜잭션 하나를 검증할 때, 트랜잭션을 검증해야 하는 노드가 해당 트랜잭션의 검증해야 하는 모든 기록을 보유하고 있지 않을 수도 있습니다. 이러한 경우에, 해당 노드는 트랜잭션을 체인에 올리고자 하는 사람에게 자신이 보유하지 못한 트랜잭션의 기록을 요구합니다. 트랜잭션을 체인에 올리고자 제안한 사람은 해당 트랜잭션을 과거에 성사시킬 때 트랜잭션의 과거 기록을 확인했을 것입니다. 따라서 해당 노드는 트랜잭션의 전체 기록을 가지고 있을 것입니다.
유일성 컨센서스
만약 Bob이 1백만 달러의 시중 은행의 예금을 들고 있다고 해봅시다. Bob은 두 개의 트랜잭션을 만들고자 합니다.
- 1백만 달러를 Charlie에게 주고 80파운드를 받는 경우
- 1백만 달러를 Dan에게 주고 90유로를 받는 경우
이 두 가지 트랜잭션에 대하여 참여자들이 모두 합의했다고 하더라도, 이중지불 문제로 인하여 트랜잭션이 올바르다고 말할 수 없습니다. Bob은 그의 1백만 달러를 “두 번” 이나 사용하였기 때문입니다. 그리고 영국 파운드와 유로를 동시에 받았습니다. 이 상황을 시각화하여 표현하면 다음과 같습니다.
이러한 상황을 막기 위해, 해당 트랜잭션은 반드시 유일성을 증명해야 합니다. 오로지 한 번만 트랜잭션이 일어났다는 것을 보여주어야 한다는 의미입니다. 자신이 거래를 두 번이나 일으키지 않았다는 사실은 자신이 증명할 수는 없고, 대신 보증인 노드 (notary) 가 증명하게 됩니다.
보증인 노드
3줄 요약
- 보증인 노드는 이중 지불이 일어나지 않았다는 사실을 보증하여 유일성을 검증합니다.
- 보증인 노드는 트랜잭션을 검증하여 유효성을 검증할 수 있습니다다.
- 네트워크는 다양한 보증인 노드를 선택할 수 있고, 이들끼리 합의 알고리즘을 별도로 정할 수도 있습니다.
개괄
보증인 노드란 유일성을 검증해주는 노드를 의미합니다. 주어진 트랜잭션에 대하여 다른 트랜잭션이 이루어지지 않았다는 사실을 보증합니다. 즉, 다른 트랜잭션에서 특정 트랜잭션의 입력 상태가 아직 소비되지 않았다는 것을 검증합니다.
어떤 트랜잭션을 검증해달라는 요청을 받은 보증인은 다음과 같은 역할을 수행합니다.
- 만약 다른 트랜잭션이 요청을 받은 트랜잭션의 입력 상태를 소비하지 않은 경우 트랜잭션에 서명합니다.
- 만약 이중지불을 하려는 시도가 감지된 경우 트랜잭션을 파기합니다.
이러한 과정을 통해 보증인 노드는 시스템 전반의 완결성 (finality) 를 보장합니다. 보증인의 서명이 포함되기 전까지 트랜잭션은 유효할 수 없습니다. 만약 충돌되는 두 개의 트랜잭션이 동시에 존재할 경우 어느 하나가 유효하다는 평가를 보증인 노드가 내리기 전까지는 승인되지 않습니다. 하지만 보증인 노드의 서명이 포함된 경우 해당 트랜잭션의 입력 값이 이전 트랜잭션에 의해 소비되지 않았다는 것을 증명할 수 있습니다. 따라서 보증인 제도는 시스템 전체의 완결성을 보장해줍니다.
모든 상태 (state) 는 보증인이 있어야 하며 보증인은 자신이 맡은 트랜잭션의 보증인인 경우에만 해당 트랜잭션을 검증하는 역할을 맡게 됩니다.
합의 알고리즘
Corda Network는 필요에 따라 원하는 합의 방식을 채택할 수 있습니다. 보증인 노드 간의 합의를 이룰 때, 기존의 다른 블록체인에서 사용되는 알고리즘을 활용할 수 있다는 뜻입니다. 구체적으로 이야기를 하면 다음과 같습니다.
- 구조 — 보증인 노드는 하나의 네트워크 노드여도 괜찮습니다. 혹은 여러 노드의 묶음이어도 됩니다. 혹은 서로 믿지 못하는 배반의 노드의 묶음이어도 괜찮습니다.
- 합의 알고리즘 — 보증인 노드가 여러 노드의 묶음인 경우 노드들의 투표에 의하여 거래를 보증하는 알고리즘을 사용할 수도 있습니다. 예를 들어서 PBFT나 RAFT를 직접 차용하여 금융사들이 보증인 그룹을 결성할 경우 과반수에 이르는 동의가 있을 경우 해당 트랜잭션을 유효한 거래로 처리할 수도 있다는 것입니다.
검증의 생략과 수행
보증인 노드는 반드시 트랜잭션을 검증하기 이전에 자신이 해당 트랜잭션을 검증할 것인지 아닌지를 결정해야 합니다. 경우에 따라서 보증인 노드는 트랜잭션의 검증을 생략할 수도 있고, 그냥 수행할 수도 있습니다. 트랜잭션을 검증하기로 한 경우 해당 트랜잭션의 모든 기록을 하나씩 유효한 지 따져보아야 합니다.
해당 결정을 할 때, 보증인 노드는 다음과 같은 사항을 고려해야만 합니다.
- 만약 트랜잭션의 검증을 생략한 경우, 네트워크는 DDoS 공격에 처해질 가능성이 있습니다. 어느 노드가 고의로 유효하지 않은 트랜잭션 (어느 상태가 소비되었다고 거짓으로 적은 후) 을 대량으로 생산해서 보증인 노드에게 보내면 소비되지 않은 상태가 소비되었다고 처리될 가능성이 있습니다. 따라서 이러한 경우 트랜잭션에 참여한 모든 노드의 신원을 저장한 후 추후에 DDoS 공격 등의 문제가 생겼을 경우 책임을 묻게 됩니다.
- 만약 트랜잭션을 검증한 경우, 보증인 노드는 반드시 트랜잭션의 전체 기록을 검토하고 관련된 사항을 모두 검증해야만 합니다. 이는 보증인 노드에게 일부 기밀 정보를 유출할 수 있는 가능성을 내포하게 됩니다. 이런 경우 보증인 노드에게 새로운 공개키를 부여함으로써 보증인 노드가 거래인의 정보를 확인할 수 있는 범위를 제한합니다.
물론 해당 결정을 내릴 때는 추가적으로 고려해야 할 사항이 있는 것은 사실입니다.
여러 보증인
각각의 Corda Network는 서로 다른 보증인을 가질 수도 있고, 또한 각자가 원하는 방식의 합의 알고리즘을 채택할 수도 있습니다. 이러한 방식을 통하여 다음과 같은 장점을 얻을 수 있습니다.
- 프라이버시 보호 — 트랜잭션 전체를 검증하거나 검증을 하지 않는 보증인 노드 모두를 같은 네트워크에서 보유함으로써 서로 다른 합의 알고리즘을 채택하도록 이끌 수 있습니다. 이러한 과정을 통하여 특정 트랜잭션에는 원하는 보증인과 합의 알고리즘을 적용하도록 만들 수 있습니다. 기밀을 지켜야 할 필요성이 있는 거래에는 그럴 필요가 없는 거래와는 다른 보증인과 합의 알고리즘을 채택할 수 있다는 의미입니다.
- 속도의 제고 — 하나의 트랜잭션을 다양한 보증인 노드에게 보냄으로써 플랫폼 전체의 트랜잭션 속도를 제고할 수 있다는 장점도 있습니다.
- 낮은 대기 시간 — 보증인을 물리적으로 가까운 노드로 지정함으로써 대기 시간을 현실적으로 낮출 수 있습니다.
보증인의 교체
보증인 노드만이 트랜잭션을 승인할 수 있다는 사실을 상기해봅시다. 물론 요청받은 트랜잭션의 입력 상태를 보증할 수 있도록 사전에 지정이 되어 있어야 할 것입니다. 하지만 경우에 따라서 특정 상태의 지정된 보증인 노드를 교체해야 할 상황이 생길 수도 있습니다. 다음과 같은 경우가 그럴 것입니다.
- 만약 하나의 특정 트랜잭션이 다양한 상태에 의해서 소비가 되어서 서로 다른 보증인이 이미 지정이 되어 있는 경우
- 트랜잭션을 보증해달라고 요청하는 노드가 프라이버시 문제나 효율성 문제때문에 다른 보증인 노드가 승인해달라고 특별하게 요청하는 경우
이러한 보증인 노드의 전환 요청은 특별히 생성되는 트랜잭션에 의해 처리될 수 있습니다.
—
여기서 언급되지 않은 내용은 https://docs.corda.net/ 웹사이트에 접속하시면 더 살펴보실 수 있습니다. 오늘 이 글을 통하여 R3 Corda에 대한 이해가 풍부해지셨길 기대합니다. 감사합니다.