이더리움 RANDAO 프로토콜
비콘체인의 무작위성

Intro
무작위성는 보안과 공정성 모두를 위해 무허가형(permissionless) 블록체인 프로토콜의 중요한 부분이다. 때문에 Ethereum의 지분 증명 프로토콜은 위원회 구성원의 역할을 무작위로 선별하여 공정성과 더불어, 예측 불가능한 흐름을 통해 보안성을 제공한다.
이더리움 비콘체인은 프로토콜 내 무작위성을 제공하기 위해 RANDAO 메커니즘을 사용한다. 여기서 RANDAO는 단순히 기여자(contributor)가 제공하는 무작위성을 점진적으로 모으는 어큐뮬레이터(accumulator:축적기)를 의미한다. 기여자는 블록을 생성 할 때 마다 기존에 축적된 값(value)에 또 다른 값을 섞어 넣어 무작위성에 기여하게 된다.
The RANDAO
비콘체인의 모든 블록에는 해당 블록의 제안자가 제공한 (검증 가능한) 랜덤 값, 즉 RANDAO에 섞어넣는 무작위 값이 포함되어 있다. 이 값을 randao_reveal라고 한다. 각 블록이 생성 될 때 마다 블록제안자가 제공하는 randao_reveal이 RANDAO 값에 혼합되며 축적된다. 이와 같은 과정이 시간이 지남에 따라 반복되어 RANDAO는 모든 블록제안자의 randao_reveal를 축적하여 무작위성을 실현한다.
- : 현재 블록
- : 현재까지 RANDAO에 축적된 값
- : 이번 블록의 제안자가 제시한 랜덤 값(randao_reveal)
RANDAO에 축적되는 값은 위 공식에 따라 결정된다. 이전 블록의 RANDAO에 저장된 값에 블록제안자가 제시한 randao_reveal 값을 XOR 연산을 하여 새로운 RANDAO 값으로 정의한다.
RANDAO 값은 비콘체인의 에포크에 지정된 32명의 블록제안자가 제시한 randao_reveal이 블록이 생성될때마다 순차적으로 XOR 연산되며 업데이트 된다. 그리고 마지막 Slot 블록제안자의 randao_reveal까지 다 섞이면, 현재 에포크의 RANDAO 값은 다음 에포크의 위원회에서 블록 제안자와 입증자를 선별하는 난수의 시드로 사용된다. (정확히는 다다음 에포크의 위원회 역할을 선별하는데 사용되는 난수를 만드는 시드로 사용된다. 이후, 아래에서 자세하게 다룰 예정이다.) 이 부분이 비콘체인에서 RANDAO 프로토콜을 사용하는 이유이다.
무작위성을 위한 무질서 성질 : 엔트로피(entropy)

