블록체인에서 난수를 생성하는 방법

스마트 컨트렉이 있는 블록체인(이더리움, 이오스)는 랜덤 함수를 제공하지 않습니다. 블록체인의 특성상 트렌젝션이 검증되려면 어떤 노드에서도 같은 결과가 나와야 하기 때문입니다. 이 포스트에서는 블록체인에서 난수를 생성하기 위해 시도한 기존 방법들 그리고 NBLab이 제안하는 방식을 설명드리겠습니다.

블록의상태값을 활용한 방식

블록에는 여러가지 상태값이 있습니다. 일반적으로 블록이 가지는 상태값은 다음과 같습니다.

  • 블록의 높이: 몇번째로 블록이 생성되었는지
  • 생성시간: 블록이 언제 생성되었는지
  • Block Hash: 이전 블록 그리고 현재 포함된 트렌젝션을 대표하는 고유 값

여러 상태 값 중 난수생성엔 미래에 예측이 불가능 해보이는 Block Hash 값이 주로 사용됩니다. 포함되는 트랜젝션의 구성에따라 이 BlockHash 값은 달라지게 되는데, 미래엔 어떤 트랜젝션이 블록에 포함될지 모르기 때문에 난수를 생성하는 합리적인 방법중 하나입니다.

단점 : 마이너 의존성
Block Hash 값은 모든 노드에서 같은 값을 가지게 됩니다. 그러나 Block Hash의 값은 단 하나의 노드에서만 생성이 됩니다. 블록을 최초로 생성한 그 노드에서 말이죠. 오직 하나의 노드에서 Block Hash가 생성되기 때문에 해당 노드가 블록에 포함될 트랜젝션의 구성을 바꿔가면서 본인이 원하는 Block Hash 값을 만들어 낼 가능성이 존재합니다. 우리는 이 가능성을 마이너 의존성이라고 합니다. 마이너 의존성으로 인해 블록의 상태값을 활용한 방식은 난수가 편향될 수 있는 가능성이 존재합니다.

Commit and Reveal 방식

Commit and Reveal 방식은 난수 요청자가 전처리된 seed 를 선택하는 방식입니다. 보다 쉬운 설명을 위해 다음과 같은 게임을 생각해보죠.

숫자 맞추기 게임
7개의 문이 있고 각 문 뒤에는 1부터 7까지 임의의 숫자가 존재합니다.

게임방법
게임에 참여하는 사람은 1부터 7중 하나의 숫자를 말합니다. 
하나의 문을 선택해서 문뒤의 숫자를 확인합니다.
확인한 숫자와 기존에 말했던 숫자가 일치하면 상금을 획득합니다.

Commit and Reveal 방식은 위에서 설명한 게임과 유사합니다.

난수생성방법

  1. 스마트 컨트렉트에 hashing seed가 존재합니다.
  2. 난수 요청자는 hashing 된 seed 중 하나의 seed를 선택합니다.
  3. 요청자는 난수생성에 필요한 또 다른 seed을 컨트랙트에 제공합니다.
  4. 스마트컨트렉트는 요청자가 제공한 seed 그리고 요청자가 선택하였던 hashing된 seed 를 조합해서 난수를 생성합니다.

컨트렉트 생성자의 조작 가능성
컨트렉트 생성자의 경우 hashing 된 seed가 무엇인지 알고 있기 때문에 컨트렉트 생성자가 게임에 참여하는 경우 항상 이기는 게임을 할 가능성이 있습니다. 위에서 예로 든 게임에서 게임을 만든 사람은 문뒤에 어떤 숫자가 있는지 알고 있기 때문에 항상 상금을 획득할 수 있습니다.

컨트렉트 용량 문제
여러명이 참여할 경우 hashing 된 seed가 더 많이 필요하게 됩니다. hashing 된 seed가 두 요청자에 의해 중복으로 선택 될 경우 하나의 요청은 취소가 되어야 하기 때문이죠. 따라서 요청자가 늘어날 수록 컨트렉트에 hashing 된 seed가 더 많이 저장이 되어 있어야 합니다. 위에서 예로 든 게임의 경우 유저가 늘어날 수록 더 많은 방을 만들어야 하는 상황과 같습니다. 즉 유저가 늘어날 수록 컨트렉트 저장 공간이 커져야 하는 것이지요. 이는 확장성을 고려하지 않은 설계라고 할 수 있습니다.

