블록체인에서의 자료형(Data type)

Joowon
RIZON Korea
Published in
7 min readMar 20, 2020

블록체인은 하나의 기술이 아닌 여러 가지 고도 기술의 집약체입니다. 그중 자료형도 한 가지 연구 분야입니다. 표준으로 정의된 자료형을 사용하는 것을 넘어서, 더 작은 용량을 사용하며 정확한 연산을 할 수 있는 자료형을 만들기 위한 연구가 진행되고 있습니다. 블록체인 플랫폼에서 가장 활성화된 서비스인 가상자산(암호화폐, cryptocurrency)의 단위를 기반으로 어떤 사항을 고려해서 자료형을 정의해야 하는지 살펴보려고 합니다.

소수점 표현 방식

블록체인 플랫폼들은 소수점을 포함한 실수를 가상자산 단위로 활용하고 있습니다. 그러나 프로그래밍언어에서 기본으로 제공하는 float, double 등의 자료형을 사용하고 있지 않습니다. 그 이유는 해당 자료형들이 부동소수점을 이용하기 때문입니다. 부동소수점은 실수를 컴퓨터상에서 소수점 위치를 고정하지 않고 근사한 값으로 표현하는 방식이라 오차가 있습니다.

> 0.1 + 0.1 + 0.1
0.30000000000000004

위 예시와 같이 0.1을 세 번 더하면 0.3이란 값이 나와야 하지만 컴퓨터는 다른 결과값을 도출합니다. 이 문제 때문에 부동소수점에서는 정확한 등호(=)의 결과를 얻을 수 없습니다. 이를 해결하기 위해 부동소수점 연산에서 반올림을 통해 발생하는 오차의 상한값인 머신 엡실론(Machine epsilon)을 사용합니다. 그래서 부동소수점을 비교할 때 비교하려는 값과 결과값의 차가 머신 엡실론의 값보다 작거나 같은지를 확인하고 비교 결과값을 얻게 됩니다. 하지만 이러한 연산 과정은 데이터 정합성을 보증해야 하는 블록체인 플랫폼에서 문제가 될 수 있습니다. 각 OS와 컴파일러에 따라 보장해주는 소수점 자릿수가 다르고 이 계산 값이 누적되다 보면 두 값은 위에서 설명한 머신 엡실론 이상의 차가 발생하게 되며 전혀 다른 값을 표현하게 됩니다.

/* Windows node v10.19.0 */
> 1 - Math.pow(0.5, 22711.847256807654/(15000*184555992.82315296)) 5.686676352034681e-9
/* MacOS node v10.19.0 */
> 1 - Math.pow(0.5, 22711.847256807654/(15000*184555992.82315296)) 5.686676241012378e-9

이를 해결하기 위해 정수형 자료형으로 고정소수점 개념을 활용한 프로젝트 중 하나의 예시를 살펴보겠습니다. 가상자산의 단위로 64bit 정수형 자료형을 사용하며 첫 번째 32bit는 정수로, 두 번째 32bit는 소수점 아래 값을 표현합니다. 32bit가 표현할 수 있는 최댓값은 4,294,967,295이므로 소수점 9자리까지 표현할 수 있습니다. 이 가상자산으로 1.000000023을 표현하면 정수값은 1이고 이를 byte로 변환하면 [0, 0, 0, 1]이 되고, 소수점 아래 값은 23이므로 [0, 0, 0, 23]이 됩니다. 이는 [0, 0, 0, 1, 0, 0, 0, 23]과 같은 형태로 저장할 수 있고, 4294967319가 1.000000023을 표현하는 형식으로 사용하게 됩니다. 하지만 이와 같이 사용했을 때 자료형은 최대 값을 갖게 되고 이를 넘어가는 수를 사용했을 때 오버플로우가 발생해 잘못된 결과를 얻게 됩니다.

연산자 오버플로우

오버플로우란 연산의 결과가 다룰 수 있는 범위를 벗어나 예기치 못한 결과 값을 얻게 되는 것입니다. 예를들면 0~100까지 표현할 수 있는 자료형이 있다고 할 때 최대값인 100에서 1을 더하는 연산을 했을 때 0이라는 결과를 얻게 됩니다.

이 오버플로우를 이용해서 타인의 가상자산을 조작하는 시나리오는 다음과 같습니다. 먼저 가상자산은 0~100을 표현할 수 있는 자료형을 사용했다고 가정하겠습니다. A는 10 Coin을 가지고 있고 B에게 90 Coin, 수수료로 11 Coin을 보내는 트랜젝션을 발생시킵니다.