RANDAO는 각 참가자가 차례로 덱을 섞으면서 시간이 지남에 따라 무작위성이 누적되는 카드 덱이라고 생각하면 된다. 이 덱은 블록 생성이 멈추지 않는한, 반복적으로 다시 무작위화 되며, 한 참여자의 무작위성이 약하더라도 시간이 지남에 따라 누적된 결과는 높은 수준의 엔트로피를 가지게 된다.
"무작위성"에서 사용되는 "엔트로피"는 정보 이론(Information Theory)에서 나온 개념으로, 어떤 데이터나 정보의 불확실성이나 무질서도를 나타내는 정도를 의미한다. 높은 엔트로피는 더 많은 무작위성이나 불확실성을 나타내며, 낮은 엔트로피는 더 예측 가능하거나 규칙적인 패턴을 나타낸다. RANDAO에 제출하는 randao_reveal의 무작위성은 블록 제안자가 서명하는 BLS 체계의 개인키에서 결정된다. BLS 체계의 개인키의 길은 256 비트로 0 ~ 2^256 -1 사이의 숫자 중에서 무작위로 생성된다. 이 정도 범위라면 아주 높은 엔트로피를 실현 할 수 있기에 RANDAO의 무작위성에 적합하다.
비콘체인의 블록 제안자는 이전 에포크의 블록 제안자들의 randao_reveal값을 XOR 연산하여 하여 결정된 난수를 통해 무작위로 선정된다. 거기에 예상치 못한 이슈( 통신 누락 또는 고아 블록(리오그))로 인해 블록 제안자의 randao_reveal를 소실되는 경우도 발생, 중간에 갑자기 스태이킹한 이더를 출금하여 위원회 자리가 오프라인이 될 수도 있다. 이 처럼 이더리움의 RANDAO는 BLS 체계 범위 뿐만 아니라 프로토콜에서 발생할 수 있는 경우를 포함하여 무질서한 엔트로피를 구현한다.
Source of randomness : randao_reveal
class BeaconBlock(Container):
slot: Slot
proposer_index: ValidatorIndex
parent_root: Root
state_root: Root
body: BeaconBlockBody[ About ] BeaconBlock
[ Ethereum beacon-chain Github ] BeaconBlock
class BeaconBlockBody(Container):
randao_reveal: BLSSignature
eth1_data: Eth1Data # Eth1 data vote
graffiti: Bytes32 # Arbitrary data
# Operations
proposer_slashings: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS]
attester_slashings: List[AttesterSlashing, MAX_ATTESTER_SLASHINGS]
attestations: List[Attestation, MAX_ATTESTATIONS]
deposits: List[Deposit, MAX_DEPOSITS]
voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS]
sync_aggregate: SyncAggregate # [New in Altair]
# Execution
execution_payload: ExecutionPayload # [New in Bellatrix]
# Capella operations
bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES] # [New in Capella][ About ] BeaconBlockBody
[ Ethereum beacon-chain Github ] BeaconBlockBody
이더리움 비콘체인 소스코드를 보면, 모든 블록(BeaconBlock)의 본문(BeaconBlockBody)에는 제안자의 randao_reveal가 저장되는 필드가 있다. 이 randao_reveal는 검증 가능한 무작위 값을 위한 두가지 속성을 갖고 있다.
- 무작위성(randomness) : 다른 노드가 예측할 수 없어야 한다.
- 검증 가능(verifiable) : 모든 노드가 블록제안자가 제출한 randao_reveal임을 검증 할 수 있어야한다.
이러한 속성을 구현하기 위해 이더리움 2.0은 BLS signatures을 사용한다. randao_reveal의 Type(BLSSignature)에서 알 수 있듯히 randao_reveal은 블록제안자의 개인키로 서명된 BLS signatures이다.
def get_epoch_signature(state: BeaconState, block: BeaconBlock, privkey: int) -> BLSSignature:
domain = get_domain(state, DOMAIN_RANDAO, compute_epoch_at_slot(block.slot))
signing_root = compute_signing_root(compute_epoch_at_slot(block.slot), domain)
return bls.Sign(privkey, signing_root)
def get_domain(state: BeaconState, domain_type: DomainType, epoch: Epoch=None) -> Domain:
"""
Return the signature domain (fork version concatenated with domain type) of a message.
"""
epoch = get_current_epoch(state) if epoch is None else epoch
fork_version = state.fork.previous_version if epoch < state.fork.epoch else state.fork.current_version
return compute_domain(domain_type, fork_version, state.genesis_validators_root)[ About ] get_epoch_signature(), get_domain()
[ Ethereum beacon-chain Github ] get_epoch_signature()
[ Ethereum beacon-chain Github ] get_domain()
randao_reveal는 현재 블록 제안자의 Slot(block.slot)와 “DomainType('0x02000000')”(출처:DOMAIN_RANDAO)을 결합된 데이터에 블록 제안자의 개인 키로 서명하여 이를 생성한다. 그 누구도 블록 제안자의 개인키를 알 수 없으니, 다른 노드는 다음 블록의 제안자가 제출하는 randao_reveal 값을 예측 할 수 없다. ( # 첫번째 속성 조건에 만족시킨다. )
블록 제안자가 제출한 randao_reveal 값은 블록 제안자의 공개키를 통해 검증(verifiable) 할 수 있다. ( # 두번째 속성 조건에 만족시킨다. ) 여기서 검증 가능(verifiable)해야하는 이유는, 제안자가 RANDAO에 제출하는 무작위성의 기여도 값이 자의적으로 만드는 것을 방지하기 위함이다. 제안자가 자신에게 유리한 값을 의도적으로 선택할 수 없어야한다. Slot 그리고 블록 제안자의 공개키는 서명하는 당사자가 임의로 수정할 수 없거나 이미 공개된 데이터이다. 만약 검증이 실패한다면 서명 값은 블록 제안자가 본인이 의도적으로 만든 값을 randao_reveal로 사용했음을 알 수 있다. 이때, 블록 제안자의 서명값과 공개키에 대해 올바르게 검증되지 않으면 제안된 블록은 무효가 된다.
다른 검증자는 제안자의 개인 키를 모르기 때문에 예측할 수 없지만, 모든 검증자가 제안자의 공개 키를 알고 있기 때문에 쉽게 검증할 수 있다. [ About ] : randao_reveal
Update RANDAO : randao_mixes
class BeaconState(Container):
...
# Randomness
randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR]
...[ About ] BeaconState
[ Ethereum beacon-chain Github ] BeaconState
비콘체인에는 프로토콜의 모든 프로세스에서 일괄적으로( 모놀리식 라고도 한다) 적용되는 상태값(state)를 BeaconState에 저장한다. 현재 그리고 지난 RANDAO 값은 에포크 번호와 mapping(Key - Value)된 beacon state의 randao_mixes 필드(Bytes32)에 저장된다.
지난 에포크 번호를 넣으면 해당 에포크에 사용했던 RANDAO 난수를 조회할 수 있다. 이를 통해 해당 에포크의 위원회를 재구성할 수 있으며, 과거 배정되었던 위원회를 다시 계산하여, 몇 달이 지난 후에도 위원회를 삭감(slash)할 수 있다.
# process_randao() 일부
## process_randao() 함수는 바로 아래 단락에서 자세하게 다룹니다.
...
epoch = get_current_epoch(state)
...
state.randao_mixes[epoch % EPOCHS_PER_HISTORICAL_VECTOR] = mix
...하지만 모든 에포크에서 정의된 RANDAO 값을 저장하는건 아니다. 에포크 번호 별로 저장되는 RANDAO 값은 65536(uint64 : 2**16) 에포크 주기로 삭제된다. (위 코드로 봤을 때, 다음 주기의 에포크 번호로 덮어씌여 지는게 맞는 표현 같다 ). 이는 에포크 단위 (1 에포크 생성 기간 6.4분 )으로 측정했을 때 약 0.8 년(~290일) 주기가 된다. 현재 이더리움 비콘체인 Guthub에 따르면 에포크에 mapping된 RANDAO 값을 재설정하는 주기는 비콘체인 환경 변수 EPOCHS_PER_HISTORICAL_VECTOR에 정의 되어 있다.
| Name | Value | Unit | Duration |
|---|---|---|---|
EPOCHS_PER_HISTORICAL_VECTOR |
uint64(2**16) (= 65,536) |
epochs | ~0.8 years |
[ About ] EPOCHS_PER_HISTORICAL_VECTOR
[ Ethereum beacon-chain Github ] EPOCHS_PER_HISTORICAL_VECTOR
과거 에포크의 randao_mixes는 악의적 또는 프로토콜을 위반하는 검증자에 대한 삭감(slash)를 위해 과거 배정된 위원회를 재구성할 때 사용된다고 했지만, 약 0.8년이 지난 후에는 찾을 수 없다.
def process_randao(state: BeaconState, body: BeaconBlockBody) -> None:
epoch = get_current_epoch(state)
# Verify RANDAO reveal
proposer = state.validators[get_beacon_proposer_index(state)]
signing_root = compute_signing_root(epoch, get_domain(state, DOMAIN_RANDAO))
assert bls.Verify(proposer.pubkey, signing_root, body.randao_reveal)
# Mix in RANDAO reveal
mix = xor(get_randao_mix(state, epoch), hash(body.randao_reveal))
state.randao_mixes[epoch % EPOCHS_PER_HISTORICAL_VECTOR] = mix[ About ] process_randao()
[ Ethereum beacon-chain Github ] process_randao()
randao_mixes는 현재 블록의 RANDAO 값은 모든 블록이 생성될 때 마다 process_randao 함수에 의해 업데이트 된다. 때문에 비콘체인의 Slot에 블록이 없으면 RANDAO는 업데이트 되지 않는다. 이때, 호출되는 process_randao 함수는 생성된 블록의 본문(BeaconBlockBody)에 있는 블록 제안자의 개인키로 서명된 randao_reveal를 통해 두가지 작업을 거쳐 진행하게 된다.
먼저, randao_reveal이 블록제안자의 개인키로 서명됬음이 검증한다. 만약 블록 제안자의 서명값과 공개키에 대해 올바르게 검증되지 않으면 제안된 블록은 무효되며 업데이트는 진행되지 않는다.( # assert 부분 )

검증이 성공적으로 끝나면 randao_reveal는 hash() 함수로 한번 SHA256 해시처리 하여 데이터를 Bytes32로 압축한다. BLS 서명에 사용하는 BLS12–381 알고리즘은 공개키 크기에 따라 서명 압축(signature compression)을 지원한다. 기본적으로 96 bytes의 공개키를 사용하는 경우, 서명 데이터는 48 bytes가 되지만, 압축된 공개키를 사용할 경우, 반대로 48 bytes의 공개키와 96 bytes의 서명 데이터를 생성하게 된다. ( 출처 )
비콘체인에서 검증자들이 사용하는 BLS 체계의 공개키는 압축된 공개키(48 bytes)를 사용하기에 서명된 randao_reveal는 96 bytes이다. SHA256로 해시하게 되면 96 bytes에서 32 bytes로 용량을 줄여 효율적으로 데이터를 저장할 수 있다.
해시 처리 후에는 현재 에포크 번호에서 축적된 randao_mixes와 검증자의 randao_reveal을 XOR 연산하여 섞는다. ( # Mix in RANDAO reveal 부분 ) 그리고 해당 에포크 번호와 mapping된 randao_mixes에 XOR 연산된 새로운 RANDAO 값을 저장한다.
The RANDAO seed : LOOKAHEAD
비콘체인는 에포크가 생성될 때, Slot에 배정되는 블록 제안자와 입증자를 선정하며 프로토콜의 보안성과 안전 지속성을 위해 무작위로 역할을 분배한다. 이때, 무작위 시드로 RANDAO 값을 사용한다.
에포크에 지정된 32명의 블록제안자가 제시한 randao_reveal이 블록이 생성될때마다 순차적으로 XOR연산 되며, 최종적으로 (에포크의 마지막 Slot 까지 블록이 생성될 때) 완성된 값은 다른 에포크의 역할을 선별하는 시드 값으로 사용된다.
| Name | Value | Unit | Duration |
|---|---|---|---|
MIN_SEED_LOOKAHEAD |
uint64(2**0) (= 1) |
epochs | 6.4 minutes |
[ About ] MIN_SEED_LOOKAHEAD
[ Ethereum beacon-chain Github ] MIN_SEED_LOOKAHEAD
이때, 현재 에포크에서 만들어진 시드는 바로 다음 에포크가 아닌 +2 에포크( MIN_SEED_LOOKAHEAD + 1 ( = 2 ) )의 시드로 사용된다. 아래 이더리움 비콘체인 Guthub에 적용된 환경 변수를 보면 현재 적용된 MIN_SEED_LOOKAHEAD를 확인할 수 있다.
def get_seed(state: BeaconState, epoch: Epoch, domain_type: DomainType) -> Bytes32:
"""
Return the seed at ``epoch``.
"""
mix = get_randao_mix(state, Epoch(epoch + EPOCHS_PER_HISTORICAL_VECTOR - MIN_SEED_LOOKAHEAD - 1)) # Avoid underflow
return hash(domain_type + uint_to_bytes(epoch) + mix)
def get_randao_mix(state: BeaconState, epoch: Epoch) -> Bytes32:
"""
Return the randao mix at a recent ``epoch``.
"""
return state.randao_mixes[epoch % EPOCHS_PER_HISTORICAL_VECTOR][ About ] get_seed()
[ Ethereum beacon-chain Github ] get_seed()
[ About ] get_randao_mix()
[ Ethereum beacon-chain Github ] get_randao_mix()
새로운 에포크의 위원회(committee)에 블록제안자와 검증자를 선별하기 위한 시드를 조회할때 get_seed() 함수를 사용한다. 함수의 내부 로직을 보면 현재 에포크(위원회를 선별 중인)에서 뒤로 두번째 에포크 ( 현재 에포크 - MIN_SEED_LOOKAHEAD - 1 )에 저장된 randao_mix를 get_randao_mix() 함수를 통해 조회하는걸 볼 수 있다.
RANDAO 취약점의 보완점 : MAX_SEED_LOOKAHEAD
현재 에포크에서 만들어진 난수(최종 randao_mix)는 +2 에포크를 생성하기 위한 시드라는 사실을 알았다. 만약 우리가 비콘체인의 프로토콜을 공격한다는 마음이 있다면 +1 에포크가 진행되는 동안( 6.4분 ), 만들어진 난수를 통해 +2 에포크의 위원회를 예측할 수 있지 않을까? 공격자는 예측한 위원회에 적절한 타이밍에 계산된 공개키를 가진 검증자로 합류(활성화:activations)하여 블록 검증자가 될 수 있을 것이다. 또한 다수의 계정(DVT:Distributed Validator Technology)으로 검증자 역할을 수행하는 공격자가 적절한 타이밍에 탈출(종료:exits)하여 본인의 다른 계정을 블록제안자로 만들 수도 있을 것이다. 현재 RANDAO의 높은 엔트로피로 위와 같은 상황은 발생할 확률이 매우 희박하지만, 이는 공격의 문을 열어줄 수 있기에(스테이크 그라인딩:stake grinding의 한 유형입니다) 혹시 모를 상황을 대비해 비콘체인은 방어 프로토콜을 설정했다.

| Name | Value | Unit | Duration |
|---|---|---|---|
MAX_SEED_LOOKAHEAD |
uint64(2**2) (= 4) |
epochs | 25.6 minutes |
[ About ] MAX_SEED_LOOKAHEAD
[ Ethereum beacon-chain Github ] MAX_SEED_LOOKAHEAD
이를 방지하기 위해 비콘체인은 공격자가 예측할할 수 있는 최대 시드를 MAX_SEED_LOOKAHEAD(=4)로 가정하고 모든 검증 활성화와 종료를 4 에포크 만큼 지연시켜 지속적으로 정직했던 검증만이 유입될 수 있도록 한다.
에포크 N에서 생성된 시드는 MIN_SEED_LOOKAHEAD에 의해 에포크 N+2의 시드가 된다. 이때, 공격자가 즉시 탈출한다고 했을 때, 에포크는 N+1에 탈출하게 되지만, MAX_SEED_LOOKAHEAD에 의해 에포크 N+5까지는 검증자의 역할을 수행하게 된다.
공격자의 새로운 검증자 합류 또한 마찬가지이다. 포크 N에서 생성된 시드는 MIN_SEED_LOOKAHEAD에 의해 에포크 N+2의 시드가 될 때, 에포크 N+2의 블록 검증자가 되기 위해 새로운 검증자로 합류한다. 하지만 MAX_SEED_LOOKAHEAD에 의해 실제로 에포크 N+5부터 검증자로 활동하게 될 것이다.
공격자는 위 시나리오대로 블록 검증자가 되기 위해선 에포크 N+1이 완료 되기전( 6.4분 안에 ) 4 epochs 후의 위원회를 예측해야 하고 합류 또는 탈출까지 수행해야 할 것이다. Justim Drake의 이더리움 노트에 의하면 정직한 검증자가 전체 풀의 10%만 온라인 상태일 때, 공격자가 4 epochs 후의 시드를 예측할 수 있는 확률은 ( 1- 10% )^3*64 로, 약 10억분의 1에 불과하다고 한다. ( 출처 : Phase 0 design notes 69번 | https://notes.ethereum.org/@JustinDrake/rkPjB1_xr )
마지막 공개자 공격(Last Revealer) 문제

어느 에포크 N의 시드값은 에포크 N-2 ( 두 에포크 전 )에서 생성된 시드 값이 되며, 시드에서 생성된 무작위 값에 따라 임무(블록 제안자와 입증자)가 할당된다. 이때 시드 값이 확정되는 시기는 에포크 N-2의 마지막 Slot 블록제안자가 블록 생성을 완료 했을 시점이다. 때문에 블록제안자가 에포크의 마지막 슬롯에서 블록을 제안하도록 할당받으면, 다음 에포크의 할당에 대해 약간의 통제권을 갖게 된다.
마지막 Slot의 블록 제안자가 마지막 공개자라고 했을 때, 마지막 공개자는 앞서 블록을 생성하며 공개했던 제안자들의 randao_reveal을 계산(XOR)할 수 있다. 이때 마지막 공개자는 마지막으로 자신의 randao_reveal을 섞거나, 혹은 의도적으로 블록을 생성하지 않으면서 자신의 randao_reveal을 섞지 않을 수 있다. 이러한 방식을 통해 마지막 블록제안자는 두 가지 결과중 하나를 선택하여 다다음 에포크(에포크 N+2)의 위원회 선정에 영향을 줄 수 있다.
예를 들어 다음과 같은 상황이 발생할 수 있다. 홀짝에 따라서 보상을 가져가는 도박 컨트랙트에 참여하여 홀수에 돈을 건 A가 RANDAO의 마지막 공개자가 될 수 있다. A는 다른 RANDAO 참여자들이 공개하는 randao_reveal를 지켜보았다가 자신이 randao_reveal를 제출하면 시드에 따라 짝수가 생성된다는 사실을 알 수 있다. 따라서 A는 의도적으로 자신의 randao_reveal를 의도적으로 제출하지 않고 해당 에포크에 난수를 본인에게 유리한 방향으로(홀수가 나올 수 있게) 유도할 수 있다.
실제로 비콘체인의 RANDAO 값은 더 머지 이후 EIP-4399에서
PREVRANDAOopcode를 통해 스마트컨트랙트 내에서 사용할 수 있게 됬다. 만약,PREVRANDAO을 통해 복권 또는 홀짝 스마트컨트렉트를 개발하게 된다면 위 상황은 충분히 발생할 수 있는 사례가 될 것이다.
RANDAO는 참여자의 동기부여와 난수에 대한 공정성이 매우 중요한 프로토콜이지만, 위와 같은 상황을 통해 마지막 공개자와 다른 참여자간에 편향된(불공평한) 상황이 발생 하게 된다. 이러한 문제는 마지막 공개자 공격(Last Revealer)라고 한다.
Last Revealer 보완점 : 구현예정 ?
이더리움은 RANDAO의 Last Revealer 문제에 대해 충분히 인지하고 있지만, 이더리움 더 머지(The Merge) 업데이트 내용이 정의된 EIP-2982 표준을 보면 마지막 공개자가 블록 생성을 실패시켜 randao_reveal을 의도적으로 제출하지 않을 가능성은 매우 낮다고 얘기한다. (아래 출처 EIP-2982 Random sampling 참고) ”에포크의 마지막 블록제안자가 의도적으로 블록 생성을 포기하면서 본인에게 유리한 무작위 시드를 생성하여 이득을 취하는 경우는 극히 드물것이다”는게 이유이다. 비콘체인에서 블록제안자는 본인이 제시한 블록이 채택됨에 따라 보상을 얻게 된다. 즉, 마지막 공개자가 이 보상을 포기하면서 까지 Last Revealer 공격을 시도할 이유가 없다는 것이다.
In the future we plan to use verifiable delay functions (VDFs) to further increase the random seeds’ robustness against manipulation.
향후에는 검증 가능한 지연 함수(verifiable delay functions : VDF)를 사용하여 조작에 대한 무작위 시드의 견고성을 더욱 높일 계획입니다.
출처 EIP-2982 Random sampling : https://eips.ethereum.org/EIPS/eip-2982#seed-selection
하지만 EIP-2982 Random sampling의 마지막 단락을 보면 해당 문제에 대해 이더리움은 검증 가능한 지연 함수(verifiable delay functions:VDF)를 통해 위 문제로 발생할 수 있는 평향성에 대해 견고성을 높일 계획이라고 한다. 현재 작성된 이 글은 카펠라 업데이트까지 진행된 시점이다. 아직까지는 이더리움 프로토콜에서 VDF에 대한 내용이 반영되지 않았다. 이더리움 공식 Guthub의 비콘체인이 구현된 레포지토리에 VDF를 검색해도 해당 내용은 검색되지 않는다.
검증 가능한 지연 함수: Verifiable Delay Function (VDF)
아직 구현되지 않았지만, 이더리움이 계획중인 검증 가능한 지연 함수(이하 VDF)에 대해 간단하게 알아보자. Last Revealer 문제는 결국 마지막 공개자가 본인의 randao_reveal을 섞어서 얻은 난수가 본인에게 유리한지 아닌지 판단하에 발생하게된다. VDF는 간단한 연산을 통해 얻을 수 있는 결과를 의도적으로 복잡한 연산을 거쳐, 시드로부터 난수를 계산하는데까지 걸리는 시간을 지연시키는 함수이다. 이를 통해 의적 행위자가 계산하는 시간을 오래걸리게 만들어 Last Revealer 문제를 해결한다.
VDF는 VDF의 결괏값을 다시 VDF의 입력값으로 이용하여 계층화(folding)한다. 예를 들어 VDF 함수에 5를 입력하면, ( …((())) …. ) 라는 계층적인 공식을 거쳐 최종 결과값을 만들어 낸다. 계층이 깊어질수록 연산이 어려워지고 따라서 의사 난수를 계산하는 데까지 시간도 오래 걸리게 된다.
이더리움 연구 블로그 에 게시된 글을 봤을 때, VDF를 설계하고 지정하는 데 많은 작업이 이루어졌지만 현재로서는 이를 구현하려는 적극적인 계획은 없어보인다. 이더리움 암호학 연구팀은 VDF 설계 방식에 동의하지만, 현재 이더리움 내에서 VDF를 사용하는 것을 권장하지 않으며, 지속적인 연구와 상당한 개선은 향후 수정될 수 있는 부분이라고 한다.
참고 ethresear.ch : https://ethresear.ch/t/statement-regarding-the-public-report-on-the-analysis-of-minroot/16670?u=benjaminion
마무리
이더리움 코어를 조사하면 합의와 비콘체인에 대한 정보는 많이 찾을 수 있지만, 놀랍게도 RANDAO에 대한 자료는 상대적으로 부족한 편이였다. 이를 계기로 RANDAO에 중점을 두어 이더리움 코어의 핵심 프로토콜에 대해 자세히 다뤄보았다. 이번 글을 통해 국내의 다수 블록체인 개발자들이 유익한 정보를 얻길 바라며, 이와 같은 내용으로 글을 마무리한다.