Signidice

Signidice 방식은 commit and reveal 방식의 난수 요청자가 늘어남에 따라 컨트렉트 저장공간이 늘어나는 단점을 개선한 방식입니다. 스마트컨트렉트에는 난수별로 hasing seed가 저장이 되지 않는 대신 Public Key 가 공개됩니다. 난수 요청자가 제공한 seed는 공개된 Public Key 에 대응되는 Private Key로 서명이 됩니다. 이 서명 정보가 난수 생성에 사용이 되는 것이지요. 간단히 말해 난수 요청자가 제공한 seed와 난수 제공자가 숨기고 있는 Private Key 의 조합으로 난수가 생성된다고 할 수 있습니다.

컨트렉트 용량 문제
Signidice 의 경우에도 마찬가지로 용량 문제를 겪을 수 있습니다. 용량 문제를 해결한 알고리즘인데 용량 문제를 겪었다니 이상하게 느껴지실 수 있습니다. 기존에 commit and reveal 방식의 경우 seed 제공 시 많은 용량이 필요하다면 Siginidice 방식의 경우 난수 생성 결과를 기록하기 위해 컨트렉트 용량이 사용됩니다. 왜 이러한 작업이 필요할까요? 바로 한번 사용되었던 seed를 사용하지 않기 위해 기존에 사용되었던 seed의 기록을 모두 남기기 때문입니다. 한번 사용된 seed가 재사용될 경우 같은 난수가 발생하기 때문이지요.

게다가 Signidice 에 저장되는 데이터는 추후 난수 생성 시 생성에 필요한 리소스가 증가하는 단점도 가지고 있습니다. commit and reveal 방식의 경우 요청자가 단순히 hashing 된 seed를 선택만 하면 되지만 Signidice 의 경우 제공한 seed가 기존에 사용되었는지 확인하는 과정을 거치게 되는데, 요청되었던 seed가 많아질 수록 이 확인작업에 시간이 오래 걸리게 됩니다.

NBLab이 고안한 RNG

NBLab은 Signidice 방식과 블록의 상태값을 사용한 각 방식의 장점만을 취해 공정성과 확장성을 만족하는 RNG 방식을 고안하였습니다. Signidice 방식의 유일한 문제는 기존에 사용되었던 seed를 사용하지 않기 위해 사용되었던 seed를 모두 contract에 기록한다는 것입니다. 이를 해결하기 위해 그리고 블록의 제공하는 상태 값 또한 seed로 활용하였습니다. 블록에서 제공하는 상태 값 그리고 난수 요청자가 제공하는 seed가 결합된 요청은 사실상 기존에 요청되지 않은 요청이라고 볼 수 있습니다. 따라서 이 방식을 사용할 경우 요청자의 seed를 매번 컨트렉트에 기록할 필요가 없게 됩니다. 어려운 내용이 많았지만 결국 핵심은 이번에 NBLab이 고안한 알고리즘은 블록체인을 통해 공정한 난수 생성이 가능함과 동시에 유저가 많아져도 확장이 가능합니다.

마치는 글

NBLab은 이번에 고안해낸 알고리즘으로 EOS 상에 Slot dapp 을 출시하였습니다. 이 Slot 은 사용자에게 공정한 결과를 제공하며 유저가 많아짐에 따라 유지 비용이 기하급수적으로 증가하지 않아 확장이 가능합니다. 관련한 설명은 다음 포스트 NBLab의 EOSlot (가칭) 에서 확인해보실 수 있으며 플레이는 https://slot.nblab.io 에서 가능합니다.
(일부 국가에서는 Three Stars Slot을 이용할 수 없습니다.)

감사합니다.

NEOWIZ PLAY STUDIO Blockchain Lab.
Homepage : https://www.nblab.io
Email: nblab@neowiz.com
Medium : https://medium.com/nblab