Validator’s Note 8 — 어서와 인출은(withdrawal)은 처음이지?

Youngbin Park
DSRV
Published in
14 min readMar 30, 2023

--

Disclaimer: 이 글은 정보 전달을 위한 목적으로 작성되었으며, 특정 프로젝트에 대한 투자 권고, 법률적 자문 등 목적으로 하지 않습니다. 모든 투자의 책임은 개인에게 있으며, 이로 발생된 결과에 대해 어떤 부분에서도 DSRV는 책임을 지지 않습니다. 본문이 포괄하는 내용들은 특정 자산에 대한 투자를 추천하는 것이 아니며, 언제나 본문의 내용만을 통한 의사결정은 지양하시길 바랍니다. 추가적으로 이 글이 쓰여진 시점과 현재 모두 DSRV는 이더리움의 벨리데이터로 참여하고 있음을 알려드립니다.

곧 이더리움에 스테이킹했던 ETH를 인출(withdraw)할 수 있습니다. 이더리움의 EL 측 포크의 이름인 상하이(Shanghai)와 CL 측 포크의 이름인 카펠라(Capella)를 합쳐 샤펠라(Shapella)라고 명명된 이번 업그레이드가 이루어지고 나면 인출 기능이 활성화됩니다. 메인넷 업그레이드를 진행하기 전 마지막 단계로, 지난 3/15 (KST) 골리(Goerli) 테스트넷에서 샤펠라 업그레이드가 성공적으로 완료되었으며, 이더리움 메인넷에서는 4/13 (KST) 업그레이드가 진행될 예정입니다.

이번 업그레이드 이전에는 스테이킹한 ETH의 인출이 불가능 하였으며, 스테이킹을 시작하려면 32ETH 가 필요했습니다. 이러한 제한으로 인해 사용자가 적은 금액으로 스테이킹을 시작하고 디파이(DeFi)에서 LSDs(Liquid Staking Derratives)를 활용할 수 있는 리퀴드 스테이킹(Liquid Staking)이라는 개념이 많은 관심을 받기 시작하였습니다. 사용자들은 스테이킹을 하면서 수익을 극대화할 수 있는 방법으로 리퀴드 스테이킹을 선택했고, 다양한 리퀴드 스테이킹 서비스가 계속 등장하면서 리퀴드 스테이킹 시장은 크게 성장했습니다.

현재 1790만개가 넘는 ETH가 스테이킹되어 있으며 이중 약 43%가 리퀴드 스테이킹을 통해 스테이킹 되어 있습니다. 하지만 리퀴드 스테이킹에서의 인출은 기본적인 이더리움 인출 과정과 약간은 다르게 이루어집니다. 따라서 오늘은 밸리데이터(혹은 노드 오퍼레이터) 입장에서 이더리움 생태계의 큰 부분을 차지하고 있는 리퀴드 스테이킹의 인출 과정을 대표 사례인 라이도(Lido)를 통해 살펴보면서 그 차이점을 정리해 보려고 합니다.

Background

먼저 이더리움의 인출에는 1) 부분 인출(Partial withdrawal) 및 2) 전체 인출(Full withdrawal)의 두 가지 종류가 있습니다. 부분 인출의 경우 32ETH를 초과하여 쌓인 잔액이 자동으로 인출되며 밸리데이터는 계속해서 활성화된 상태로 존재합니다. 반면 전체 인출의 경우 밸리데이터가 종료(Exit)되어 더 이상 비콘 체인 합의에 참여하지 않으며, 밸리데이터가 종료되고 나면 32ETH에 리워드를 포함한 전체 잔액에 대한 인출이 이루어집니다. 따라서 전체 인출을 할때는 부분 인출에는 없던 종료 과정이 필요하게 됩니다.

