
Solana의 합의
핵심 인사이트
- 동기화에서 Proof-of-History(PoH)의 역할: PoH는 합의 알고리즘이 아니라 Solana의 합의 메커니즘이 동기화에 사용하는 도구입니다. 마찬가지로 Proof-of-Stake(PoS)는 합의 자체가 아니라 시빌 저항 메커니즘입니다.
- 합의에는 투표 트랜잭션이 필요합니다: 블록 내 투표는 TPS 지표를 인위적으로 부풀리기 위한 불필요한 트랜잭션이 아닙니다. 투표가 gossip(비공식 P2P 통신)을 통해서만 전파되면 검증인마다 Tower의 투표 상태를 다르게 인식할 수 있습니다.
- Solana에는 두 가지 주요 확정 규칙이 있습니다: 단기 포크 선택을 위한 규칙(낙관적 확정)과 최종성을 위한 완전한 PoS 합의 규칙(최종 확정/루트 지정)입니다. 클라이언트와 사용자는 원하는 보안 속성과 맞춤형 UX에 따라 이러한 확정 규칙을 선택할 수 있습니다. 이는 “confirmed”와 “finalized”라는 두 가지 커밋 수준으로 나타납니다.
- 검열 위험 이해하기: 검증인과 개발자는 검증인이 블록 생성 순서를 방해하려는 검열 공격의 가능성을 인지해야 합니다. 이러한 공격의 작동 방식과 실행에 필요한 연산 능력 및 스테이킹 지분의 역할을 이해해야 합니다.
- 예정된 프로토콜 업그레이드: 검증인과 개발자는 비동기 실행과 프로그래밍 방식의 슬래싱 등 Solana 합의 메커니즘의 향후 변경 사항에 적극적으로 대비해야 합니다.
소개
Solana의 활동이 증가하면서 스택의 여러 계층이 전례 없는 수준으로 시험받고 있습니다. 로컬 수수료 시장과 같은 “인기” 주제는 많은 글과 논의에서 다뤄졌지만, Solana의 합의는 오랫동안 주목받지 못했습니다. 그러나 악의적 공격의 유인과 잠재적 익스플로잇의 수익이 커지는 만큼, 활동과 관심의 증가는 커뮤니티에 합의에 대한 깊은 이해를 요구합니다.
합의는 전체 커뮤니티가 이해해야 할 Solana의 가장 중요한 요소 중 하나입니다. 수천 개의 검증인이 트랜잭션의 정규 순서에 합의하는 방식을 결정하기 때문입니다.
합의는 오랫동안 분산 시스템 분야에서 연구되어 왔습니다. Lamport, Shostak, Pease가 작성한 비잔틴 장군 문제는 1980년대 초에 발표되었습니다. RAFT와 같은 합의 알고리즘은 web2에서 오랫동안 사용되었습니다. 암호화폐 분야에서는 대부분의 합의 알고리즘이 BFT 합의를 서로 다르게 구현한 형태입니다. 여기에는 Gasper(Ethereum), Tendermint(Cosmos), MonadBFT(Monad), HotShot(Espresso), Narwhal/Tusk(Sui)가 포함됩니다.
이 글은 Solana의 합의 메커니즘인 TowerBFT를 형식적으로 증명하려는 것이 아닙니다. 대신 지금까지 주로 Solana Labs와 Firedancer 기여자들만 자세히 알고 있던 Solana의 합의 작동 방식을 개발자와 더 넓은 커뮤니티에 설명하는 것을 목표로 합니다. 장단점과 한계에 대한 논의도 함께 다룹니다.
합의에 대한 간략한 입문
합의 프로토콜의 목적은 트랜잭션과 블록 내 트랜잭션의 상대적 순서에 합의하는 것입니다. 네트워크의 검증인이 트랜잭션의 정규 순서에 합의하는 합의 프로토콜에는 크게 두 가지 유형이 있습니다.
- 최장 체인 프로토콜: 이러한 프로토콜은 Bitcoin의 Nakamoto 합의처럼 구축에 가장 많은 연산 노력이 필요했던 체인을 정규 체인으로 선택합니다. 이는 흔히 블록 수가 가장 많은 체인과 일치하지만, 더 정확히는 누적 작업량 또는 연산 능력이 가장 큰 체인을 의미합니다.
- BFT 유형 프로토콜: 대부분의 PoS 프로토콜은 BFT 합의 알고리즘의 한 형태를 구현합니다. pBFT와 같은 프로토콜은 활성성과 보안을 위한 임계값에 의존합니다. 일관성과 가용성은 CAP 정리가 보장하는 두 가지 속성입니다. CAP 정리에 따르면 모든 분산 데이터 저장소는 일관성, 가용성, 파티션 내성이라는 세 가지 보장 중 두 가지만 제공할 수 있습니다.
최장 체인 합의 프로토콜과 BFT 유형 합의 프로토콜 모두 각자의 확정 규칙에서 보안을 확보합니다. 안전성과 활성성으로 구성되는 보안은 주어진 확정 규칙에서 나오며 체인 자체의 속성이 아닙니다. Ethereum Foundation의 정의에 따르면 확정 규칙은 “노드가 실행하여 특정 블록이 확정되었는지 출력하는 알고리즘입니다. 확정된 경우, 주로 네트워크 동기성과 정직한 스테이킹 지분 비율에 관한 특정 가정 아래에서 해당 블록은 절대 재구성되지 않음이 보장됩니다.”
결국 그 기반에는 항상 사회적 합의가 있습니다. 특정 확정 규칙을 통해 보안을 정의하는 클라이언트 코드를 작성하는 사람들이 최종적으로 이를 결정합니다.
Proof-of-Stake는 BFT 모델에 추가 계층을 도입하며 참여자가 자신의 스테이킹 지분을 제공하도록 요구합니다. 참여자는 일련의 규칙을 준수하면 보상을 받지만, 이중 서명과 같은 위법 행위가 입증되면 슬래싱될 수 있습니다. 이를 책임성 있는 안전성이라고 하며, 프로토콜은 정직한 노드에 외부 효과를 주지 않고 악의적 노드를 식별하고 처벌할 수 있습니다. 하지만 이는 BFT 합의 프로토콜의 근본적인 보안 메커니즘을 대체하지 않습니다. 네트워크 중단을 피하려면 부정직한 노드가 3분의 1 미만이어야 하고, 잘못된 트랜잭션의 검증을 막으려면 3분의 2 미만이어야 합니다. 스테이킹 지분 기반 시스템은 네트워크 효율성을 방해하거나 저해할 수 있는 행동에 대가를 부과합니다.
이러한 BFT 네트워크에는 두 가지 중요한 임계값이 있습니다.
- 1/3: 부정직한 노드가 전체의 3분의 1 이상이면 네트워크가 “중단”될 수 있습니다. 이 경우 해당 노드들이 참여를 거부하기만 해도 나머지 노드는 합의에 필요한 3분의 2의 절대다수에 도달할 수 없습니다. 따라서 네트워크가 잘못된 트랜잭션을 생성하는 것이 아니라 모든 트랜잭션 생성을 완전히 중단합니다. 널리 쓰이는 지표 중 하나는 다소 거칠지만 Nakamoto 계수입니다. 이는 활성성 장애, 즉 블록 생성 중단을 일으키는 데 필요한 최소 노드 수를 나타냅니다.
- 2/3: 부정직한 노드가 전체의 3분의 2 이상이면 공모하여 원하는 트랜잭션을 검증할 수 있습니다. 이는 네트워크가 정상적으로 작동하지 않고 부정직한 절대다수가 지시한 대로 트랜잭션을 처리하는 최악의 상황입니다. 공격자가 스테이킹 지분의 67% 이상을 통제하면 주요 거래소의 노드(예: Binance)와 같은 정직한 노드를 격리할 수 있습니다. 데이터 센터와 공모해 해당 노드의 네트워크 트래픽을 제한하는 방식으로 격리할 수 있습니다. 그러면 악의적 주체는 격리된 노드가 자신이 만든 블록을 최종 확정하도록 하는 동시에, 충돌하는 블록을 나머지 네트워크에 배포할 수 있습니다. 이러한 공격은 격리된 노드의 제한된 시야를 악용합니다. 나머지 네트워크와 격리된 노드가 온체인 상태를 서로 다르게 보게 되므로 이중 지출이 발생할 수 있습니다.
스테이킹 지분이 33%를 넘는 더 낮은 수준에서도 유사한 공격이 가능하지만, 단순한 격리가 아니라 네트워크 파티션을 만들어야 합니다. 이 상황에서 비잔틴 이해관계자는 네트워크 파티션을 악용해 서로 충돌하는 정보로 네트워크의 각 구간을 조작할 수 있으며, 마찬가지로 이중 지출과 기타 안전성 장애가 발생할 수 있습니다.
일반적으로 노드 수가 많을수록 특정 주체가 임계값에 도달할 만큼 상당한 비율을 손상시키기 어려워집니다. 단, 지리적으로 분산되어 있다고 가정합니다. 그러나 더 큰 네트워크를 원하는 목표는 효율성과 충돌하는 경우가 많습니다. 노드가 많아지면 데이터 전송 요구량이 늘고 투표 전파에 더 많은 시간이 필요해 합의가 느려질 수 있습니다. 일부 프로토콜은 최대 노드 수에 엄격한 상한을 두기도 합니다.
Proof-of-History(PoH)
Proof-of-Stake(PoS)가 네트워크의 합의를 보장하는 동안 Solana는 PoS 합의 메커니즘에 Proof of History(PoH)를 통합해 지속적인 블록 생성을 위한 동기화를 지원합니다. Solana는 동기화된 합의 라운드를 기다리지 않고 느리거나 응답하지 않는 슬롯 리더의 슬롯을 건너뜁니다. PoH는 이벤트가 발생한 정확한 시점을 증명하는 것이 아니라 이벤트의 순서와 이벤트 간에 흐른 시간을 증명합니다.
일반적인 인식과 달리 Proof-of-History(PoH) 자체는 합의 메커니즘이나 알고리즘이 아닙니다. 현재 구현의 합의는 PoH의 일부 요소를 활용하지만, 이론적으로 PoH를 제거하고 구현을 소폭 변경해도 Solana의 합의는 계속 작동할 수 있습니다.
PoH의 핵심은 검증 가능한 지연 함수(VDF)와 유사한 단순한 해싱 알고리즘이지만, 기술적으로 VDF는 아닙니다. Solana는 순차적인 역상 저항 해시 함수(SHA-256)를 사용해 이를 구현합니다. 함수는 지속적으로 실행되며 한 반복의 출력을 다음 반복의 입력으로 사용합니다. 이 연산은 각 검증인의 단일 코어에서 실행됩니다.
시퀀스 생성은 순차적이고 단일 스레드로 이뤄지지만 출력은 병렬로 검증할 수 있어 멀티코어 시스템에서 효율적으로 검증할 수 있습니다. 해싱 속도에는 상한이 있지만 하드웨어 개선을 통해 성능을 더 높일 수 있습니다.
Solana 네트워크에 검증인 A, B, C, D가 있는 예를 살펴보겠습니다. 이 예에서 리더 일정은 블록 생성 순서를 A - B - C - D로 지정할 수 있습니다. 검증인 A가 차례에 따라 블록 생성을 시작합니다. 이를 위해 검증인 A는 SHA-256 해시 함수를 반복 실행해 “틱”의 시간 척도를 형성하는 PoH 메커니즘을 사용합니다. 이 해싱 과정은 소요 시간에 대한 고유하고 검증 가능한 기록을 생성해 검증인 A의 블록이 정확한 시간 경과를 반영하도록 합니다. 검증인 A가 블록을 완료하면 검증인 B가 다음 블록을 생성하고, 이어서 검증인 C가 생성합니다.
검증인 C가 순서를 방해하기 위해 자기 차례가 아닌데 블록을 내보내 검증인 B를 건너뛰고 검증인 A의 바로 뒤를 잇으려 한다고 가정해 보겠습니다. 검증인 C가 검증인 B의 자리를 설득력 있게 대신하려면 검증인 B가 생성했을 PoH 해시 시퀀스를 복제해야 합니다. 즉, 검증인 B가 블록을 생성하는 데 걸렸을 시간을 나타내는 해시 시퀀스를 생성해야 합니다. 단일 코어의 해싱 성능에는 물리적 한계가 있습니다. 컴퓨터가 주어진 시간 동안 생성할 수 있는 해시 수에 상한이 있으므로 일정 시간이 흘렀음을 알 수 있습니다.
검증인 C는 이전의 정상 블록인 검증인 A의 블록 끝에서 시작해 트랜잭션이 없는 빈 블록 체인을 생성함으로써 리더 일정에서 검증인 B를 검열하려 할 수 있습니다. B를 성공적으로 검열하려면 C는 두 가지 조건을 충족해야 합니다. 첫째, C는 빈 PoH 체인을 빠르게 계산할 연산 능력이 필요합니다. 둘째, C는 자신의 지정 슬롯 동안 블록이 수락되도록 충분한 수의 스테이킹된 노드에 블록을 빠르게 전파해 B를 효과적으로 검열해야 합니다. 검증인의 스테이킹 지분 가중치에 따라 정보 흐름의 우선순위를 정하는 Turbine 덕분에 스테이킹 지분 가중치가 높은 검증인일수록 더 빠르게 전파할 수 있습니다.
이 공격 시나리오는 가능하지만 검열에 성공할 수 있는 시간은 제한적입니다. 공격 노드는 상당한 연산 자원(SHA-256 해싱용)과 많은 스테이킹 지분을 보유해야 합니다. 생성할 수 있는 블록 수가 스테이킹 지분에 비례하기 때문입니다.
C는 노드 A보다 더 빠르게 네트워크에 도달해야 할 뿐 아니라 해시도 빠르게 생성해야 합니다. 이 공격은 주로 슬롯 n의 지정 리더인 검증인이 n 이전의 리더 슬롯을 맡은 검증인을 검열하려는 시나리오를 대상으로 합니다. 이 검증인이 달성할 수 있는 검열 범위는 스테이킹 지분에 따라 달라집니다. 리더 슬롯을 생성할 수 있는 능력이 보유한 스테이킹 지분에 직접 연결되기 때문입니다.
PoH 메커니즘은 블록이 일정한 속도로 생성되도록 보장하기도 합니다. 각 검증인이 PoH 시퀀스를 독립적으로 검증할 수 있으므로 외부 시간 동기화가 필요하지 않습니다. 예를 들어 Ethereum은 합의를 위해 각 블록에서 네트워크 시간 프로토콜(NTP)을 사용합니다. Solana에서는 외부 프로토콜 없이 각 검증인이 각 블록이 올바른 시간 슬롯에 생성되었는지 내부적으로 독립 검증합니다.
Tower BFT(Solana의 합의 메커니즘)
Solana의 합의 메커니즘인 Tower BFT는 샤드(블록 일부)가 다른 검증인에게 전파된 후 작동합니다.
앞서 언급했듯이 Solana는 Proof-of-History와 함께 Tower BFT를 실행합니다. Tower BFT는 Proof-of-History의 동기화된 시계 연산을 활용하도록 설계된 pBFT 계열의 합의 알고리즘입니다. 이를 통해 네트워크 전체에 공통 시계를 설정하고 느리거나 응답하지 않는 리더에게 할당된 슬롯을 효율적으로 건너뛸 수 있습니다. 이 과정은 각 슬롯마다 네트워크가 동기식 합의 라운드를 거칠 필요를 없애고 지속적인 블록 생성을 지원합니다. 따라서 검증인은 다음 블록을 구축하기 전에 이전 블록이 도착할 때까지 기다릴 필요가 없습니다.
또 다른 오해는 Solana의 합의 메커니즘이 현재 프로그래밍 방식의 슬래싱을 구현하고 있다는 것입니다. 슬래싱은 로드맵에 포함되어 있지만, 현재 네트워크는 안전성 위반 후 중단되며 필요에 따라 사회적 합의에 의존해 슬래싱합니다.
Solana의 합의 메커니즘은 노드마다 서로 다른 수준의 영향력을 부여합니다. 네트워크의 투표는 동등하지 않으며 각 노드의 스테이킹 지분에 따라 가중됩니다. 이는 스테이킹 지분 가중 QoS와 Turbine과 같은 원리로 작동합니다. 다른 조건이 같다면 스테이킹 지분이 큰 노드가 작은 노드보다 정규 합의를 결정하는 데 더 큰 영향력을 갖습니다.
예를 들어 총 100단위의 스테이킹 지분을 보유한 네 개의 노드가 있는 네트워크에서 분포와 영향력은 다음과 같을 수 있습니다.
- 노드 A는 10단위의 스테이킹 지분을 보유합니다.
- 노드 B는 20단위의 스테이킹 지분을 보유합니다.
- 노드 C는 30단위의 스테이킹 지분을 보유합니다.
- 노드 D는 40단위의 스테이킹 지분을 보유합니다.
이 구성에서는 부정직한 노드 그룹마다 행사할 수 있는 능력이 다릅니다. 노드 D는 전체 노드 수의 25%에 불과하지만 큰 스테이킹 지분 때문에 단독으로 네트워크를 중단시킬 수 있습니다. 마찬가지로 노드 C와 D가 결합하면 노드 수의 50%에 불과해도 결과에 영향을 줄 만큼 충분한 스테이킹 지분을 보유하므로 잘못된 트랜잭션을 승인할 수 있습니다.
네트워크를 중단시키는 3분의 1 임계값은 부정직하거나 손상되거나 차단된 노드를 통해 도달할 수 있습니다. 반면 잘못된 트랜잭션을 검증하는 3분의 2 임계값에는 적극적인 공모가 필요하며, 단순히 정직한 노드를 차단하는 것만으로는 부족합니다. 따라서 후자를 달성하기가 훨씬 더 어렵습니다. 정직한 노드를 차단하는 대신 노드를 타락시키거나 장악해 부정한 계획에 적극적으로 참여시켜야 하기 때문입니다.
슬롯 내 맥락
Solana에서 슬롯 리더는 총 약 1.6초간 지속되는 연속 네 개의 슬롯을 할당받습니다(블록 4개 x 블록당 400ms). 리더는 각 에포크가 시작될 때 선택됩니다(432,000슬롯 또는 ~2~3일). 리더 일정은 검증인의 스테이킹 지분 가중치에 비례해 무작위로 정해집니다.
리더는 할당된 각 슬롯에 새 블록을 구축하고 제안하는 역할을 맡습니다(Ethereum 생태계와 달리 제안자-빌더 분리가 없습니다). 다른 검증인은 Solana 네트워크 헤드에 대한 자신의 로컬 관점에 포크 선택 규칙을 적용하고, 투표 트랜잭션을 통해 해당 블록의 유효성을 증명합니다.
블록이 유효하려면 리더가 주어진 PoH 틱 범위 안에서 블록을 게시해야 합니다. 이 범위 안에서 게시되지 않은 블록은 건너뛴 것으로 간주됩니다.
참여자가 네 명(A, B, C, D)이고 D가 순서를 방해하려는 다음 리더 일정의 예를 살펴보겠습니다. D가 C의 차례에 개입하려면 C의 블록을 효과적으로 건너뛰는 PoH 틱 시퀀스를 생성해야 합니다. 그러면 체인은 다음과 같은 모습이 됩니다.
A - B - [C 누락] - D.
C의 블록이 누락된 상황에서 정직한 D는 자신의 슬롯을 시작하기 전에 C 슬롯의 전체 기간을 포함하는 PoH 시퀀스를 생성해야 합니다. 그러면 C의 슬롯에 할당된 시간이 지난 후 B의 블록을 잇게 되므로 D의 블록은 유효해 보입니다.
D가 C의 슬롯에 대한 PoH 시퀀스를 생성하는 동안 C는 일반적으로 적절한 PoH 시퀀스로 B의 블록에 연결된 자신의 블록을 스트리밍합니다. 이에 따라 두 가지 결과가 발생할 수 있습니다.
- D의 PoH 연산이 C보다 빠르지 않은 경우: C가 블록을 완료할 무렵 D가 자신의 블록을 브로드캐스트하기 시작합니다. 이미 C의 블록을 본 네트워크는 D의 블록을 거부합니다.
- D가 C보다 PoH를 빠르게 연산하는 경우: D는 C가 자신의 블록을 완료하기 전에 블록 브로드캐스트를 시작합니다. 그렇더라도 순서에 큰 영향을 주려면 D가 C보다 훨씬 빨라야 합니다. 검증인이 SHA-256 연산에 사용하는 CPU의 속도가 빠르고 성능 상한도 상대적으로 비슷하다는 점을 고려하면 가능성은 낮습니다.
두 상황 모두 D가 C를 성공적으로 대체할 가능성은 매우 낮습니다. 또한 D가 C를 대체하려다 실패하면 자신의 슬롯에서 블록을 내보낼 기회를 잃습니다. B 직후에 블록을 내보내고 C 이후에 다시 시도하면 D의 슬롯에 두 개의 블록을 생성하는 위반이 되어 슬래싱 대상이 됩니다. 시도에 실패할 때마다 D는 자신의 블록 생성 기회를 잃으므로 실제로 선택할 가능성이 낮은 전략입니다.
네트워크의 관점에서는 D의 의도를 판단할 수 없습니다. D가 C를 검열할 의도 없이 단순히 C의 블록을 보지 못한 것인지, 아니면 B를 검열하려는 의도가 있었는지 구분하기는 어렵거나 불가능합니다. 따라서 쉽게 탐지할 수 없으며 네트워크에서 처벌할 수도 없습니다.
투표 트랜잭션
Solana의 합의 메커니즘은 합의 달성을 위해 투표 트랜잭션에 의존합니다. 투표 트랜잭션은 블록 안에 포함되지만 일반 트랜잭션에 묻히지 않도록 우선 처리됩니다. 현재 특정 블록에 포함된 트랜잭션의 대다수는 투표 트랜잭션입니다.
하지만 항상 그렇지는 않을 수 있습니다. 특정 블록에서 투표 트랜잭션이 차지하는 비율은 활동량과 합의에 참여하는 검증인 수의 비율을 나타내기 때문입니다. 향후 투표 트랜잭션은 블록에서 소수가 될 수 있습니다.
투표 트랜잭션은 합의에 반드시 필요합니다. TPS 지표를 인위적으로 부풀리기 위한 불필요한 트랜잭션이 아닙니다. 투표가 gossip(비공식 P2P 통신)을 통해서만 전파되면 검증인마다 Tower의 투표 상태를 다르게 인식할 수 있습니다. 이러한 차이로 인해 검증인마다 어떤 포크가 올바를 가능성이 높은지 다르게 판단할 수 있습니다. 검증인이 불완전하거나 일관되지 않은 정보에 기반해 탐욕적인 선택을 하면 포크가 분기될 수 있습니다. 지속적인 블록 생성에는 계속되는 투표가 필요하며, 이전 블록이 아직 확정되는 중일 때는 특히 그렇습니다. 이를 위해서는 Tower 상태에 대한 신뢰할 수 있고 일관된 관점이 필요합니다.
사용자가 시작하는 일반 트랜잭션과 마찬가지로 투표 트랜잭션도 기본 수수료(0.000005 SOL)를 지불해야 합니다. 수수료는 지속적인 서명을 위해 핫 월렛에 있어야 하는 검증인 ID가 지불하며, 투표 계정은 계정 조회 및 위임에 사용됩니다.
검증인이 서명한 각 투표에는 검증인의 공개 키와 투표 대상 블록의 해시가 포함됩니다.
검증인은 동일한 슬롯에 대해 여러 블록을 수신하면 “최선”의 블록을 결정할 때까지 가능한 모든 포크를 추적합니다. 검증인은 관련 상태 전이 함수를 로컬에서 실행하고(비동기 실행 도입 후 변경 예정), 리플레이 후 새 블록에 투표합니다. 검증인은 온체인 투표 트랜잭션을 통해 특정 포크에 대한 투표를 표시합니다.
각 투표 트랜잭션에서 검증인은 잠금 기간이 있는 투표를 게시합니다. 이 잠금은 커밋 메커니즘으로 작동해 검증인을 선택한 포크에 묶고 결정에 기회비용을 부과합니다. 현재 잠금은 런타임이 아니라 사회적 합의를 통해 강제됩니다. 투표 잠금을 지속적으로 위반하면 수동으로 슬래싱될 가능성이 매우 높습니다. 투표 크레딧을 받지 못하는 것만으로는 충분한 억제력이 되지 않으므로 잠금 기간 위반에 대한 프로그래밍 방식의 슬래싱이 가까운 미래에 추가될 가능성이 높습니다.
검증인은 이전 투표와 루트 지정/최종 확정 블록 사이에 있는 모든 조상 블록에 대해서도 블록 해시에 서명합니다. 이는 중복 블록을 감지하는 데 필요합니다. 리더가 각 노드에 서로 다른 블록을 보내면 모든 노드는 동일한 슬롯에 대해 서로 다른 선행 블록에 투표하게 됩니다. 그러나 65,000개 슬롯으로 구성된 에포크에서는 극단적인 경우 각 투표의 크기가 최대 2MB에 이를 수 있습니다. 65,000개 슬롯마다 32바이트 해시가 필요할 수 있기 때문입니다. 자세한 내용은 향후 게시물에서 살펴보겠습니다.
검증인은 “Vote Tower”를 관리합니다. 이는 각 투표가 포크를 강화하고 Tower에서 그 위에 있는 포크의 조상이 되는 순차적인 투표 스택입니다. 이 Tower에 새 투표가 추가되면 스택의 모든 이전 투표에 대한 잠금 기간이 두 배로 늘어나며, 이전 결정의 커밋과 잠금 기간이 점진적으로 증가합니다. 투표 과정 자체에는 여러 검사가 적용됩니다. 검증인은 이전 투표의 잠금 기간을 준수해야 하고, 네트워크의 상당 부분(일반적으로 3분의 2)도 같은 포크에 커밋했는지 확인해야 하며, 새 포크로 전환하려면 대체 포크에서 상당한 다수(38% 초과)의 투표가 필요합니다.
슬롯 n의 블록에 대해 리더 외 검증인의 투표는 이르면 n+1부터 온체인에 나타납니다. 투표 소위원회는 없으며 모든 검증인이 모든 블록에 투표할 수 있습니다. 이러한 투표는 먼저 Turbine 트리에서 가까운(한 홉 거리의) 다른 검증인의 블록에 나타납니다. 검증인은 “슬롯 해시”가 아직 알려진 모든 슬롯에 투표할 수 있고 슬롯 해시는 512개 슬롯 동안 유지되므로 슬롯 n에 대한 투표는 최대 슬롯 n+512까지 나타날 수 있습니다(Shinobi에게 감사드립니다). 슬롯 n에 대해 특정 블록으로 미리 정해진 상한은 없습니다. 하지만 최소 32개의 연속 블록이 위에 구축된 루트 지정 슬롯은 더 이상 투표를 받지 않고 최종 확정됩니다.
투표 방식에는 런타임이 완전히 강제하지 않는 몇 가지 특이점이 있습니다. 예를 들어 현재 검증인은 체인의 팁을 무시하고 “루트 지정” 슬롯에만 투표할 유인이 있으며, 이는 합의에서 처벌되지 않습니다. 따라서 검증인은 실제 합의 작업을 위해 체인의 팁에 기여하지 않으면서 정규 체인이 될 가능성이 매우 높은 포크에서 지속적으로 투표 크레딧을 얻을 수 있습니다. 이러한 현상은 현재도 발생하고 있으며, 평균 “투표 지연 시간”이 68슬롯을 넘는 검증인도 있습니다. Timely Vote Credits라는 제안 기능은 이러한 인센티브 불일치를 완화하는 것을 목표로 합니다.
Solana의 포크 선택 규칙
Ethereum의 LMD Ghost 및 Casper FFG와 마찬가지로 Solana에는 두 가지 확정 규칙이 있습니다. 하나는 단기 포크 선택을 위한 것이고 다른 하나는 최종성을 위한 완전한 PoS 합의용입니다. 이를 통해 사용자와 클라이언트는 서로 다른 확정 규칙 아래에서 맞춤형 UX를 선택할 수 있습니다. 이는 “confirmed”와 “finalized”라는 두 가지 커밋 수준으로 나타납니다.
“Confirmed” 블록(낙관적 확정이라고도 함)은 검증인의 최소 3분의 2가 특정 블록에 투표 트랜잭션으로 투표해야 합니다. 최종성 위반이 가능하려면 현재 스테이킹 지분의 ~4.6%가 슬래싱되어야 합니다. “Finalized” 블록은 이후 최소 32개 슬롯에 대한 투표 또는 절대다수(>2/3)의 투표가 필요합니다. 악의적 공격에는 스테이킹 지분의 3분의 1 이상이 슬래싱되어야 합니다. 완전한 최종성을 확보하려면 32개 블록 전의 루트 지정 블록을 기다려야 하므로 “confirmed” 블록보다 훨씬 오래 걸립니다.
포크 선택 규칙을 통해 네트워크는 체인의 헤드에 합의할 수 있습니다. Solana Labs 구현은 주로 heaviest_subtree_fork_choice.rs라는 적절한 이름의 약 4,600줄짜리 Rust 파일에서 포크 선택을 처리합니다. 이 파일은 검증인이 어떤 포크가 정규 체인이 될 가능성이 가장 높은지 판단하는 데 필요한 로직을 제공합니다. 더 자세한 코드 분석은 향후 게시물에서 다룰 예정이며, 포크 선택의 전반적인 작동 방식은 다음과 같습니다.
add_votes()을 사용해 투표를 추가합니다.
새 투표를 순회하면서 필요한 경우 이전 슬롯에서 투표 계정의 스테이킹 지분을 빼고 새로 투표한 슬롯에 스테이킹 지분을 추가합니다.
- 포크 업데이트 작업 배치를 생성하기 위해
generate_update_operations()을 호출합니다.
이 작업은 다음을 수행합니다.
- 이전 포크에서 스테이킹 지분을 뺍니다
- 새 포크에 스테이킹 지분을 추가합니다
- 각 포크를 따라 루트까지 스테이킹 지분을 집계합니다
process_update_operations():
- 필요한 경우
mark_fork_valid()/invalid()을 호출합니다 - 각 포크를 따라
aggregate_slot()을 호출해 포크 가중치를 업데이트합니다 add_slot_stake()/subtract_slot_stake()을 호출해 스테이킹 지분을 업데이트합니다
aggregate_slot():
- 모든 하위 슬롯의 스테이킹 지분을 합산합니다
- 스테이킹 지분 가중치가 가장 큰 하위 포크를 찾습니다
- 높이를 기준으로 가장 깊은 하위 포크를 찾습니다
- 이 값을 상위로 전파해 해당 슬롯에서 가장 무겁고 깊은 포크를 찾습니다
select_forks():
- 블록 생성을 위한 전체 최중량 포크를 반환합니다
- 마지막 투표에서 이어지는 최중량 포크를 반환합니다
투표에 따라 스테이킹 지분을 더하거나 빼고, 집계를 통해 각 포크의 가중치를 아래에서 위로 다시 계산하며, 가중치가 가장 큰 하위 트리를 가진 루트를 구축하고 투표할 최적의 포크로 선택합니다.
포함 가능성
트랜잭션이 각 확정 규칙에 필요한 요건을 충족한 후 포함될 가능성은 트랜잭션의 수명 주기에 따라 달라집니다.
리더가 오프라인인 경우처럼 슬롯을 “건너뛸” 수 있지만, 해당 트랜잭션은 향후 블록에 포함되거나 전혀 포함되지 않을 수 있습니다.
여기서 슬롯 수는 대략적인 추정치이지만 투표가 언제 누적되는지 독자가 이해할 수 있도록 제시했습니다. 또한 이는 블록마다 다릅니다. 블록이 “confirmed” 또는 “finalized” 확정 수준에 도달하는 데 걸리는 길이는 달라질 수 있습니다. 되돌려질 위험은 트랜잭션의 수명 주기 전체에 걸쳐 단조롭게 감소합니다. 블록이 최종 확정(루트 지정)된 후에도 이론적으로는 사회적 합의를 통해 포크되어 “정규” 체인에서 제거될 수 있습니다.
향후 연구 분야와 결론
이 글에서는 Solana의 합의 메커니즘인 Tower BFT와 기타 관련 메커니즘의 내부 작동 방식을 살펴봤습니다. 트랜잭션 순서를 정하는 정규 포크를 생성하기 위해 Proof-of-History, 투표 트랜잭션, 포크 선택이 Solana에서 어떤 역할을 하는지 알아봤습니다.
이러한 메커니즘과 관련해 추가로 연구하고 형식화할 수 있는 방향은 많습니다.
- Ethereum 연구자들은 블록 생성자가 슬롯이 끝날 때까지 기다렸다가 블록을 제출하는 Timing Games의 가치를 정량화했습니다. 이러한 게임은 Solana에서 정량적으로 어떤 모습이며 현재 실제로 일어나고 있습니까?
- 비동기 실행은 2024년의 주요 프로토콜 변경 사항으로 로드맵에 포함되어 있습니다. 상태 전이를 로컬에서 계산하지 않고 기존 포크에 투표만 하는 노드에는 어떤 잠재적 공격 벡터와 보안 고려 사항이 있습니까?
- 현재 상당수의 검증인(<20%)이 Solana Labs 또는 Jito-Solana 클라이언트를 수정해 실행합니다. 이들은 런타임이나 확정 규칙이 관리하지 않는 어떤 임계값을 변경하고 있습니까?
- 프로그래밍 방식의 슬래싱 구현. 현재 사회적 합의 외에는 슬래싱 없이 수익성이 매우 높은 거래 전략을 실행하지 않도록 막는 경제적 유인이 거의 없습니다.
- 완전히 다른 두 클라이언트를 실행할 때 Solana의 합의 메커니즘 성능은 어떤 모습입니까? 두 클라이언트가 동일한 확정 규칙으로 정의되려는 경우에도 마찬가지입니다.
- 투표 소위원회를 통해 기대할 수 있는 성능 향상과 상태 축소 효과는 무엇입니까?
- 최종 확정된 슬롯이 아니라 낙관적으로 확정된 슬롯에서 재시작할 때 발생할 수 있는 공격 벡터는 무엇입니까? 거래소와 같은 서드파티 오프체인 솔루션은 낙관적 확정 또는 완전한 최종성의 사용을 어떻게 고려해야 합니까?
- 슬래싱된 자금을 안전성 위반에 포함된 트랜잭션의 보험으로 사용해야 합니까? SOL 표시 보험 풀의 메커니즘과 인센티브는 무엇입니까?
이 글에서는 Solana가 합의 메커니즘에서 구현하는 몇 가지 메커니즘과 임계값, 그리고 지정된 슬롯에서 리더가 일반적으로 블록을 생성하는 방식과의 관계를 살펴봤습니다. 최근 Solana의 활동 증가는 이러한 메커니즘의 활성성과 안전성을 실제 환경에서 시험하고 있으며, 악의적 공격의 유인도 커지고 있습니다.
토론과 의견을 제공해 주신 anoushk(Tinydancer), dubbel06(Overclock), Prithvi(Helius), Mert(Helius), Jarry(Ellipsis Labs)에게 감사드립니다.
관련 아티클
Helius 구독하기
최신 Solana 개발 소식을 확인하고 새 게시물 알림을 받아보세요


