본문으로 건너뛰기
Bankware Global Engineering

Distributed systems, ledger design, financial infrastructure, and protocol engineering.

모든 저자 보기

Native Program은 거래의 변경안을 어떻게 검증할까?

· 약 10분
Bankware Global Engineering

A는 자산 100을 갖고 있고, S에게 그중 30까지 사용할 수 있도록 승인했다. S는 이 권한으로 20을 B에게 보내려고 한다. 거래가 끝나면 A에게 80, B에게 20이 남고, S가 앞으로 사용할 수 있는 한도는 10이 되어야 한다.

nigo-protocol의 Native Program 경로에서는 거래를 구성하는 쪽이 이 변경안을 먼저 준비한다. 프로그램은 전달받은 변경안이 사용 조건을 지키는지 검사한다. Direct Cell의 거래 준비에서는 명시적인 입력·출력을 원장 밖에서 구성하고 서명하는 과정을 살펴봤다. 여기서는 같은 변경안 구성 방식에 사용 승인이라는 업무 조건을 더해, Native Program의 검증 안쪽으로 들어가 보자.

프로그램이 단순히 “허용한다”고 답하면 충분할까? 그 답이 A의 어떤 자산 입력을 쓰도록 허용했는지, 어떤 승인 기록을 무엇으로 바꾸도록 허용했는지가 빠져 있다면, 원장은 그 승인이 어느 입력의 사용과 어떤 상태 변경에 적용되는지 확인할 수 없다. 사용 조건을 통과했다는 판단과 실제 바뀌는 기록을 연결하는 방법이 이 글의 질문이다.

Direct Cell: 거래는 원장 밖에서 어디까지 준비할 수 있을까?

· 약 9분
Bankware Global Engineering

A가 가진 자산 100 중 20을 B에게 보내려고 한다. B는 그중 5를 C에게 보낼 생각이다. A에게 남을 80 중 10은 D에게 보낼 예정이다.

이 거래들을 준비하려면 매번 앞의 거래가 블록에 들어갈 때까지 기다려야 할까? 또 거래의 내용을 만드는 사람과 서명하는 사람, 그 내용이 맞는지 확인하는 사람이 모두 같은 곳에 있어야 할까?

nigo-protocol의 Direct Cell은 소비할 기록과 새로 만들 기록을 거래에 직접 담는다. 하나의 원장, 세 가지 거래 실행 방식에서는 이 요청을 Native Program과 EVM의 요청에 비교했다. 여기서는 Direct Cell의 명시적인 변경안이 거래를 준비하는 장소와 역할을 어떻게 나눌 수 있게 하는지 살펴보자.

그 가능성을 이해하려면 두 가지를 함께 봐야 한다. 어떤 결과를 제안할지 미리 정할 수 있다는 것과, 그 제안이 실제 원장에 확정됐다는 것은 서로 다른 사실이다.

하나의 원장, 세 가지 거래 실행 방식

· 약 9분
Bankware Global Engineering

A가 가진 자산 100 중 20을 B에게 보내려고 한다. 거래가 끝나면 A에게 80이 남고 B는 20을 갖게 된다. 목표는 간단하지만, 원장에 어떤 요청을 보내야 하는지는 실행 방식에 따라 달라진다.

“이 기록을 소비하고 A의 80과 B의 20을 만들어 달라”고 변경할 결과를 적을 수도 있다. “이 컨트랙트의 이전 함수를 실행해 달라”고 요청하고, 결과는 코드가 계산하게 할 수도 있다. 다른 사람이 A의 자산을 대신 사용한다면 그 권한과 조건을 검사하는 방법도 필요하다.

nigo-protocol은 이 차이를 Direct Cell, Native Program, EVM이라는 세 가지 실행 방식으로 다룬다. 이번 글에서는 하나의 이전 예제를 따라, 각 요청에 무엇을 담고 누가 다음 상태를 만들며 그 결과가 어떻게 같은 원장에 반영되는지 살펴본다.

과거에 없던 상태와, 지금 꺼낼 수 없는 상태

· 약 10분
Bankware Global Engineering

