Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

합의 알고리즘: 분산 네트워크가 동의에 이르는 방법

수천 개의 노드가 각자 다른 트랜잭션을 받고, 각자 다른 블록을 만들려고 할 때, 어떻게 모두가 동일한 블록체인에 동의할 수 있을까? 이것이 합의(Consensus) 문제다.


1. 비잔틴 장군 문제

합의 알고리즘을 이해하려면 먼저 **비잔틴 장군 문제(Byzantine Generals Problem)**를 알아야 한다.

시나리오: 비잔틴 제국의 군대가 적의 도시를 포위하고 있다.
여러 장군이 각기 다른 위치에 있으며 전령을 통해 소통한다.

           장군 A
          /      \
        전령    전령
        /            \
장군 B ─────전령──── 장군 C
        (배신자)

- 장군들은 "공격" 또는 "후퇴"를 투표해야 함
- 과반수가 같은 행동을 해야 성공
- 문제: 일부 장군(또는 전령)이 배신자일 수 있음
  - 배신자는 거짓 메시지를 보내거나, 
    어떤 장군에게는 "공격", 다른 장군에게는 "후퇴"를 전달할 수 있음

블록체인에서의 대응:

  • 장군 = 네트워크 노드
  • 메시지 = 블록, 트랜잭션
  • 배신자 = 악의적인 노드 (해커, 버그가 있는 노드)
  • 합의 = 모든 정직한 노드가 같은 블록체인 상태에 동의

이론적으로 비잔틴 내결함성(BFT)을 달성하려면 전체 노드 중 최대 1/3만이 악의적이어야 한다 (3f+1 규칙).


2. Proof of Work (PoW) — 작업 증명

2.1 핵심 아이디어

“계산 작업을 많이 한 사람이 블록을 추가할 권리를 얻는다.”

CPU/GPU 연산 능력을 소모해야 블록을 생성할 수 있으므로, 공격하려면 엄청난 실제 자원(전기, 하드웨어)이 필요하다.

2.2 채굴 과정 상세

채굴자의 목표: 
  SHA256(블록 헤더) 값이 특정 목표값보다 작아야 한다

목표값 (난이도에 따라 달라짐):
  00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
  (앞에 0이 8개)

채굴 루프:
  nonce = 0
  반복:
    hash = SHA256(SHA256(헤더 + nonce))
    if hash < target:
      블록 발견! 네트워크에 전파
    else:
      nonce += 1

왜 어려운가? SHA-256의 출력은 완전히 예측 불가능하다. 올바른 nonce를 찾는 유일한 방법은 일일이 시도해보는 것(무차별 대입)뿐이다.

확률 예시:

  • 해시 앞에 0이 10개 필요: 1/16^10 = 1/1,099,511,627,776 확률
  • 즉 평균 1조 번 이상의 계산이 필요

2.3 난이도 조절

비트코인은 2,016블록(약 2주)마다 난이도를 자동 조절한다:

실제 소요 시간 < 2주: 난이도 상승 (더 어렵게)
실제 소요 시간 > 2주: 난이도 하락 (더 쉽게)

목표: 항상 평균 10분당 1블록

예시:
  이전 2주간 블록 생성: 1,500개 (목표의 74.4%)
  → 10분이 걸릴 것들이 평균 8.1분에 생성됨
  → 난이도를 10/8.1 = 1.23배 상승

2.4 Rust로 PoW 시뮬레이션

use sha2::{Sha256, Digest};
use std::time::Instant;

fn mine_block(data: &str, difficulty: usize) -> (u64, String) {
    let target = "0".repeat(difficulty);
    let start = Instant::now();
    
    let mut nonce: u64 = 0;
    
    loop {
        let input = format!("{}{}", data, nonce);
        let mut hasher = Sha256::new();
        hasher.update(input.as_bytes());
        let hash = hex::encode(hasher.finalize());
        
        if hash.starts_with(&target) {
            let elapsed = start.elapsed();
            println!("채굴 완료!");
            println!("  nonce:   {}", nonce);
            println!("  hash:    {}", hash);
            println!("  시간:    {:.3}초", elapsed.as_secs_f64());
            println!("  시도 수: {}", nonce + 1);
            return (nonce, hash);
        }
        
        nonce += 1;
        
        // 진행 상황 표시 (100만 번마다)
        if nonce % 1_000_000 == 0 {
            println!("{}백만 번 시도 중...", nonce / 1_000_000);
        }
    }
}

fn main() {
    let block_data = "블록 #1: Alice→Bob 1ETH, Bob→Carol 0.5ETH";
    
    for difficulty in [2, 3, 4, 5] {
        println!("\n=== 난이도 {} ===", difficulty);
        mine_block(block_data, difficulty);
    }
}