이 때 블록체인 합의알고리즘은 A가 보내는 금액과 수수료를 합산한 금액이 A가 가진 금액보다 작은 값인지 확인합니다. 보내는 금액(90 Coin)과 수수료(11 Coin)를 합하였을 때 값은 101이나 해당 자료형은 100까지 밖에 표현할 수 없음으로 100보다 1 큰 값인 101은 0이됩니다. 따라서 A가 가지고있는 가상자산(10 Coin)은 보내려는 금액과 수수료의 합(0 Coin) 보다 큼으로 유효한 트랜젝션이 됩니다. 해당 트랜젝션이 처리되고나면 A는 가지고있는 금액(10 Coin)에서 보내는 금액과 수수료의 합(0 Coin)을 뺀 값인 10–0 = 10 Coin을 그대로 가지게되며 B코인은 A가 보낸 금액(90 Coin)을 가지게 되고, 트랜젝션 검증자는 수수료인(11 Coin)을 가져가게 됩니다. 이로써 가상자산 101 Coin이 추가 생성된 것 입니다. 또한 A가 자신이 소유하지 않은 B의 가상자산을 마음대로 조정할 수 있는 공격시나리오가 발생합니다.

가상자산의 자료형을 64bit 정수형을 사용했다면 18,446,744,073,709,551,615까지 사용할 수 있기 때문에 이 값이 가상자산의 공급량을 넘지않아 오버플로우가 발생하지 않을꺼라 판단한 프로젝트들이 있습니다. 하지만 위와같이 오버플로우 공격이 일어날 수 있고 이를 방지하기위해 연산이 일어나고 난 결과를 연산 전 값과 비교하여 오버플로우 발생여부를 확인하는 로직을 추가하여 연산을 하고있습니다. 위 예시로하면 90 + 11의 결과는 0이되고, 이 0은 90, 11보다 작음으로 오버플로우가 발생한 연산이며 유효하지 않은 트랜젝션으로 처리합니다.

용량

연산자 오버플로우 공격을 피해 정확한 값을 사용하기 위해 string값 또는 hex string값을 가상자산의 자료형으로 사용하는 프로젝트들이 있습니다. 이는 오버플로우, 부동소수점 등의 오류를 피할 수 있으나 용량을 많이 차지하는 문제가 있습니다. 1억이란 숫자를 각 자료형으로 표기했을 때 차지하는 용량은 아래와 같습니다.

위와 같이 string, hex string의 자료형은 자릿수가 늘어날수록 정수형보다 많은 용량을 필요로합니다. 그리고 가상자산의 수량에 따라 길이가 변할 수 있음으로 추가적으로 길이를 나타내는 byte를 아래와 같이 추가하여야합니다.

이를 응용하여 길이를 포함한 정수형을 사용할 수 있습니다.

비록 기존 32bit 정수형에 비해 1byte늘어났지만 4byte보다 작은 값을 사용할 때는 32bit 정수형보다 작은 용량으로 표현할 수 있습니다. 예를 들어 12라는 숫자를 표현할 때 용량은 아래와 같습니다.

위와 같이 가상자산의 단위를 표현할 수 있는 방법은 다양하고 각각의 장단점이 있습니다.

마치며

블록체인은 여러가지 고도한 기술의 집약체이므로 자료형은 그 일부분일 뿐이라고 생각할 수 있습니다. 하지만 자료형을 다루는 사소한 실수로 예기치 못한 결과를 얻게 됩나다. 또한 블록체인은 탈중앙화 시스템이므로 관리자가 패치하여 수정할 수 없기에 해당 플랫폼은 완전히 붕괴될 수 있습니다. 그러므로 블록체인 플랫폼을 설계 및 개발 시, 전송 속도를 포기하고 정확한 데이터를 위해 큰 용량의 자료형을 사용할지, 혹은 연산 속도를 위해 정수형 자료형을 사용해 빠르게 처리할지 등 각 플랫폼의 특성을 고려하여 최적화된 자료형을 사용해야 합니다.

마지막으로 제가 다룬 자료형이나 저희 팀원들이 작성한 주제, 혹은 블록체인 플랫폼에 대한 더 깊은 이야기를 나누고 싶으시다면 포럼에서 논의 할 수 있습니다. 포럼은 항상 열려있으며 누구든 참여할 수 있습니다. 많은 관심 부탁 드립니다.

--

--