시작하기 전에: 중요 안전 수칙
절대 하지 말아야 할 것
- 동일한
priv_validator_key.json으로 두 개의 노드를 동시에 실행하지 마세요. 이는 이중 서명을 발생시켜 슬래싱은 0%이지만 영구적인 툼스톤(tombstone) 처리를 초래합니다. 해당 검증자는 다시는 활성 세트에 복귀할 수 없습니다. - 결과를 완전히 이해하지 못한 상태에서 검증자 노드에
unsafe-reset-all을 사용하지 마세요. 이 명령은 합의 상태를 삭제하며, 툼스톤 처리로 이어지는 충돌 투표를 발생시킬 수 있습니다. - 노드가 실행 중인 상태에서
priv_validator_state.json을 백업하지 마세요. 이 파일은 합의 과정에서 계속 변경됩니다. 먼저 노드를 완전히 중지한 다음 복사하세요. - 백업해 둔
priv_validator_state.json을 복원하지 않은 채 스냅샷 복구 후 노드를 시작하지 마세요. 스냅샷에는 이 파일이 포함되어 있지 않습니다. 이 파일 없이 시작하면 서명 상태가 높이 0으로 초기화되어 이중 서명이 발생합니다. - 사전 테스트 없이 아카이벌 노드나 대용량 히스토리 노드를 롤백하지 마세요. 대용량 데이터베이스에서의 롤백은 수 시간이 걸리거나 노드를 완전히 사용 불능 상태로 만들 수 있으며, 특히 PebbleDB에서 그렇습니다.
- 모든 복구 작업(롤백, 스냅샷 복원, 바이너리 업그레이드) 전에, 노드를 완전히 중지한 후
priv_validator_state.json을 항상 백업하세요. - 롤백 또는 스냅샷 복구 후 노드를 시작하기 전에
priv_validator_state.json을 항상 원래 위치로 복원하세요. - 노드를 시작하기 전에
priv_validator_state.json이 온전한지 항상 확인하세요. height, round, step 값이 타당한지 점검하세요. - 조정 업그레이드에는 항상
--halt-height를 설정하세요. halt-height 플래그를 생략한 노드는 더 어려운 복구 경로를 거쳐야 합니다. - 업그레이드 후 시작하기 전에 항상
injectived version으로 바이너리 버전을 확인하세요. - 체인이 안정되면 임시 합의 오버라이드(
--unsafe-consensus-timeout-precommit-delta=1ms등)를 항상 원래대로 되돌리세요.
일반적인 문제와 해결 방법
업그레이드 높이에서 노드가 멈춤
증상:- 노드 로그에 예정된 업그레이드 높이에서 체인이 중단되었다고 표시됨
latest_block_height가 중단 높이를 넘어 진행되지 않음
- 노드 중지
~/.injectived/data/priv_validator_state.json백업- 새 바이너리 설치
- 확인:
injectived version - 노드 시작
업그레이드 후 블록 헤더 해시 불일치
증상:- 노드 중지
priv_validator_state.json백업- 한 블록 롤백:
priv_validator_state.json복원- 새 바이너리로 노드 시작
충돌 투표 경고
증상:priv_validator_state.json이 초기화되거나 손상되어, 이미 서명한 라운드에 다시 서명하면서 충돌 투표가 발생하고 있습니다.
일반적인 유발 요인:
- 검증자에서
unsafe-reset-all실행 - 오래되었거나 잘못된
priv_validator_state.json복원 - 노드가 실행 중인 상태에서
priv_validator_state.json을 백업함(오래된 사본) - 롤백 명령이 검증자 상태를 초기화함
- 올바른
priv_validator_state.json백업(노드를 완전히 중지한 후 생성한 것)이 있는 경우: 복원 후 재시작하세요. - 올바른 백업이 없는 경우: 즉시 노드를 중지하고 블록 생성이 재개될 때까지 기다린 후 재시작하세요. 잘못된 상태로 시작하면 이중 서명 위험이 있습니다.
- 서명 정보 확인:
검증자 툼스톤 처리됨(이중 서명)
증상:- 동일한 서명 키로 노드 인스턴스 두 개를 실행
- 이전에 서명한 높이에서 재서명을 유발하는 오래된
priv_validator_state.json복원 - 롤백으로 서명 상태가 초기화된 후 노드가 충돌하는 블록에 서명
- 영향을 받은 검증자의 툼스톤을 명시적으로 해제하는 거버넌스 제안 또는 업그레이드 핸들러
- 새 오퍼레이터 키로 새 검증자 생성(기존 위임을 잃음)
- 하드웨어 수준에서 단일 서명자를 보장하는 TMKMS 또는 Horcrux 사용
- 노드를 중지한 후 항상
priv_validator_state.json백업 - 동일한 서명 키로 두 개의 노드를 동시에 실행하지 않기
스냅샷에서 복구
사용 시점: 롤백이 실패하거나, 너무 오래 걸리거나, 노드 상태가 복구 불가능할 정도로 손상된 경우(AppHash 불일치). 절차:- 노드를 완전히 중지
~/.injectived/data/priv_validator_state.json백업- 다른 곳에 백업되어 있지 않다면
~/.injectived/config/priv_validator_key.json백업 - 신뢰할 수 있는 제공자로부터 스냅샷 다운로드:
- Injective 팀이 보안 업그레이드 전이나 도중에 긴급 스냅샷을 공유할 수 있음
- Polkachu Injective Snapshots (일반적으로 goleveldb)
- 인시던트 중에 커뮤니티 검증자들이 긴급 스냅샷을 공유할 수 있음
- 이전 데이터 제거:
- 스냅샷을
~/.injectived/data/에 압축 해제 - 백업해 둔
priv_validator_state.json을~/.injectived/data/에 복원 priv_validator_state.json이 존재하고 올바른지 확인- 노드 시작
자신의 priv_validator_state.json을 반드시 보관해야 하는 이유
스냅샷에는 블록체인 데이터(블록, 애플리케이션 상태)가 포함되지만, 검증자의 서명 상태는 절대 포함되지 않습니다. 서명 상태는 검증자가 마지막으로 서명한 높이(height), 라운드(round), 단계(step)를 추적합니다. 이 파일을 잃어버리거나 빈 파일로 교체하면, 노드는 자신이 이미 서명한 내용을 알지 못하고 충돌하는 블록에 서명할 수 있으며 — 이는 이중 서명과 영구적인 툼스톤 처리를 초래합니다.
서명 상태가 항상 스냅샷 높이보다 앞서 있어야(또는 같아야) 하는 이유를 보여주는 실제 예시입니다.
상황: 블록 125에 halt-height가 설정된 조정 체인 업그레이드.
priv_validator_state.json은 다음과 같습니다:
--halt-height 플래그는 블록 126이 커밋(확정)되는 것을 막지만, CometBFT 합의 엔진은 여전히 높이 126에 진입하여 라운드를 시작합니다 — 제안(proposing), prevote, precommit을 수행한 후에야 애플리케이션 계층이 블록 처리를 거부하고 노드가 종료됩니다. 높은 라운드 번호(42)는 검증자들이 점진적으로 중지하면서 합의에 도달하지 못한 채 네트워크가 라운드를 반복한 것을 반영합니다. 이는 정상적인 동작입니다: 해당 블록이 확정되지 않았더라도 여러분의 검증자는 높이 126에서 실제 투표를 했습니다.
즉, 여러분의 검증자는 이미 높이 126, 라운드 42에서 투표를 한 것입니다. 사용 가능한 스냅샷은 높이 115의 것입니다.
서명 상태 없이 스냅샷을 복원하면 발생하는 일:
스냅샷에는 priv_validator_state.json이 없거나 빈 파일(높이 0)이 들어 있습니다. 이 상태로 노드를 시작하면:
- 노드가 높이 115의 블록체인 데이터를 로드합니다
- 블록 116-125를 재생(replay)하여 높이 126까지 따라잡습니다
- 높이 126에서 합의에 진입하여 라운드 0부터 서명을 시작합니다
- 그러나 네트워크에는 이미 이 높이에서 라운드 42까지의 여러분의 투표가 존재합니다
- 노드가 높이 126에서 다른 블록 제안에 서명합니다(새 바이너리로 재생했기 때문에 다른 결과가 나올 수 있음)
- 네트워크가 여러분의 검증자 키에서 나온 두 개의 충돌하는 서명을 감지합니다
- 검증자는 이중 서명으로 툼스톤 처리됩니다. 영구적으로.
- 노드 중지
priv_validator_state.json백업(높이 126, 라운드 42로 기록되어 있음)- 데이터 디렉터리 삭제
- 스냅샷 압축 해제(높이 115의 블록체인 데이터)
- 백업해 둔
priv_validator_state.json을 데이터 디렉터리에 다시 복사 - 노드 시작
- 높이 115의 블록체인 데이터를 로드합니다
- 블록 116-125를 재생하여 높이 126까지 따라잡습니다
- 높이 126에서 서명 상태를 읽습니다: “나는 이미 라운드 42까지 서명했다”
- 라운드 0-42를 건너뛰고 라운드 43이 될 때까지 새로 서명하지 않습니다
- 충돌 투표가 없습니다. 검증자는 안전합니다.
데이터베이스 백엔드 호환성: 스냅샷은 백엔드 종속적입니다. goleveldb 스냅샷은 pebbledb로 구성된 노드에서 작동하지 않으며, 그 반대도 마찬가지입니다. 구성을 확인하세요:
롤백이 멈추거나 실패함
증상:injectived rollback이 실행되지만 완료되지 않거나 오류가 발생합니다.
원인:
- PebbleDB 백엔드: pebble에서의 롤백에는 알려진 문제가 있으며 무한정 멈출 수 있음
- 매우 큰 데이터베이스: 롤백 시간은 데이터베이스 크기에 비례함
- 손상된 WAL (Write-Ahead Log)
- PebbleDB 노드의 경우: 대신 스냅샷에서 복구
- 대용량 노드의 경우: 롤백이 30분 이상 완료되지 않으면 중단하고 스냅샷 사용
- goleveldb로의 전환을 고려하세요. PebbleDB는 공간 효율이 더 좋지만 롤백에 대한 검증이 덜 되어 있습니다
캐치업 중 라운드 회귀 오류
증상:AppHash 불일치
증상:- 롤백 시도:
injectived rollback - 롤백이 실패하거나 오류가 지속되는 경우: 스냅샷에서 복구
- 복구 후에는 항상
priv_validator_state.json을 복원
업그레이드 후 센트리 노드가 멈춤
증상: 검증자 노드는 업그레이드되어 서명 중이지만, 센트리 노드는 이전 블록 높이에 멈춰 있습니다. 원인: 센트리 노드도 업그레이드 높이를 지나 블록을 처리하려면 새 바이너리가 필요합니다. 해결 방법: 센트리 노드를 검증자와 동일한 바이너리 버전으로 업그레이드하세요. 센트리에는priv_validator_state.json이 없지만(서명하지 않음), 올바른 바이너리는 필요합니다.
업그레이드 후 체인 정지(투표력 부족)
증상:- 업그레이드 높이 이후 체인이 새 블록을 생성하지 않음
- 합의 라운드 번호가 계속 증가함(라운드 50, 100, 200+)
- 노드가 prevote와 precommit을 로그에 남기지만 블록이 커밋되지 않음
latest_block_height가 중단 높이에 멈춰 있음
- 체인이 업그레이드 높이에서 중단됩니다(예: 블록 125)
- 업그레이드를 완료한 검증자들이 높이 126에서 합의에 참여하기 시작합니다
- 각 라운드마다 네트워크가 블록 126을 확정하려 시도하지만, 투표력의 2/3 미만이 투표하고 있어 실패합니다
- 라운드 번호가 증가하며 이 주기가 반복됩니다. 라운드 1, 2, 3, … 50, … 100+
- 충분한 검증자가 업그레이드를 완료하고 온라인 상태가 될 때까지 계속됩니다
- 이미 업그레이드한 경우: 조치가 필요 없습니다. 노드는 참여 중이며 정족수에 도달하면 자동으로 다음 블록을 확정합니다. 노드가 라운드를 따라잡는 동안 로그에 라운드 회귀 오류가 표시될 것입니다. 이는 예상된 동작입니다(캐치업 중 라운드 회귀 오류 참조).
- 아직 업그레이드하지 않은 경우: 여러분이 부족한 투표력의 일부입니다. 체인이 재개될 수 있도록 가능한 한 빨리 업그레이드를 완료하세요.
- 진행 상황 모니터링: 얼마나 많은 검증자가 온라인 상태로 참여 중인지 확인:
- 검증자 채널에서 조율: 주요 업그레이드 중에는 검증자들이 일반적으로 검증된 검증자 채널에서 업그레이드 진행 상황과 투표력 비율을 추적하며 조율합니다.
이 시간대가 길어질수록 라운드 번호는 더 높이 올라갑니다. 나중에 온라인 상태가 되는 검증자는 그 모든 라운드를 따라잡아야 하며, 이것이
--unsafe-consensus-timeout-precommit-delta=1ms 플래그가 존재하는 이유입니다. 다만 체인이 안정된 후에는 제거해야 한다는 점을 기억하세요.다운타임으로 감금됨(툼스톤 아님)
증상:- 검증자가 비활성 또는 감금 상태로 표시됨
- 서명 정보에
tombstoned: false가 표시됨 - 누락 블록 카운터가 높음
- 노드가 실행 중이고 최신 블록까지 완전히 따라잡았는지 확인
- 감금 해제:
- 검증자가 다시 활성 상태인지 확인:
조정 업그레이드 체크리스트
업그레이드 높이 이전
- 거버넌스 제안 또는 체인 팀으로부터 목표 halt-height 확인
- 새 바이너리 다운로드 및 검증(sha256 체크섬 확인)
- 노드 구성 또는 CLI 플래그에
--halt-height=<target_height>설정 - Cosmovisor 사용 시: 올바른 업그레이드 디렉터리에 새 바이너리 배치
-
priv_validator_state.json백업 - 롤백이 필요할 경우에 대비해 스냅샷 제공자 파악
- 중단 높이까지의 체인 진행 상황 모니터링
업그레이드 높이에서
- 노드가 예정된 높이에서 중단되었는지 확인
- 노드를 완전히 중지(프로세스가 종료되었는지 확인)
-
priv_validator_state.json백업 - 새 바이너리 설치
- 버전 확인:
업그레이드 이후
- 새 바이너리로 노드 시작
- 합의 참여 여부를 로그로 모니터링
- prevote가 올바른지 확인(매 라운드마다 nil에 투표하지 않는지)
- 익스플로러에서 투표력 모니터링 (Mintscan)
-
wrong Block.Header.LastResultsHash가 표시되면: 중지, 1블록 롤백,priv_validator_state.json복원, 재시작 - 라운드 캐치업 오버라이드(
--unsafe-consensus-timeout-precommit-delta)를 사용 중이라면: 안정화 후 제거 - 검증자가 서명 중인지 확인:
모니터링 참조
합의 및 동기화 상태
검증자 상태 점검
노드 구성
프루닝 노드와 아카이벌 노드 비교
추가 리소스
스냅샷 리소스
Injective 제공 스냅샷
Injective는 두 개의 리전에서 프루닝된 메인넷 스냅샷을 유지 관리합니다. 최신 사용 가능 높이와 다운로드 URL은 상태 엔드포인트를 확인하세요:
최신 스냅샷을 다운로드하려면 상태 엔드포인트에서 현재 파일 이름을 확인하세요:
커뮤니티 스냅샷 제공자
- Polkachu Injective Snapshots (일반적으로 goleveldb, 프루닝)
- HighStakes Injective Snapshots
- 인시던트 중에는 커뮤니티 검증자들이 검증자 채널에서 긴급 스냅샷을 공유할 수 있음
