Solana · Chapter 4

Solana의 Commitment Level은 어떻게 결정되는가?

작성자: Choi.eth

18 min read

솔라나 네트워크에 참여하는 노드들은 특정 블록이 Confirmed 또는 Finalized 상태에 도달했다는 사실을 어떻게 알 수 있을까요?

솔라나는 단순히 특정 Validator에게 확정 여부를 문의하는 방식이 아닙니다. 네트워크에 참여하는 노드들이 P2P 통신을 통해 블록과 투표 정보를 공유하고, 각자 보유한 정보를 바탕으로 블록의 확정 수준을 판단합니다.

작성 기준: 2026년 10월 15일.

본문은 현재 메인넷에서 사용 중인 Tower BFT 방식에 대한 학습 자료입니다. 솔라나는 2026년 10월 21일 Alpenglow 메인넷 전환을 예정하고 있으며, 전환 후에는 투표 전파와 Finality 메커니즘이 크게 달라집니다.

1. Solana의 Commitment Level

솔라나는 블록의 확정 수준을 세 가지로 구분합니다.

Commitment Level 의미 판단 조건
processed 블록이 노드에서 처리된 상태 블록 수신 및 실행
confirmed 네트워크의 슈퍼다수 지분이 투표한 상태 활성 Stake의 2/3 초과가 직접 투표
finalized 네트워크에서 최종 확정된 상태 Tower BFT의 최대 Lockout과 슈퍼다수 Root 확정

이더리움에 대응하면 latest ≈ processed, safe ≈ confirmed, finalized ≈ finalized로 이해할 수 있습니다. 다만 이더리움의 Casper FFG와 솔라나의 Tower BFT는 서로 다른 합의 규칙을 사용하므로 정확히 동일한 상태는 아닙니다.

여기서 중요한 점은 각 단계의 판단 기준입니다. processed는 노드가 블록을 처리했는가, confirmed는 충분한 지분이 블록에 투표했는가, finalized는 충분한 지분이 해당 블록을 Root로 확정했는가에 초점을 맞춥니다.

2. Solana의 노드와 P2P 네트워크 구조

솔라나에서는 일반적으로 Agave와 같은 하나의 Validator 클라이언트가 트랜잭션 실행, 블록 검증, 합의 관련 기능을 함께 수행합니다. 이는 Execution Layer와 Consensus Layer를 별도의 클라이언트로 분리하는 이더리움과 다른 점입니다.

솔라나 노드는 Gossip, Turbine, TPU 등의 통신 경로를 사용하며, 이 중 Commitment Level을 이해하기 위해 중요한 것은 Gossip과 Turbine입니다.

구성 요소 목적 Commitment와의 관계
Gossip / CRDS Peer 정보 및 투표 관련 정보 공유 다른 Validator의 투표를 관찰
TPU 트랜잭션을 Leader에게 전달 Vote Transaction 전달
Turbine 블록을 Shred 단위로 전파 블록과 포함된 투표 트랜잭션 수신
Replay Stage 블록 재실행 및 상태 검증 Vote Account 상태 재현
Commitment 집계 투표·Root·Stake 정보 집계 Confirmed / Finalized 판단

이 구조에서 Voting Validator와 Non-voting RPC 노드의 차이도 알아둘 필요가 있습니다.

Voting Validator는 블록을 검증한 뒤 합의 투표에 참여합니다. 반면 --no-voting 옵션을 사용하는 RPC 노드는 직접 투표하지 않지만, 다른 Validator들의 블록과 투표 정보는 계속 수신합니다. 따라서 RPC 노드도 네트워크의 합의 상태를 독립적으로 추적할 수 있습니다.

3. Validator의 Identity와 Vote Account

솔라나 Validator가 합의에 참여하려면 먼저 노드 식별자와 투표 상태를 구분해야 합니다.

Identity Key

Identity Key는 Validator 노드를 식별하는 키페어입니다. Gossip 네트워크의 CRDS에는 노드의 Identity Public Key와 네트워크 주소 등의 정보가 공유됩니다.

이더리움의 Node ID와 유사하게 이해할 수 있으며, 솔라나에서는 공개키 자체가 노드의 식별자로 사용됩니다.

Vote Account

Vote Account는 Validator의 합의 투표 상태를 저장하는 온체인 Data Account입니다. owner에는 Vote Program의 ID가 설정되며, data에는 Vote State가 저장됩니다.

