가짜 블록체인 기술

전세계에서 블록체인 열기가 가장 뜨거운 한국. 덕분에 어처구니 없는 일들도 많이 일어난다.

가장 대표적인 예는 소스 코드도 외부 참여도 없는 메인넷. 메인넷을 런칭했는데 공개된 소스 코드도 없고, 오직 개발사만 노드를 운영하고 있다면 그런 블록체인이 중앙화된 서버와 뭐가 다를까? 해당 블록체인이 어떤 로직으로 동작하는지 알 수도 없고, 트랜잭션을 내 손으로 직접 검증(validation)해볼 수도 없는 블록체인은 무늬만 블록체인인 서버 기술이다.

국내 대표 코인 아이콘이 대표적인 예다. 지난 1월 메인넷을 런칭했고 얼마 전부터 ERC20 토큰을 메인넷 토큰으로 교환해주는 토큰 스왑을 시작했다. 하지만 메인넷의 소스 코드는 이런 저런 핑계로 공개를 미루고 있고, 메인넷 노드도 아이콘 외에 다른 기관이 운영하고 있는 것처럼 보이지 않는다.

아이콘이 블록체인 기술로 그 어떤 신뢰도 제공하지 못하고 있음에도 불구하고 코인마켓캡 기준으로 6000억원이 넘는 가치를 가지고 있다는 사실이 시사하는 바는 매우 크다. 현재 아이콘의 가치는 블록체인 기술이 아닌 아이콘 재단에 대한 신뢰에 기반하기 때문이다. 중앙화된 발행기관에 대한 비판에서 나온 블록체인 기술이 오히려 중앙화된 발행기관에 대한 신뢰에 절대적으로 의존하고 있는 셈이다. 아이콘은 한국의 대표 블록체인 기술을 표방하지만, 역설적으로 블록체인 기술의 가치를 철저히 부정하고 있다.

 

Tendermint로 배우는 블록체인 코어 개발

블록체인 플랫폼을 만들려면 합의 알고리즘 외에도 트랜잭션 포맷, P2P 네트워크, 직렬화, 스토리지, 키 관리, 암호 알고리즘 등 여러 요소들을 고민해야 합니다. 하지만 보통 블록체인 기술 백서는 합의 알고리즘 위주로 1-2개의 주요 기술 요소만 설명하고 다른 요소에 대해서는 언급을 하지 않는 경우가 많습니다.

블록체인 기술을 직접 만들려면 이런 요소들도 간과할 수가 없는데, 비트코인, 이더리움 소스 코드를 보는 방법 외에는 마땅한 리소스가 없는 것도 사실입니다. 블록체인 구현 기술에 대해 궁금한 분에게 추천 드리는 문서는 Tendermint의 CTO인 Ethan Buchman가 석사 논문으로 작성한 Tendermint: Byzantine Fault Tolerance in the Age of Blockchains입니다.

Tendermint 합의 알고리즘 뿐만 아니라 블록체인 구현에 필요한 여러 기술 요소들에 대해 간결하게 잘 설명하고 있고, 배경 지식, 다른 블록체인 플랫폼과의 비교 등도 포함되어 있어서 블록체인 기술을 구현 수준에서 공부하시는 분들에게 좋은 가이드가 될 것 같습니다.

Go 언어로 구현된 Tendermint 소스 코드도 참고하세요!

 

이더리움 트랜잭션 malleability 문제

이더리움은 ECDSA 이용하여 트랜잭션을 서명하고 서명값(r, s, v)를 트랜잭션에 붙여서 보냅니다. 트랜잭션 해시는 서명을 포함하기 때문에 서명값에 따라 트랜잭션의 해시 값도 달라집니다.

이더리움 블록 헤더의 transactions root 필드는 각 블록 내의 트랜잭션 인덱스를 키로 각 트랜잭션의 해시를 저장해서 만든 merkle patricia tree 루트입니다. 블록을 검증할 때 헤더의 transactions root가 실제 트랜잭션으로 계산한 transactions root와 같은지 확인하는 방법으로 트랜잭션의 위변조 여부를 검사하고 있습니다.

