결함 허용 및 최종성
BFT 보장
Savitri 합의는 쿼럼 2f+1 (67% 임계값)을 가진 BFT (Byzantine Fault Tolerant) 투표 프로토콜을 사용합니다.
결함 허용
| 전체 노드 수 (n) | 최대 비잔틴 노드 (f) | 필요 쿼럼 |
|---|---|---|
| 3 | 0 | 2 |
| 5 | 1 | 4 |
| 7 | 2 | 5 |
| 10 | 3 | 7 |
| 15 | 4 | 11 |
공식: f = floor((n-1) / 3), 쿼럼 = 2f + 1
안전성
블록은 2f+1 검증자의 서명을 가진 **블록 수락 인증서 (BAC)**가 생성될 때만 최종화됩니다. 이는 다음을 보장합니다:
- 상충되는 블록은 동일한 높이에서 최종화될 수 없습니다
- BAC가 발행된 후에는 롤백이 없습니다 (확률론적이 아닌 결정론적 최종성)
- 비잔틴 노드는 쿼럼 참여 없이 인증서를 위조할 수 없습니다
활성성
네트워크는 n - f개의 정직한 노드가 온라인인 한 블록을 생성할 수 있습니다:
- 제안자 교체: 50블록 후 제안자가 단일 실패 지점을 방지하기 위해 교체됩니다
- 선거 감시자: 60초 동안 블록 진행이 없으면 선거를 재활성화합니다
- 점진적 쿼럼 완화: 연속 선거 실패 3회 이상 후 최소 후보자 수가 2로 낮아집니다
DAG 구조
블록 헤더는 동시 블록 생성을 위한 다중 부모 DAG 구조를 지원합니다:
pub struct BlockHeader {
pub parent_hash: Vec<u8>, // 기본 부모 (하위 호환성)
pub parent_hashes: Vec<Vec<u8>>, // DAG를 위한 추가 부모
// ...
}
충돌 탐지
ConflictDetector는 다음을 식별합니다:
- 이중 지출 충돌: 여러 브랜치에서 참조된 동일한 UTXO
- 상태 충돌: 충돌하는 상태 전환
- 포크 탐지: 다른 제안자로부터 동일 높이의 여러 블록
충돌 해결
충돌이 탐지되면:
- 누적 PoU 점수가 더 높은 브랜치 선택
- 충돌하는 트랜잭션 취소
- 손실 브랜치에서 충돌하지 않는 트랜잭션 재적용
그룹 인식 합의
그룹 구성
Masternode가 lightnode를 그룹으로 구성합니다:
- PoU 점수별 lightnode 정렬
group_size그룹에 배정 (개발 3, 운영 7)- gossipsub을 통해 그룹 배정 발행
- 시스템 시간이 아닌 에포크 기반의 결정론적 그룹 ID
그룹 내 선거
각 그룹 내에서:
- 구성원들이 PoU 점수를 공유합니다
- 가장 높은 PoU 점수가 제안자가 됩니다 (동점 시 peer_id로 결정)
- 최소
(total+1)/2명의 후보자 필요 - 3회 이상 실패 후: 최소 2명의 후보자로 완화
블록 수락
- 그룹 제안자가 블록 생성
- 그룹 구성원들이 검증 및 서명
- 2f+1 서명으로 BAC 생성
- Masternode가 BAC를 검증하고 최종화
복구 메커니즘
선거 복구
| 메커니즘 | 트리거 | 동작 |
|---|---|---|
| 감시자 타이머 | 60초 동안 블록 없음 | PoU + 선거 재활성화 |
| 점진적 완화 | 3회 이상 실패 | 쿼럼을 2로 낮춤 |
| 제안자 교체 | 50블록 | 교체, 재선거 |
| 즉각 재선거 | 그룹 재초기화 | PoU + 선거 작업 시작 |
피어 복구
| 메커니즘 | 트리거 | 동작 |
|---|---|---|
| Gossipsub 킵얼라이브 | 60초 간격 | PoU 점수 발행 |
| 메시 복구 감시자 | 60초 동안 메시 없음 | 그룹 피어 재연결 |
| SlowPeer 연결 해제 | 큐 포화 | 연결 해제 및 재연결 |
| 논스 재설정 | 로컬 > 스토리지 + 200 | 스토리지 논스로 재설정 |
그룹 복구
그룹이 재초기화될 때:
- 기존 구성원의 PoU 점수 유지
- 신규 구성원은 기본 점수로 시작
intra_group_started플래그 재설정- 주기적 타이머 대기 없이 즉시 PoU + 선거 시작
슬래싱 (운영)
| 위반 | 페널티 | 냉각 시간 |
|---|---|---|
| 이중 투표 | 스테이크 50% | 없음 |
| 다운타임 | 스테이크 10% | 점진적 |
| 유효하지 않은 제안 | 스테이크 25% | 없음 |
슬래싱은 개발넷에서 비활성화, 메인넷에서 활성화 (config/production.toml).
합의 설정
| 매개변수 | 개발 | 운영 |
|---|---|---|
| 타임아웃 | 15초 | 10초 |
| 최대 라운드 | 5 | 10 |
| 쿼럼 임계값 | 0.67 | 0.67 |
| BFT 최적화 | 비활성화 | 활성화 |
| 슬래싱 | 비활성화 | 활성화 |
| 블록 시간 | 2초 | 5초 |
| 그룹 크기 | 3 | 7 |