데이터 설명
node_pubkey Validator의 Identity Public Key
votes 최근 투표 기록 및 Lockout 관련 정보
root_slot Validator가 확정한 Root Slot
authorized_voter 투표 서명 권한
authorized_withdrawer 계정 출금 권한
commission 보상 수수료율
epoch_credits 투표 보상 관련 기록

위 필드는 개념을 단순화한 것으로, 실제 Vote State의 직렬화 형식과 필드는 버전에 따라 차이가 있습니다. 중요한 것은 Validator Identity Account와 Vote Account가 서로 다른 계정이라는 점입니다.

일반적인 Non-voting RPC 노드도 Identity Key가 필요하지만, 투표하지 않으므로 자신의 Vote Account를 필수적으로 운영할 필요는 없습니다.

  • Vote Account의 owner는 Validator 개인이 아니라 Vote Program입니다. Vote Program은 유효한 Vote Transaction을 실행하여 Vote Account의 데이터를 갱신합니다.

4. 블록이 생성되고 Processed가 되는 과정

이제 네트워크에 네 대의 Voting Validator와 한 대의 RPC 노드가 있다고 가정하겠습니다. Slot 100에서 Validator A가 Leader로 선정되어 블록 X를 생성했다고 가정하겠습니다.

솔라나에서는 특정 Slot의 Leader가 블록을 생성합니다. Slot은 블록을 생성할 수 있는 시간 구간이고, 실제 Block은 그 시간 구간에서 만들어진 결과물입니다. 모든 Slot에서 블록이 반드시 생성되지는 않습니다. Leader A는 블록 X를 생성한 뒤, 이를 Shred라는 작은 데이터 조각으로 나누어 Turbine을 통해 다른 Validator에게 전파합니다.

다른 Validator와 RPC 노드는 Shred를 수신해 블록을 재구성하고, 블록에 포함된 트랜잭션을 재실행합니다.

이 단계에서 RPC 노드는 블록 X를 처리했지만, 아직 다른 Validator들의 충분한 투표를 확인하지 못했습니다. 따라서 해당 블록이 향후 다른 Fork로 대체될 가능성이 남아 있습니다.

5. Validator의 투표는 어떻게 전파되는가?

Validator는 블록을 검증하고 Fork Choice에 따라 투표할 블록을 선택합니다. 이후 자신의 투표를 표현하는 Vote Transaction을 생성하고 서명합니다.

Tower BFT 기반 솔라나에서는 Vote Transaction이 두 가지 경로를 통해 다른 노드에 알려질 수 있습니다.

Gossip을 통한 투표 정보 전파

Validator는 서명된 투표 정보를 Gossip 네트워크를 통해 공유할 수 있습니다. 다른 Validator와 RPC 노드는 이 정보를 수신하여, 어떤 Validator가 어느 Slot에 투표했는지 빠르게 관찰할 수 있습니다.

Gossip의 장점은 투표가 아직 블록에 포함되지 않았더라도 다른 노드가 이를 확인할 수 있다는 점입니다.

Vote Transaction의 온체인 기록

Validator는 Vote Transaction을 Leader에게 전달할 수도 있습니다.

Leader는 해당 트랜잭션을 블록에 포함하고, 블록 실행 과정에서 Vote Program이 실행됩니다. Vote Program은 유효한 투표인지 검증한 후, Validator의 Vote Account에 저장된 투표 상태를 갱신합니다.

이때 Gossip으로 투표 정보를 관찰하는 것과 Vote Transaction이 블록에 포함되어 Vote Account에 기록되는 것은 별개의 과정입니다.

6. Confirmed는 어떻게 판단하는가?

confirmed는 특정 블록에 전체 활성 스테이킹 지분의 2/3를 초과하는 직접 투표가 모인 상태입니다. 여기서 투표 가중치는 Validator의 개수가 아니라 각 Validator에게 위임된 활성 Stake를 기준으로 계산됩니다.

Validator 활성 Stake 블록 X 투표
A 40% O
B 30% O
C 20% X
D 10% X

예를 들어 Slot 100의 블록 X에 대한 투표 현황이 다음과 같다고 가정하겠습니다. Validator A와 B가 투표했다면 총 70%의 활성 Stake가 블록 X를 직접 지지한 것입니다.

40+30100=70%\frac{40+30}{100}=70\%