그런데 서명 데이터 중 하나인 s는 타원곡선 상의 점이기 때문에 x축에 대칭인 타원곡선의 특징상 하나의 서명에 대해 high s, low s 두 개의 값이 모두 유효한 서명이 됩니다. 따라서 트랜잭션을 받아서 low s를 high s로 바꾸는 것만으로 서명의 유효성을 해치지 않고 트랜잭션의 해시 값을 바꿀 수 있게 됩니다.

이러한 문제를 트랜잭션 malleability라고 부르는데, 이더리움에서는 이 문제를 해결하기 위해 두 개의 s 값 중에 low_s만을 유효한 서명으로 인정하고 있습니다. 비트코인에서도 같이 같은 이유로 트랜잭션 malleability 문제가 있었고 역시 low_s만 유효한 서명으로 인정하는 방법으로 문제를 해결하였습니다.

비트코인의 BIP-62도 이 문제에 대해 설명하고 있으니 관심 있으신 분은 읽어보시기 바랍니다.

이더리움 트랜잭션의 서명 검증 방법

이더리움은 타원곡선디지털서명(ECDSA) 알고리즘을 이용하여 트랜잭션을 서명합니다. 비트코인과 마찬가지로 secp256k1 곡선을 사용하고 있습니다. ECDSA로 서명한 메시지를 검증하려면 서명에 사용한 비밀키에 대응하는 공개키가 필요합니다.

그런데 네트워크로 전송되는 이더리움 트랜잭션 포맷을 보면 서명자의 공개키가 포함되어 있지 않습니다. 트랜잭션에 보낸 사람의 주소는 포함되어 있지만 이더리움 주소는 공개키의 해시값이기 때문에 주소만 가지고 공개키를 복원하는 것은 불가능합니다.

그럼 이더리움은 어떻게 트랜잭션이 서명이 유효한지 검증할 수 있을까요? 놀랍게도 ECDSA는 메시지(트랜잭션의 해시)와 서명만 있으면 서명에 사용된 공개키를 복원하는 게 가능합니다. 완벽한 복원은 아니고 후보를 4개까지 줄일 수 있습니다.

그래서 이더리움은 4개의 후보 중에 어떤 공개키를 써야 하는지를 트랜잭션에 포함시켜서 보냅니다. 이더리움 트랜잭션 서명은 r, s, v 컴포넌트로 이루어져 있는데 여기서 r, s는 각각 32바이트로 이루어진 서명 데이터이고, v는 1바이트로 4개의 후보 중에 어떤 공개키를 사용해야 하는지 지정합니다.

자세한 내용이 궁금하신 분은 SEC 문서의 4.1.6 Public Key Recovery Operation을 읽어보시기 바랍니다.

비트코인 코어 개발자 공부법

블록체인 개발자에 대한 수요는 높은데, 블록체인 개발 경험이 있는 개발자는 거의 없습니다. 블록체인 개념만 공부하고 바로 블록체인을 만들기는 어렵기 때문에 기존 블록체인 프로젝트 소스코드를 읽고 공부하는 것이 가장 효과적인 방법입니다. 소스코드 공부하기 좋은 블록체인 프로젝트 추천드립니다.

비트코인

Bitcoin Core (C++)
https://github.com/bitcoin/bitcoin

btcd (Go)
https://github.com/btcsuite/btcd

이더리움

go-ethereum (Go)
https://github.com/ethereum/go-ethereum

Parity (Rust)
https://github.com/paritytech/parity

리플/스텔라

rippled (C++)
https://github.com/ripple/rippled

stellar-core (C++)
https://github.com/stellar/stellar-core

Tendermint

Tendermint (Go)
https://github.com/tendermint/tendermint

추가로 암호학적인 접근 방법에 관심이 있으신 분은 monero나 zcash (Bitcoin Core 기반)도 추천드립니다.

