메인 콘텐츠로 건너뛰기

목적 및 범위

이 문서는 정식 체인 유지, 블록 삽입, 체인 재구성 처리를 담당하는 블록체인 관리 하위 시스템을 설명합니다. BlockChainHeaderChain이 블록 헤더, 본문, 영수증 및 체인 선택에 필요한 메타데이터를 추적하여 체인 상태를 관리하는 방식을 다룹니다. 관련 문서:

핵심 구조

BlockChain

BlockChain 타입은 정식 블록체인을 관리하는 중앙 컴포넌트입니다. 블록 삽입, 검증, 상태 실행, 체인 재구성을 조정하며, 합의 엔진(consensus.Engine), 포크 선택 로직(ForkChoice), 상태 처리기(Processor), 블록 검증기(Validator)와 협력합니다. 주요 상태로 현재 정식 헤드(currentBlock), 스냅 동기화 기준 블록(currentSnapBlock), 최종화된 블록(currentFinalBlock), 안전 블록(currentSafeBlock)을 추적합니다. 이러한 헤드 포인터는 합의 규칙과 포크 선택 결과에 따라 갱신됩니다.

HeaderChain

HeaderChain은 블록 헤더 저장소와 번호–해시 매핑을 관리하는 경량 체인 구조입니다. 헤더 단위 검증과 체인 탐색을 담당하며, 헤더 체인 재구성과 정식 헤더 매핑 갱신을 조정합니다. 전체 블록 삽입은 BlockChain이 담당하며, HeaderChain은 그 하위 구성 요소로 사용됩니다.

정식 체인 관리

정식 체인은 노드가 따르는 공식 체인 경로를 의미합니다. 블록체인은 다음 두 가지 핵심 매핑을 유지합니다:
  • 번호 → 해시: 특정 블록 번호에 대응하는 정식 블록 해시
  • 해시 → 번호: 특정 블록 해시에 대응하는 블록 번호
이 매핑은 체인 재구성 시 일관되게 갱신되며, RPC 조회와 내부 검증의 기준으로 사용됩니다.

초기화 시 상태 로딩

초기화 중 loadLastState() 메서드는 디스크에서 체인 상태를 복원합니다:
  1. 데이터베이스에서 마지막 헤드 블록 해시 읽기
  2. 해시를 통해 헤드 블록 로드
  3. 현재 블록(currentBlock) 설정
  4. 헤더 체인 헤드 로드
  5. 스냅 기준 블록 및 최종화 블록 로드

블록 삽입 파이프라인

블록 삽입은 검증, 실행, 정식 체인 업데이트를 포함하는 다단계 프로세스입니다.

삽입 흐름 요약

InsertChain() 메서드는 블록 배치를 삽입하는 주요 진입점이며, 내부적으로 다음 단계를 거칩니다:
사전 검증 → 헤더 검증 → 본문 검증 → 상태 실행
→ 상태 검증 → 상태 커밋 → 포크 선택 판단 → 이벤트 게시

각 단계 설명

1. 사전 검증
  • 미래 블록 캐시(futureBlocks) 확인
  • 블록 중복 삽입 여부 확인
  • 부모 블록 존재 여부 확인
2. 헤더 검증
  • 합의 엔진의 VerifyHeader() 호출
  • WBFT의 경우 제안자, 서명, 검증자 세트 정합성 검증
  • 블록 번호, 타임스탬프, 가스 한도 규칙 확인
3. 본문 검증
  • ValidateBody() 호출
  • 트랜잭션 루트 해시와 헤더 일치 여부 확인
  • WBFT 환경에서는 엉클 블록이 존재하지 않음을 검증
4. 상태 실행
  • 부모 블록 상태를 기반으로 StateDB 생성
  • 각 트랜잭션에 대해 ApplyTransaction() 호출하여 EVM 실행
  • 영수증 및 사용 가스 누적
5. 상태 검증
  • ValidateState() 호출
  • 가스 사용량, 영수증 블룸, 상태 루트 검증