원장에 “그때 이 자산이 있었나요?”라고 물었는데, 기록을 찾을 수 없다는 답이 돌아왔다. 그 시점에 정말 없었다는 뜻일까? 아니면 답한 노드가 그때의 자료를 갖고 있지 않다는 뜻일까?

현재 잔액을 확인할 때는 잘 드러나지 않는 차이다. 하지만 과거의 소유를 확인하거나 거래 결과를 감사하려면 두 답을 구분해야 한다. 자료를 꺼낼 수 없다는 이유로 “없었다”고 판단하면, 원장의 사실이 조회한 노드의 보관 사정에 따라 달라진다.

StateCell의 소유자에서는 소유 정보와 변경 권한을 연결하고 상태 변화의 경로를 기록하는 이유를 살펴봤다. 이번에는 그 기록의 보존과 검증에 관한 질문이다. 시간이 지난 다음에도, 그때 원장에 무엇이 있었는지 확인할 수 있을까?

StateCell의 소유자: 누가 상태를 바꿀 수 있을까?

· 약 9분
Bankware Global Engineering

A가 S에게 자신의 자산을 30까지 대신 사용할 수 있도록 허용했다. S는 그중 20을 B에게 보내려 한다. 이번 거래에 서명하는 사람은 S다. 하지만 사용할 자산은 A의 것이다.

원장이 ‘자산의 소유자가 직접 서명했는가’만 검사한다면 이 거래는 처리할 수 없다. 그렇다고 S가 A의 자산을 사용하겠다고 적은 것만으로 허용할 수도 없다. A가 무엇을 승인했는지, S의 요청이 그 범위 안에 있는지 함께 판단해야 한다.

누구의 상태인가와, 누가 어떤 조건으로 그 상태를 바꿀 수 있는가. StateCell에 소유자라는 개념을 넣으면서 함께 풀어야 했던 질문이다.

StateCell은 원장의 상태를 담는 작은 기록 단위다. 1편에서는 자산과 스마트컨트랙트의 상태를 이 공통 단위로 표현하는 이유를, 2편에서는 값의 구조를 표현하는 방법을 살펴봤다. 이번에는 위의 사용 승인 예제를 따라 소유 정보와 변경 권한, 프로그램과 원장의 역할을 설명한다.

StateCell의 스키마 해시: 값의 구조를 표현하는 방법

· 약 10분
Bankware Global Engineering

주소 하나와 숫자 30을 바이트열로 저장했다고 하자. 읽는 쪽은 어디까지가 주소이고 어디부터가 정수인지 알아야 한다. 필드가 더 늘어나거나 같은 기록이 배열로 반복된다면 그 조합을 해석할 약속도 필요하다.

1편에서는 자산 출력과 스마트컨트랙트의 상태를 StateCell이라는 공통 단위로 표현하려는 이유를 설명했다. 공통 단위를 정하고 나니 그 안에 담을 값의 구조를 어떻게 나타낼지가 다음 질문이 되었다. 정수 하나뿐 아니라 구조체, 배열, 매핑도 다룰 수 있어야 하기 때문이다.

nigo-protocol은 값과 값의 구조를 분리하고, 그 구조를 스키마 해시로 식별한다. 이번 글에서는 작은 사용 한도 기록에서 시작해, 기본 자료형으로 복합 구조를 만들고 이를 셀 단위의 상태로 연결하는 설계를 설명한다.

자체 블록체인을 만들기로 했다: UTXO에서 StateCell까지

· 약 10분
Bankware Global Engineering

토큰을 얼마나 오래 보유했는지에 따라 권리를 계산하려면, 지금의 잔액에 과거의 기록을 더해야 한다. 소유기간 컨트랙트를 돌아본 글에서는 잔액이 바뀔 때마다 블록 번호와 변경 후 잔액을 남기는 방식으로 이 문제를 풀어봤다. 기존 블록체인 위에 스마트컨트랙트를 배포하는 것만으로도 보유기간을 반영한 수익배분을 실험할 수 있었다.