흔히 블록체인 기술을 1세대 (비트코인), 2세대 (이더리움), 3세대 (기타 등등)으로 나누는데, 엔지니어 관점에서 3세대 블록체인은 별로 볼 게 없습니다. 소스코드가 아예 없거나 있어도 검증 안 된 프로토타입 수준인 것들이 많아서 기술적인 완성도는 비트코인, 이더리움에 비해서 한참 떨어집니다.

블록체인 개발에 입문하시는 분에게는 특히 비트코인 구현 분석을 추천드립니다. 오랜 세월 개발하면서 생긴 레거시도 있지만, 구현 완성도가 높고 블록체인의 핵심 아이디어를 잘 이해할 수 있는 구조이기 때문입니다. 희안하게 한국에서는 뒤떨어진 기술 취급 받지만, schnorr signature 도입, mimblewimble, MAST(merkleized abstrct syntax tree) taproot 등 재미있는 아이디어를 많이 실험하고 있는 프로젝트이기도 합니다.

O(1) Block Propagation

비트코인 마이너가 블록 생성에 성공하고 나면 네트워크에 빠르게 전파해야 합니다. 블록의 크기가 커질수록 블록 전파에 걸리는 시간도 늘어나기 때문에, 블록 전파 시간을 줄이는 최적화가 중요해집니다. 블록 전파 시간을 줄이는 방법 중에 하나로 비트코인 코어 개발자인 Gavin Andresen이 제안한 O(1) Block Propagation이 있습니다.

마이너가 채굴해서 전파하는 블록에는 트랜잭션들이 포함되어 있습니다. 그런데 블록을 전파 받는 노드들도 사실은 트랜잭션 풀에 마이닝된 트랜잭션을 이미 대부분 가지고 있음에도 불구하고, 정확히 어떤 트랜잭션이 마이닝되었는지 알 수 없기 때문에 블록에 포함된 트랜잭션들을 다시 다운로드 받아야 합니다.

그런데 새로 생성된 블록에 들어있는 트랜잭션의 목록과 트랜잭션 풀에 들어 있는 트랜잭션의 목록의 차이를 바로 알 수 있는 데이터 구조가 있다면, 노드 입장에서 이미 가지고 있는 트랜잭션은 굳이 다시 다운로드 받지 않아도 됩니다.

이러한 문제를 Set reconciliation이라고 하는데, IBLT(Invertible Bloom Lookup Tables)라는 데이터 구조가 이에 대한 해법을 제공합니다. Gavin Andresen의 O(1) Block Propagation 제안은 IBLT를 이용하여 이미 트랜잭션 풀에 있는 트랜잭션을 전파하지 않고도 다른 노드에게 블록을 전파하는 방법을 제안하고 있습니다.

현재 비트코인 마이너들은 별도의 고속 블록 릴레이 네트워크를 사용하고 있기 때문에 O(1) Block Propagation는 받아들여지지 않은 것 같은데, 블록체인 새로 설계하는 분들에게는 재미있는 시도일 수 있을 것 같습니다.

자세한 내용이 궁금하신 분은 원글을 읽어보세요.

리플의 키 관리 방법

리플은 다른 블록체인과 달리 key를 master key와 regular key로 구분합니다. master key는 비트코인과 마찬가지로 주소와 수학적으로 연결된 (ECDSA secp256k1) key pair를 말하고, regular key는 SetRegularKey를 이용하여 블록체인 상에 등록할 수 있는 추가적인 key입니다.

regular key pair를 등록하고 나면 master key의 private key가 아닌 regular key의 private key를 이용하여 transaction을 authorize할 수 있습니다. master key는 리플 주소와 묶여 있기 때문에 바꿀 수 없지만, regular key는 원하는 시점에 언제든 교체할 수 있다는 특징이 있습니다. 비트코인의 경우 key를 도난 당하면 찾을 방법이 없지만, 리플에서는 regular key가 도난 당했을 경우 master key를 이용해 도난 당한 regular key를 무효화시키고 새로운 regular key를 등록할 수 있습니다.

관련 설명은 리플 기술 문서에서 확인하실 수 있습니다.