실행 결과 예시:

=== 난이도 2 ===
채굴 완료!
  nonce:   138
  hash:    003a7f1c...
  시간:    0.001초
  시도 수: 139

=== 난이도 4 ===
채굴 완료!
  nonce:   52,847
  hash:    0000d3c1...
  시간:    0.045초
  시도 수: 52,848

=== 난이도 5 ===
채굴 완료!
  nonce:   1,245,832
  hash:    00000b7a...
  시간:    1.073초
  시도 수: 1,245,833

난이도가 1 증가할 때마다 평균 시도 횟수가 16배 증가한다 (16진수 한 자리 = 4비트).

2.5 PoW의 문제점

에너지 소비:
  비트코인 네트워크 연간 전력 소비
  ≈ 아르헨티나 전체 전력 소비량 (약 130 TWh)
  
  이는 모든 채굴자가 의도적으로 비효율적인 
  작업(nonce 탐색)에 자원을 낭비하기 때문

3. Proof of Stake (PoS) — 지분 증명

3.1 핵심 아이디어

“코인을 많이 담보로 맡긴 사람이 블록 생성 권한을 얻는다.”

계산 능력 대신 **경제적 담보(Stake)**를 사용한다.

PoW: 
  블록 생성권 = f(해시파워)
  공격 비용   = 하드웨어 + 전기세

PoS:
  블록 생성권 = f(스테이킹한 ETH 양)
  공격 비용   = 코인 자체 (공격하면 내 코인 가치가 떨어짐)

3.2 이더리움 PoS 구성 요소

검증자 (Validator)

  • 최소 32 ETH를 스테이킹(잠금)한 노드
  • 블록 제안 및 투표 권한 획득
  • 현재 이더리움에 약 900,000명 이상의 검증자

슬래싱 (Slashing)

  • 악의적인 행동(이중 투표, 연속 오프라인 등)에 대한 처벌
  • 스테이킹한 ETH의 일부 또는 전부가 소각됨
  • 경제적 패널티가 정직한 행동을 유도
검증자의 보상과 처벌:

정직하게 행동 시:
  + 블록 제안 보상 (~0.1-0.2 ETH)
  + 증명(Attestation) 보상
  + MEV(최대 추출 가능 가치) 보상

악의적 행동 시:
  - 슬래싱: 최소 1/32 스테이크 즉시 삭감
  - 강제 퇴출 (검증자 자격 박탈)
  - 최대 전체 스테이크 손실 가능

3.3 블록 생성 과정

1. 에포크(Epoch, 32슬롯 = ~6.4분) 시작 시
   검증자들이 무작위로 위원회에 배정됨

2. 각 슬롯(12초)마다:
   - RANDAO 알고리즘으로 무작위 블록 제안자 선택
   - 제안자가 새 블록 생성 및 전파

3. 위원회 검증자들이 블록에 투표(Attestation)

4. 2/3 이상 투표 획득 시 블록 확정

5. 체크포인트(매 64슬롯)가 최종 확정(Finality) 됨
   → 이후 절대 변경 불가

3.4 The Merge — 이더리움의 PoW → PoS 전환

타임라인:
  2015년  - 이더리움 메인넷 출시 (PoW)
  2020년  - 비콘 체인(Beacon Chain) 출시 (PoS 테스트)
  2022년 9월 15일 - The Merge 완료!
  
  결과:
  - 에너지 소비 99.95% 감소
  - 발행량 ~90% 감소 (채굴 보상 없어짐)
  - 블록 시간: 평균 13초 → 정확히 12초

4. Proof of History (PoH) — 역사 증명 (Solana)

4.1 문제: PoS의 시간 동기화 한계

분산 네트워크에서 “지금이 몇 시인가“는 합의가 필요한 문제다. 각 노드의 시계가 조금씩 다를 수 있기 때문이다. 이 때문에 PoS 시스템은 슬롯 시간을 길게 잡아야 했다.

4.2 PoH: 시간을 해시로 증명

Solana는 시간 자체를 블록체인에 기록한다.

PoH 순서:
hash_0 = SHA256("초기값")
hash_1 = SHA256(hash_0)         ← 1회 반복
hash_2 = SHA256(hash_1)         ← 2회 반복
hash_3 = SHA256(hash_2)
hash_4 = SHA256(hash_3)
hash_5 = SHA256(hash_4)
hash_N = SHA256(hash_{N-1})     ← N회 반복