그런데 여러 자산이 같은 종류의 기록을 필요로 한다면 어떨까. 자산마다 이력을 남기는 구조를 만들고, 조회 방식을 정하고, 그 기록을 다시 읽는 작업을 반복하게 된다. 원장이 자산의 소유와 상태 변화를 공통 구조로 이해한다면 이 일을 어디까지 함께 처리할 수 있을까.

이 질문은 nigo-protocol이라는 자체 블록체인을 설계하게 된 계기 중 하나였다. 직접 원장을 만든다면 먼저 정해야 할 것이 있었다. 무엇을 하나의 상태로 저장하고, 그 상태의 변경을 어떻게 표현할 것인가.

StateCell 시리즈의 첫 글에서는 이 선택의 출발점을 설명한다. UTXO가 보여준 명시적인 상태 전이와 스마트컨트랙트가 열어준 개발 경험을 어떤 방식으로 같은 원장에 담으려 했는지에 관한 이야기다.

RPC 노드를 바꾸면 실패한 거래도 해결될까

· 약 8분
Bankware Global Engineering

거래를 보냈는데 RPC 응답이 오지 않는다. 대신 사용할 노드가 하나 더 있다면, 그쪽으로 연결을 바꾸면 될까?

다른 노드는 다음 요청을 처리할 수 있다. 그러나 먼저 보낸 거래까지 없었던 일이 되지는 않는다. 연결 대상을 바꾸는 일과 거래의 실행 결과를 확인하는 일은 서로 다른 상태를 다룬다.

송금 요청의 타임아웃과 재시도에서는 같은 업무를 다시 실행할 때 생기는 문제를 살펴봤다. 이번에는 그 아래의 연결 계층으로 들어간다. BXB가 노드를 고르는 방식, 장애 후보를 다시 확인하는 방식, 미러가 다른 노드에 조회를 재시도하는 방식을 비교해 보자.

HSM 안의 키로 블록체인 거래에 서명하기까지

· 약 9분
Bankware Global Engineering

서버가 고객의 토큰을 보내려면 개인키로 거래에 서명해야 한다. 그런데 개인키를 HSM 안에 두고 서버가 그 값을 읽지 않는다면, 서명할 거래는 누가 만들고 결과는 어떻게 받아야 할까?

HSM은 Hardware Security Module, 암호키를 보호하고 암호 연산을 수행하는 장치다. 블록체인 연동에서는 장치 안의 키로 서명을 요청하고 그 결과를 받아 쓰는 역할을 맡는다. 이때 서버에는 여전히 거래를 구성하고, 서명 결과를 체인의 형식에 맞추고, 제출 결과를 확인하는 일이 남는다.

고객 계정과 블록체인 서명의 연결에서는 고객 식별자·지갑·키 선택의 관계를 살펴봤다. 이번에는 BXB의 HSM 연동 코드에서 키를 선택한 다음 실제 거래가 만들어질 때까지를 따라가 보자.

같은 Solana 토큰인데 왜 조회만 가능할까

· 약 9분
Bankware Global Engineering

새 Solana 토큰을 등록했다. 잔액 조회는 된다. A가 100개를 가지고 있다는 응답도 받았다. 그런데 A에서 B로 10개를 보내려 하자 전송 API가 보이지 않는다. 잔액을 읽을 수 있다면 전송도 할 수 있어야 하는 것 아닐까?

토큰을 읽는 데 필요한 정보와, 그 토큰의 규칙에 맞는 거래를 만드는 데 필요한 정보는 다르다. Token-2022에서는 이 차이가 특히 잘 드러난다. 같은 토큰 프로그램을 사용해도 어떤 확장 기능이 붙었는지에 따라 전송 조건이 달라지기 때문이다.

멀티체인 API의 공통점과 차이에서는 체인마다 남겨야 할 조건을 살펴봤다. 이번에는 같은 Solana 안으로 들어가, BXB가 토큰별로 어떤 명령을 제공할지 판단하는 과정을 따라가 보자. 설명 범위는 토큰 프록시의 조회와 표준 쓰기 명령이며, 자원 관리 API 전체의 지원 범위를 뜻하지 않는다.