6. 상태 커밋
  • 블록과 영수증을 데이터베이스에 기록
  • 상태 trie 커밋 및 스냅샷 갱신
7. 포크 선택 판단
  • 합의 엔진과 포크 선택 규칙에 따라 새 블록의 우선순위 평가
  • 필요 시 체인 재구성 수행
8. 이벤트 게시
  • ChainEvent, ChainHeadEvent 발생
  • 로그 및 트랜잭션 풀에 새 헤드 알림 전파

체인 재구성

체인 재구성(reorg)은 포크 선택 규칙에 따라 기존 정식 체인보다 우선하는 체인이 등장할 경우 발생합니다. StableNet의 WBFT 환경에서는 총 난이도 대신 합의 규칙과 에포크 기반 검증자 합의 결과가 체인 선택의 기준이 됩니다.

재구성 프로세스

  1. 포크 선택 결정: ForkChoice 로직이 새 블록의 정식 체인 채택 여부 판단
  2. 공통 조상 탐색: 기존 체인과 새 체인의 분기점 탐색
  3. 정식 매핑 갱신: HeaderChain.Reorg()를 통해 번호–해시 매핑 갱신
  4. 헤드 포인터 갱신: currentBlock, currentFinalBlock, currentSafeBlock 업데이트
HeaderChain.Reorg()의 주요 동작은 다음과 같습니다:
  1. 부모가 현재 헤드인 경우 단순 확장
  2. 기존 정식 매핑 중 교체 대상 제거
  3. 공통 조상까지 역추적하며 매핑 재작성
  4. 새 체인의 헤더를 정식 체인으로 기록
  5. 헤드 헤더 해시를 데이터베이스에 저장

캐싱

블록체인은 LRU 캐시를 사용하여 디스크 접근을 최소화합니다:
캐시크기용도
bodyCache256블록 본문 캐시
blockCache256완전한 블록 캐시
receiptsCache32트랜잭션 영수증 캐시
txLookupCache1024트랜잭션 위치 조회
futureBlocks256미래 시점 블록 임시 보관

체인 복구

SetHead

SetHead() 메서드는 체인을 특정 블록 번호까지 되돌립니다. 주요 사용 사례는 다음과 같습니다:
  • 손상된 블록 이후 상태 복구
  • 알려진 문제 블록 우회
  • 체인 규칙 변경 후 재동기화

Reset

Reset()은 전체 체인 데이터를 제거하고 제네시스 블록 상태로 복원합니다.

SnapSyncCommitHead

스냅 동기화 완료 시 호출되어 동기화된 블록을 정식 헤드로 설정합니다:
  1. 블록 존재 여부 확인
  2. 상태 저장소 활성화
  3. 상태 trie 접근 가능성 검증
  4. 현재 블록 포인터 갱신
  5. 스냅샷 구조 재구성

데이터베이스 스키마

블록 저장소 키

키 패턴값 타입용도
h{num}ncommon.Hash블록 번호의 정식 해시
h{hash}nuint64해시의 블록 번호
H{hash}{num}*types.Header블록 헤더
b{hash}{num}*types.Body블록 본문
r{hash}{num}[]*types.Receipt트랜잭션 영수증

체인 상태 키

용도
LastBlock정식 블록 헤드 해시
LastHeader정식 헤더 헤드 해시
LastFast스냅 기준 블록 해시
LastFinalized최종화 블록 해시
SnapshotRoot스냅샷 루트

오류 처리

오류조건처리 방식
ErrKnownBlock이미 처리된 블록무시
ErrNoGenesis제네시스 누락초기화 필요
ErrBannedHash차단된 블록 해시체인 되돌리기
ErrUnknownAncestor부모 블록 없음피어에서 요청
ErrPrunedAncestor부모 상태 프루닝됨스냅 동기화 필요
errInsertionInterrupted삽입 중단현재 삽입 중지