이는 2/3를 초과하므로 블록 X는 confirmed 조건을 충족합니다.

RPC 노드는 이를 어떻게 계산할까요?

우선 Gossip과 Replay(vote transaction)을 통해 유효한 투표를 관찰합니다. 그런 다음 로컬 Bank에 보유한 해당 Epoch의 Stake 정보를 이용해 투표 가중치를 계산합니다. 즉, 투표를 수신할 때마다 다른 Validator에게 현재 Stake를 문의하는 구조가 아닙니다.

이때 Confirmed 판단에는 Vote Stack의 최대 깊이 32나 Root 확정이 필요하지 않습니다. 충분한 Stake의 직접 투표가 관찰되면 Confirmed 조건을 충족할 수 있습니다.

7. Finalized를 이해하기 위한 Tower BFT와 Lockout

confirmed는 충분한 Validator들이 특정 블록에 투표했다는 의미입니다. 하지만 네트워크의 최종 확정 상태인 finalized에 도달하려면 추가적인 조건이 필요합니다. 여기서 등장하는 개념이 Tower BFT의 Lockout입니다.

Lockout이란?

Lockout은 Validator가 특정 블록에 투표한 후, 해당 블록과 충돌하는 Fork로 자유롭게 이동하지 못하도록 제한하는 규칙입니다.

Validator가 기존에 선택한 Fork의 후속 블록에 계속 투표하면 이전 투표의 Lockout이 증가합니다.

Tower BFT에서는 새로운 투표의 초기 Lockout을 2 slots로 정의하며, 후속 투표가 누적될 때 이전 투표의 Lockout이 2배씩 증가하도록 설계되어 있습니다.

예를 들어 다음과 같습니다.

투표 진행 Slot 100에 했던 투표의 Lockout
Slot 100에 첫 투표 2 slots
Slot 101에 후속 투표 4 slots
Slot 102에 후속 투표 8 slots
Slot 103에 후속 투표 16 slots
Slot 104에 후속 투표 32 slots

여기서 중요한 것은 Slot 100에서 했던 투표의 Lockout 값이 증가한다는 점입니다.

Lockout이 8 slots라는 것은 기존 투표에 적용되는 잠금 기간의 길이가 8 slots라는 의미입니다. Slot 108까지 새로운 투표를 하지 않으면 Slot 100의 다른 fork에 투표를 할 수 있습니다. 하지만, 이러한 규칙은 Validator가 기존에 선택한 Fork를 반복해서 지지할수록, 다른 Fork로 전환하기 어렵도록 설계한 것입니다.

Vote Stack이란?

Validator는 자신의 투표 기록을 Vote Stack(Vote Tower)이라는 로컬 자료구조에서 관리합니다.

Vote Stack에는 어떤 Slot에 투표했는지, 각 투표의 Confirmation Count와 Lockout이 무엇인지 등의 정보가 기록됩니다. Tower BFT에서는 최대 32개의 투표 기록을 유지합니다.

검증자가 같은 Fork의 후속 블록에 계속 투표하면서 가장 오래된 투표가 최대 깊이(32 votes)에 도달하면, 해당 투표는 Root로 확정됩니다.

Root란?

Root는 Validator가 Tower BFT 합의 규칙에 따라 확정한 블록(Slot)입니다.

예를 들어 다음과 같은 상태가 있을 수 있습니다.

Validator A

Root                              Last Vote
 ↓                                    ↓
Slot 100 ── 101 ── 102 ── ... ── 131 ── 132
  • Last Vote = 132: 가장 최근에 투표한 Slot
  • Root = 100: 충분한 후속 투표가 누적되어 확정된 Slot

따라서 Validator의 Root는 해당 Validator가 더 이상 되돌리지 않겠다고 확정한 기준점입니다. Validator가 Root 100을 확정했다면, Slot 100의 블록뿐 아니라 그 조상 블록들도 확정한 것입니다.

여기서 Root는 Validator 개인의 합의 상태입니다. 네트워크 전체에서 최종 확정되려면 여러 Validator의 Root가 충분한 Stake를 대표해야 합니다.

8. Validator의 Root는 어떻게 Vote Account에 기록되는가?

앞서 살펴본 Vote Stack은 Validator가 로컬에서 관리하는 자료구조입니다. 하지만 다른 RPC 노드들은 Validator의 로컬 Vote Stack 파일을 직접 읽을 수 없습니다.