뿐만 아니라 밸리데이터가 전체 인출되는 경우도 두 가지로 나뉩니다. 256 epoch(~27시간) 이상 활성화된(active) 상태였고 슬래싱(slashing)를 당하지 않은 밸리데이터는 자발적 종료(Voluntary Exit)를 요청할 수 있습니다.[1] 반면 슬래싱을 당하거나 네거티브 리워드를 받아 잔액이 32ETH 이하가 된 밸리데이터의 경우에는 별도의 요청 없이 강제로 종료(Forced Exit) 당하게 됩니다. 본 글에서는 밸리데이터가 자발적 종료를 통해 전체 인출을 하려는 경우를 살펴보겠습니다.

이더리움의 인출 (aka Solo Staker)

이더리움에서 스테이킹을 하여 밸리데이터를 운영하기 위해서는 두가지 키가 필요합니다. 컨센서스에 참여하여 서명을 하기 위해 필요한 validator key 와 이더리움을 인출받을 주소인 withdrawal key(execution address)입니다. 사용자는 이더리움 예치 컨트랙트에 ETH를 예치할 때 validator key(public) 와, 밸리데이터의 서명(signature), 그리고 withdrawal credential(withdrawal key)를 입력합니다.

1.withdrawal credential에 포함된 withdrawal key가 바로 스테이킹되었던 ETH가 인출되는 주소입니다. 따라서 예치 시 withdrawal credential을 설정하지 않은 경우, 인출을 받기 위해서는 반드시 withdrawal credential이 0x01로 시작하고 인출을 받을 withdrawal key을 포함하여 설정되도록 업데이트(BLSToExecutionChange)해야 합니다.[2]

2.밸리데이터는 전체 인출을 하기 위하여 VoluntaryExit을 요청할 수 있습니다. 밸리데이터는 epoch 및 validator_index를 포함하여 VoluntaryExit 메세지를 생성하고, 여기에 서명을 하여 CL에 전파합니다.

class VoluntaryExit(Container): 
epoch: Epoch # Earliest epoch when voluntary exit can be processed
validator_index: ValidatorIndex
class SignedVoluntaryExit(Container):     
message: VoluntaryExit
signature: BLSSignature

3.블록을 생성하는 Proposer는 CL에 전파된 SignedVoluntaryExit을 확인한 후 비콘 체인 블록에 담고 exit queue(종료 대기열)에 넣어줍니다.[3] 이때 한 블록에 담길 수 있는 VoluntaryExit 개수에는 제한이 있어(MAX_VOLUNTARY_EXITS), 한 블록당 최대 16개의 VoluntaryExit 요청만이 처리될 수 있습니다.

class BeaconBlockBody(Container):   
...
voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS]
bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES] # [New in Capella]
...

4.밸리데이터는 exit queue에서도 일정 기간을 기다려야 완전히 종료될 수 있습니다. 최소 기간은 4 epoch 이지만, 한 에폭당 처리될 수 있는 최대 종료의 수의 제한(churn limit)이 있기 때문에 얼마나 많은 대기자가 있는가에 따라 그 대기 시간이 증가할 수 있습니다. 최대 종료의 수의 제한은 이더리움의 총 밸리데이터 수에 따라 변화합니다. 약 55만 개의 밸리데이터가 있는 현재는 한 에폭당 최대 8개의 밸리데이터가 종료될 수 있습니다.

CHURN_LIMIT_QUOTIENT = 2¹⁶ = 65,536
active_validator_indices / CHURN_LIMIT_QUOTIENT= 558,205 / 65,536 = 8.517