각 hash_N이 "N번의 계산이 일어났다"는 증거가 됨
= 시간이 흘렀다는 증거

VDF (Verifiable Delay Function, 검증 가능한 지연 함수)

  • 순차적으로만 계산 가능 (병렬화 불가)
  • 계산은 오래 걸리지만, 검증은 빠름
  • “이 해시를 만들려면 최소 X시간이 걸렸을 것“을 수학적으로 증명

4.3 PoH의 효과

기존 PoS: 
  각 블록마다 "이게 맞는 순서야?" 투표 → 느림

Solana PoH:
  해시 체인 자체가 시간순서를 증명
  → 투표 없이도 순서가 명백함
  → 초당 65,000 트랜잭션 처리 가능 (이론값)

5. PBFT와 IBFT 2.0

5.1 PBFT (Practical Byzantine Fault Tolerance)

1999년에 제안된 고전적인 BFT 알고리즘.

PBFT 라운드:
  1. Pre-prepare: 리더가 요청 브로드캐스트
  2. Prepare:     각 노드가 "나도 봤어" 응답
  3. Commit:      2f+1 응답 수집 후 "확정" 메시지
  4. Reply:       클라이언트에게 결과 전달

f = 결함 허용 노드 수
총 노드 수 = 3f + 1 필요
예: f=1이면 최소 4개 노드 필요

특징:

  • 최종성(Finality)이 즉각적: 블록이 한 번 확정되면 절대 변경 안 됨
  • 노드 수가 많아지면 메시지가 O(n²)로 급증 → 확장성 한계
  • 허가된(Permissioned) 네트워크에 적합

5.2 IBFT 2.0 (Istanbul Byzantine Fault Tolerance 2.0)

이 가이드의 실습 플랫폼인 Hyperledger Besu가 사용하는 합의 알고리즘이다.

PBFT를 블록체인에 맞게 개선한 버전:

IBFT 2.0 블록 생성 과정:

라운드 시작
    │
    ▼
ProposerSelection: 라운드 로빈으로 제안자 선택
    │
    ▼
Propose: 제안자가 블록 전파
    │
    ▼
Prepare: 검증자들이 블록 검증 후 PREPARE 메시지 전송
    │ (2f+1 PREPARE 수신 대기)
    ▼
Commit: COMMIT 메시지 전송
    │ (2f+1 COMMIT 수신 시 블록 확정)
    ▼
블록 추가 완료 (즉각 최종성!)
    │
    └─ 만약 제한 시간 내 합의 실패 시:
       라운드 변경 (Round Change) → 다음 제안자 선택

IBFT 2.0의 특징:

  • 즉각적 최종성: 블록 확정 후 재조직(Reorg) 없음
  • 에너지 효율적: PoW 불필요
  • 허가형 네트워크: 검증자 집합이 알려져 있음
  • 결함 허용: 전체 검증자의 1/3 미만이 악의적이어도 동작
  • Besu 지원: Hyperledger Besu의 기본 엔터프라이즈 합의
Besu 네트워크 설정 예시 (genesis.json):
{
  "config": {
    "chainId": 1337,
    "ibft2": {
      "blockperiodseconds": 2,     // 2초마다 블록
      "epochlength": 30000,         // 검증자 투표 주기
      "requesttimeoutseconds": 4   // 타임아웃
    }
  }
}

6. 합의 알고리즘 비교

항목PoWPoSPoH (Solana)IBFT 2.0
블록 시간~10분 (BTC)~12초 (ETH)~400ms~2초
최종성확률적 (6블록)~15분~1초즉각적
에너지매우 높음낮음낮음낮음
탈중앙화높음높음중간낮음
확장성낮음중간높음중간
결함 허용51% 해시파워33% 지분-33% 검증자
허가 필요불필요불필요불필요필요
주요 사용비트코인이더리움SolanaBesu 엔터프라이즈
공격 비용하드웨어+전기코인 자체-기관 신뢰

7. 핵심 정리

  • 비잔틴 장군 문제: 악의적 참여자가 있는 분산 환경에서 합의를 달성하는 고전적 문제
  • PoW: 계산 작업으로 권한 증명. 안전하지만 에너지 소비가 큼
  • PoS: 경제적 담보로 권한 증명. 에너지 효율적이며 이더리움의 현재 방식
  • PoH: 해시 체인으로 시간을 증명. Solana의 고속 처리를 가능하게 함
  • IBFT 2.0: PBFT 기반의 즉각 최종성. 우리가 사용할 Besu의 합의 알고리즘

다음 파트(Chapter 10)에서는 이 모든 기초 위에 세워진 이더리움 플랫폼을 깊이 파고든다.