그렇다면 RPC 노드는 Validator A가 어느 Slot을 Root로 확정했는지 어떻게 알 수 있을까요? 여기서 Vote Transaction과 Vote Account가 다시 등장합니다.

로컬 Tower와 온체인 Vote State

두 개념은 서로 관련되어 있지만 동일한 저장소는 아닙니다.

구분 로컬 Vote Stack 온체인 Vote Account
저장 위치 Validator 로컬 솔라나 Account State
목적 합의 투표 및 Lockout 관리 투표 상태의 온체인 기록
주요 정보 투표 기록, Lockout, Root votes, root_slot 등
다른 노드의 접근 직접 접근하지 않음 블록 Replay로 동일 상태 재현

예를 들어 Validator A의 현재 상태가 다음과 같다고 가정하겠습니다.

Validator A

Local Tower:
    Last Vote: 150
    Root: 118

이후 Validator A가 Slot 151에 투표하면서 Root가 119로 전진했다고 가정하겠습니다.

Validator A는 이 투표 내용을 바탕으로 Vote Transaction을 생성하여 네트워크에 제출합니다. 이 투표가 블록에 포함되고 Vote Program에 의해 정상적으로 처리되면 Vote Account의 상태가 변경됩니다.

# 여기서 votes 배열은 실제 직렬화 구조를 단순화한 표현입니다. 실제 투표 기록에는 Confirmation Count 등이 포함됩니다.

# 변경 전 Vote State
{
    votes: [...],
    root_slot: 118
}

          ↓

Vote Transaction 실행

          ↓

# 변경 후 Vote State
{
    votes: [...],
    root_slot: 119
}

중요한 점은 Validator가 Vote Account의 data를 직접 수정하는 것이 아니라, Vote Transaction을 제출하고 Vote Program이 이를 실행하면서 상태를 변경한다는 것입니다.

다른 RPC 노드들도 Vote Transaction이 포함된 블록을 수신하고 Replay하므로 동일한 Vote State를 재현할 수 있습니다.

즉, 다른 노드는 Validator A의 로컬 Tower를 복사하지 않아도 온체인에 반영된 투표와 Root 정보를 확인할 수 있습니다.

9. Finalized는 어떻게 판단하는가?

이제 마지막 단계입니다.

RPC 노드는 블록을 재실행하면서 각 Validator의 Vote Account 상태를 갱신하고, 로컬의 Stake 정보와 함께 Root 확정 현황을 집계합니다.

특정 블록이 Finalized 되려면 전체 활성 Stake의 2/3 초과가 해당 블록 또는 그 후손을 Root로 확정해야 합니다.

Validator Stake 현재 Root
A 40% Slot 105
B 30% Slot 103
C 20% Slot 95
D 10% Slot 90

예를 들어 Slot 100의 블록 X가 있고, 모든 Root가 동일한 Fork에 존재한다고 가정하겠습니다.

Validator A는 Slot 105를 Root로 확정했습니다. Slot 100의 블록 X가 Slot 105의 조상이므로 A는 블록 X도 확정한 것입니다. Validator B도 같은 이유로 블록 X를 확정했습니다.

반면 C와 D는 아직 Slot 100까지 Root를 전진시키지 않았습니다. 따라서 블록 X를 확정한 Stake의 합계는 다음과 같습니다.

40%+30%=70%40\% + 30\% = 70\%

전체 활성 Stake의 2/3를 초과하므로 Slot 100의 블록 X는 Finalized 조건을 충족합니다.

RPC 노드의 Finalized 판단 흐름

이때 RPC 노드가 모든 Validator에게 getVoteAccounts 같은 RPC 요청을 각각 전송해서 Root를 수집하는 것은 아닙니다.

이미 P2P로 수신한 블록과 투표를 처리하면서 로컬에 보유한 정보를 집계하는 것입니다.

실제 Agave 구현에서는 AggregateCommitmentService와 BlockCommitmentCache 등의 구성 요소가 투표 지분과 확정 상태를 계산·관리합니다.

다만 RPC의 최종 확정 상태를 단순히 모든 Vote Account의 root_slot 숫자만 비교해서 계산하는 것으로 이해해서는 안 됩니다. 실제로는 Fork별 투표 기록, Lockout 깊이, Root, Stake 가중치 등을 종합하여 클러스터의 슈퍼다수 Root를 판단합니다.

Reference