def get_validator_churn_limit(state: BeaconState) -> uint64:
active_validator_indices = get_active_validator_indices(state, get_current_epoch(state))
return max(MIN_PER_EPOCH_CHURN_LIMIT, uint64(len(active_validator_indices)) // CHURN_LIMIT_QUOTIENT)

5.exit queue가 끝나면 밸리데이터는 드디어 종료 상태가 되어, 더 이상 밸리데이터로서의 역할을 수행하지 않게 됩니다. 하지만 exit queue에서 대기하는 동안은 여전히 밸리데이터 이므로 밸리데이터의 역할을 수행해야 하며, 슬래싱을 당할 수도 있습니다.

6.종료가 완료 후에도 실제로 자금이 인출 가능한(withdrawable) 상태가 될 때까지는 256 epoch(약 27시간)을 기다려야 합니다. (이때 슬래싱을 당하여 강제 종료된 경우에는 27시간이 아닌 약 36일을 기다려야 합니다.)

7.그 후에는 다시 withdraw queue(인출 대기열)에서 자신의 순번을 기다려야 합니다. withdraw queue에서 인출은 선입선출이 아닌 밸리데이터 인덱스 순서대로 처리되며 부분 및 전체 인출을 구분하지 않고 한 블록에 최대 16개씩 처리됩니다.

class Withdrawal(Container):
index: WithdrawalIndex
validator_index: ValidatorIndex
address: ExecutionAddress
amount: Gwei

위 과정이 모두 끝나면, 별도의 트랜잭션없이 EL에 withdrawal address의 잔액이 자동으로 증가하며 인출한 금액을 사용할 수 있게 됩니다. [4]

라이도(Lido)의 인출

이더리움에서 인출 기능이 추가됨에 따라 라이도 또한 stETH(LSD token)을 1:1 로 ETH로 출금할 수 있도록 하기 위하여, 스테이킹 라우터 및 출금 기능을 위한 v2 업그레이드를 발표하였습니다. (스테이킹 라우터나, 사용자 단에서의 Lido의 출금에 대해서는 다루지 않을 예정이므로 궁금하신 분들은 링크를 참고하시면 좋을 것 같습니다.) 라이도 v2 에서 밸리데이터의 종료 및 인출은 다음과 같이 진행됩니다.

1.라이도는 이더리움 예치 컨트랙트와 직접 상호작용 하는 것이 아닌 별도의 라이도 스테이킹 컨트랙트를 통하여 스테이킹을 합니다. 솔로 스테이커의 경우 withdrawal key와 validator key를 모두 동일한 주체가 가지고 있는 것과 다르게, 라이도의 경우 withdrawal key는 라이도 컨트랙트의 주소입니다.[5]

라이도에서는 하나의 withdrawal key에 대하여 다수의 오퍼레이터들이 운영하는 밸리데이터가 매핑되어 있기 때문에 어떠한 밸리데이터를 먼저 종료 시킬 것인지에 대한 내부 정책이 필요하고, 합의된 정책을 기반으로하여 종료할 밸리데이터를 선택합니다.[6] stETH 사용자가 출금을 요청하면 라이도 오라클(oracle)은 종료시킬 밸리데이터에 대하여 오라클 컨트랙트를 호출하여 종료 요청 이벤트를 생성합니다.

2. 각 노드 오퍼레이터는 오라클 컨트랙트에서 생성된 이벤트를 관찰하고 있다가, 자신의 밸리데이터에 대한 요청이 들어오면 위 기본적인 이더리움 인출 의 2번 과정과 같이, 서명을 포함한 VoluntaryExit 메세지를 CL 네트워크에 전파합니다.

라이도는 validator key (secret)를 가지고 있지 않기 때문에 솔로 스테이커처럼 스스로 밸리데이터를 바로 종료시킬수 없으므로, validator key를 가진 노드 오퍼레이터들에게 종료하라고 요청하고 그들이 요청을 처리하기를 기다려야 합니다. 하지만 라이도의 요청부터 밸리데이터가 메세지를 전송하는 사이의 과정은 오프체인으로 일어나며 노드 오퍼레이터가 이러한 요청을 처리하지 않게 되는 경우 문제가 발생할 수 있습니다. 라이도는 이에 대한 대책으로 밸리데이터가 출금 요청을 처리하였는지를 모니터링하여, 처리가 지연되는 경우 요청을 다른 밸리데이터에게 라우팅 하여 우선 종료처리하고 지연된 밸리데이터에게는 패널티를 주는 방식등을 고려하고 있습니다.[7]

뿐만 아니라 라이도는 밸리데이터가 요청을 처리하는 과정을 반자동화 하기 위해 밸리데이터들이 실행시킬 수 있는 Ejector라는 툴을 개발하였습니다. Ejector는 라이도 오라클에서 보낸 종료 요청을 감지하고, 밸리데이터가 미리 서명한 메세지를 가지고 있다가 요청을 받은 즉시 메세지를 전파합니다. 밸리데이터가 미리 서명한 메세지를 라이도에 제공하고, 라이도가 원할 때 이들을 종료시키는 방법이 있으나, 이러한 경우 중앙화로 인한 보안상의 문제가 발생할 수 있기 때문에 이를 노드 오퍼레이터에 분산하여 처리하는 방식을 사용합니다.

출처: https://research.lido.fi/t/withdrawals-automating-lido-validator-exits/3272

3. 밸리데이터가 출금 요청을 보낸 이후의 과정은 위의 기본적인 이더리움 인출 3–7 과정과 동일하게 진행됩니다. 인출된 리워드는 라이도의 컨트랙트로 취합되어 stETH를 상환하는데 사용하거나, 다시 스테이킹 됩니다.

Conclusion

샤펠라 업그레이드로 인출이 가능해 진다면 이더리움 스테이킹의 유동성 위험과 락업(lock-up)의 불확실성에 대한 우려가 줄어들 것입니다. 위험성의 감소로, 이더리움 스테이킹에 더 많은 참여가 이루어질 것을 기대해 볼 수 있을 것 같습니다. 이와 같은 맥락에서 스테이킹을 하면서 디파이를 통해 추가적인 수익을 창출할 수 있는 LSD에 대한 관심도 높아지고 있습니다. 또한 DVT(Distributed Validator Technology)를 사용하면 여러 노드 오퍼레이터가 하나의 밸리데이터를 관리하여 노드 운영에 대한 부담을 낮출 수 있고, 이를 통해 더 많은 사람들이 직접 노드를 운영하여 스테이킹에 참여할 수 있을 것으로 예상됩니다. 리퀴드 스테이킹 서비스들 또한 더욱 공개적이고 탈중앙화된 밸리데이터 세트를 만들기 위해 SSV 나 Obol 같은 DVT 프로젝트와 적극적으로 협력하고 있습니다.

라이도처럼 validator key와 withdrawal key의 소유 주체가 다른 리퀴드 스테이킹 서비스의 경우, 서비스 제공자 측에서 밸리데이터에게 인출을 요청하거나 밸리데이터가 서명한 종료 메세지를 미리 전달받는 과정이 필요합니다. 이처럼 인출로 인해 밸리데이터의 영향력이 커질수록, 리퀴드 스테이킹에서 밸리데이터를 운영하는 노드 오퍼레이터의 탈중앙화 정도 또한 더욱 중요해집니다. 그러나 리퀴드 스테이킹 서비스에서는 노드 오퍼레이터들이 탈중앙화 될수록, 오프 체인으로 이루어지는 위와 같은 과정에서 노드 오퍼레이터가 정직하게 행동하기만을 기대하기는 어려워 집니다. 따라서 노드 오퍼레이터가 일정 자금을 담보로 제공하거나 페널티를 부과하여 출금을 올바르게 처리하도록 강제할 수 있는 아키텍처를 구축하는 것이 중요하게 고려되어야 할 것으로 보입니다.

샤펠라 업그레이드가 코앞으로 다가온 지금, 이번 업그레이드가 스테이킹 시장에 어떤 변화를 가져올지 지켜봐 주시길 바랍니다. 읽어주셔서 감사합니다.

Written by
Youngbin Park, Research Engineer, DSRV Validator Team (Twitter @bin0_0bin)

Reference

[1] https://github.com/ethereum/consensus-specs/blob/214760b59bc2355cf0259ae2d042634a0d830525/configs/mainnet.yaml
[2] https://github.com/ethereum/consensus-specs/pull/2149
[3] https://github.com/ethereum/consensus-specs/blob/master/specs/phase0/beacon-chain.md
[4] https://eips.ethereum.org/EIPS/eip-4895
[5] https://etherscan.io/address/0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f
[6] https://research.lido.fi/t/withdrawals-on-validator-exiting-order/3048
[7] https://hackmd.io/zHYFZr4eRGm3Ju9_vkcSgQ#The-need-for-validator-exits-in-a-staking-protocol

--

--