메인 콘텐츠로 건너뛰기

목적 및 범위

이 가이드는 StableNet 노드 및 검증자 인프라를 배포하고 운영하며 유지 관리하기 위한 운영 지침을 제공합니다. 네트워크 배포 절차, 검증자 운영 방법, 노드 유지 관리 전반을 다룹니다. 시스템 아키텍처 및 컴포넌트 설계에 대한 내용은 Core Architecture를 참고하세요. 합의 프로토콜의 세부 동작은 Anzeon WBFT Consensus Protocol을, 거버넌스 컨트랙트 사용 방법은 Governance System 문서를 참조하세요.

네트워크 배포

제네시스 파일 생성

StableNet 네트워크는 genesis_generator 도구로 생성된 제네시스 파일을 사용하여 초기화됩니다. 해당 도구는 Anzeon 합의 매개변수와 시스템 컨트랙트를 포함한 제네시스 블록을 생성합니다.

제네시스 구성 매개변수

StableNet의 제네시스 구성은 anzeon 섹션에서 합의 및 거버넌스와 관련된 전용 매개변수를 정의해야 합니다.
ParameterLocationDescription
wbft.epochLengthanzeon.wbft.epochLengthNumber of blocks per epoch (default: 10)
wbft.blockPeriodSecondsanzeon.wbft.blockPeriodSecondsTarget block time in seconds (default: 1)
wbft.requestTimeoutSecondsanzeon.wbft.requestTimeoutSecondsConsensus timeout in seconds (default: 2)
wbft.proposerPolicyanzeon.wbft.proposerPolicyProposer selection policy (0 = round-robin)
init.validatorsanzeon.init.validatorsInitial validator addresses for first epoch
init.blsPublicKeysanzeon.init.blsPublicKeysBLS public keys for each validator
systemContractsanzeon.systemContractsConfiguration for system contracts

시스템 컨트랙트 초기화

각 시스템 컨트랙트는 제네시스 단계에서 초기화 매개변수를 통해 구성됩니다. 아래는 주요 시스템 컨트랙트별 초기화 매개변수 목록입니다. GovValidator (주소: 0x0000000000000000000000000000000000001001)
  • members: 쉼표로 구분된 운영자 주소 목록
  • validators: 쉼표로 구분된 검증자 주소 목록
  • blsPublicKeys: 검증자 BLS 공개 키 목록 (validators 순서와 동일)
  • quorum: 거버넌스 작업을 승인하기 위한 최소 투표 수
  • expiry: 거버넌스 제안 만료 시간 (초 단위, 기본값: 604800 = 7일)
  • gasTip: 일반 계정 트랜잭션에 적용되는 가스 팁 (wei 단위)
NativeCoinAdapter (주소: 0x0000000000000000000000000000000000001000)
  • name: 네이티브 토큰 이름 (예: "WKRC")
  • symbol: 네이티브 토큰 심볼 (예: "WKRC")
  • decimals: 토큰 소수점 자리 수 (일반적으로 18)
  • currency: 토큰이 페그된 법정화폐 코드 (예: "KRW")
  • masterMinter: GovMasterMinter 컨트랙트 주소
  • minters: 민팅 권한을 가진 컨트랙트 주소 목록 (쉼표 구분)

부트노드 구성

StableNet 네트워크는 피어 발견을 위해 부트노드를 사용합니다. 부트노드는 실행 시 --bootnodes 플래그를 통해 지정하거나, 구성 파일에 설정하여 사용할 수 있습니다. 부트노드 사용 예시 (--bootnodes 플래그 사용)
--bootnodes enode://722f1f35c6fe2ac829aa9e0d7ef55bbe782ef3cea1e2354eefbe1584057a01b7@127.0.0.1:8589,enode://aa46e4a40781022e480bb05d1fd578fff164dc2ad379dc00370456c5ce9c2479@127.0.0.1:8589
부트노드는 다음 우선순위에 따라 선택됩니다.
  1. --bootnodes 플래그로 명시적으로 지정된 값
  2. 구성 파일에 정의된 BootstrapNodes
  3. 네트워크 사전 설정 플래그 (--mainnet, --testnet)
  4. 기본 Mainnet 부트노드 설정

네트워크 플래그 및 구성

StableNet 네트워크를 배포하고 실행하기 위해 다음과 같은 주요 명령줄 플래그를 사용합니다.
FlagPurposeDefault
--datadirData directory for databases and keystore~/.stable
--mainnetStableNet mainnet-
--testnetStableNet test network-
--networkidNetwork ID (auto-detects from chain ID if 0)0
--portP2P listening port30303
--bootnodesComma-separated enode URLs for bootstrapNetwork-specific
--maxpeersMaximum number of network peers50
--nodiscoverDisable peer discovery mechanismfalse
--natNAT port mapping mechanism”any”

검증자 운영

검증자 키 구조

StableNet 검증자는 합의 및 거버넌스 시스템에 참여하기 위해 각각 다른 역할을 수행하는 세 가지 암호화 키를 사용합니다.

키 생성 및 관리

ECDSA 키

ECDSA 키는 표준 Ethereum 키스토어 형식을 사용하여 생성 및 관리합니다.
# Generate operator key (for governance)
gstable account new --datadir /data/validator1

# Generate validator key (for block signing)
gstable account new --datadir /data/validator1 --keystore /data/validator1/validator-keystore

# Import existing private key
gstable account import private.key --datadir /data/validator1
공개키 주소는 노드의 etherbase(coinbase)로 설정되며, GovValidator.validators에 등록된 주소와 반드시 일치해야 합니다.

BLS 키 파생

BLS 키는 검증자의 ECDSA 개인 키로부터 결정적으로 파생됩니다. 이를 통해 동일한 ECDSA 개인 키에 대해 항상 동일한 BLS 키가 생성됩니다.
// Derive BLS key from ECDSA private key
blsKey, err := bls.DeriveFromECDSA(ecdsaPrivateKey)
if err != nil {
    log.Fatal("Failed to derive BLS key", "err", err)
}
blsPublicKey := blsKey.PublicKey()
파생된 BLS 공개 키는 검증자 주소와 동일한 인덱스에 위치하도록 GovValidator.blsPublicKeys에 등록되어야 합니다.

검증자 등록

검증자는 거버넌스 제안을 통해 GovValidator 컨트랙트에 등록됩니다. 등록이 완료된 검증자만 합의 및 블록 제안에 참여할 수 있습니다.

검증자 노드 시작

다음은 마이닝이 활성화된 검증자 노드를 시작하는 예시입니다.
gstable \
    --datadir /data/validator1 \
    --networkid 8282 \
    --mine \
    --miner.etherbase 0xYOUR_VALIDATOR_ADDRESS
주요 검증자 플래그:
FlagPurpose
--mineEnable block production
--miner.etherbaseValidator address (coinbase)

검증자 마이닝 프로세스

검증자 노드가 마이닝을 시작하면 다음과 같은 초기화 절차가 수행됩니다.
  1. 검증자 상태 로드
    • 제네시스 및 최신 블록 상태를 기준으로 GovValidator 컨트랙트에 등록된 검증자 목록을 로드합니다.
    • 현재 노드의 etherbase(coinbase)가 활성 검증자 집합에 포함되어 있는지 확인합니다.
  2. 검증자 키 검증
    • 합의 메시지 서명에 사용되는 키에서 파생된 주소가 etherbase 주소와 일치하는지 검증합니다.
    • 해당 검증자에 대응하는 BLS 공개 키가 GovValidator.blsPublicKeys에 올바르게 등록되어 있는지 확인합니다.
  3. WBFT 합의 엔진 초기화
    • 제네시스에 정의된 Anzeon WBFT 매개변수(epoch length, block period, timeout 등)를 로드합니다.
    • 현재 블록 높이에 해당하는 WBFT 설정을 적용하여 합의 엔진을 초기화합니다.
  4. 검증자 역할 결정
    • 현재 라운드와 proposer 정책에 따라 본 노드가 proposer인지 여부를 판단합니다.
    • proposer로 선택된 경우 블록 제안을 준비합니다.
  5. 합의 메시지 처리 시작
    • 합의 메시지 수신을 위한 네트워크 핸들러를 활성화합니다.
    • 합의 단계별 서명 생성 및 검증 로직을 준비합니다 (BLS 서명 집계 포함).
  6. 블록 생성 및 합의 참여
    • proposer인 경우 WBFTExtra를 포함한 블록을 제안합니다.
    • proposer가 아닌 경우 제안된 블록을 검증하고, 합의 단계에 따라 서명된 메시지를 전파합니다.

가스 팁 정책

StableNet에서는 일반 계정의 가스 팁(우선순위 수수료)을 거버넌스 투표를 통해 관리하며, 해당 값은 GovValidator 컨트랙트에 저장됩니다. 가스 팁 정책은 계정 유형에 따라 다음과 같이 적용됩니다.

인증 계정 (Authorized Account)

인증 계정은 기존 Ethereum과 동일한 방식으로 트랜잭션별 maxPriorityFeePerGas 값을 직접 지정하여 사용합니다.
  • 트랜잭션마다 개별 가스 팁 설정 가능
  • 설정된 maxPriorityFeePerGas 값이 실제 우선순위 수수료로 적용됨
  • 네트워크 혼잡 시 경쟁적 우선순위 지정 가능
  • 거버넌스에서 정의된 고정 가스 팁 정책의 적용을 받지 않음

일반 계정 (Non-Authorized Account)

일반 계정 역시 트랜잭션마다 maxPriorityFeePerGas 값을 설정할 수 있으나, 해당 값은 실제 가스 팁 결정에는 사용되지 않습니다.
  • 트랜잭션에 설정된 maxPriorityFeePerGas 값과 관계없이 거버넌스에서 정의된 고정 가스 팁이 실제 우선순위 수수료로 적용됨
  • 트랜잭션에 설정된 가스 팁 값은 트랜잭션 교체(replacement) 판단을 위한 용도로만 사용됨
  • 고정 가스 팁 미만의 트랜잭션은 트랜잭션 풀에서 필터링됨

가스 팁 업데이트

  • 검증자는 거버넌스 제안을 통해 새로운 고정 가스 팁 값을 제안할 수 있습니다.
  • 제안은 정족수 승인을 거쳐야 하며, 승인 및 실행 시점부터 즉시 적용됩니다.

에포크 전환

StableNet은 에포크(epoch) 단위로 동작하며, 검증자 세트 변경은 에포크 블록에서만 적용됩니다. 주요 사항:
  • 에포크 길이는 anzeon.wbft.epochLength로 구성되며, 기본값은 10블록입니다.
  • 에포크 N 동안 제안 및 승인된 검증자 세트 변경 사항은 에포크 N+1 시작 시점부터 적용됩니다.
  • 첫 번째 에포크의 검증자 세트는 제네시스에 정의된 anzeon.init.validators를 사용합니다.
  • 이후 에포크의 검증자 세트는 GovValidator.validators 배열을 기준으로 로드됩니다.

거버넌스 참여

검증자는 운영 키(operator key)를 사용하여 거버넌스에 참여합니다. 거버넌스는 제안과 투표를 통해 네트워크 설정과 검증자 세트를 관리합니다.

제안 타입

  • ADD_VALIDATOR: 검증자 세트에 새로운 검증자를 추가
  • REMOVE_VALIDATOR: 검증자 세트에서 기존 검증자를 제거
  • SET_GAS_TIP: 필수 가스 팁 값 업데이트
  • CONFIGURE_SYSTEM: 시스템 매개변수 및 설정 변경

투표 프로세스

  • 모든 거버넌스 구성원은 컨트랙트 호출을 통해 제안을 생성할 수 있습니다.
  • 다른 구성원은 vote(proposalId, approve) 호출을 통해 제안에 대해 찬성 또는 반대 투표를 수행합니다.
  • 제안이 정족수에 도달하면 자동으로 실행됩니다.
  • 제안은 설정된 만료 기간(기본값: 7일)이 경과하면 만료됩니다.

노드 모니터링 및 유지 관리

로깅 구성

StableNet 노드는 여러 수준의 로그 상세도를 지원하는 구조화된 로깅 시스템을 사용합니다. 운영 환경에 따라 전역 로그 레벨, 모듈별 로그 레벨, 로그 출력 형식을 구성할 수 있습니다.
# 전역 로그 레벨 설정
gstable --verbosity 3  # 0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=trace

# 모듈별 로그 레벨 설정
gstable --vmodule "consensus/*=5,miner=4,eth/*=3"

# 파일 로그 출력 및 로테이션
gstable --log.file /var/log/gstable/node.log --log.rotate

# 로그 수집을 위한 JSON 포맷 출력
gstable --log.json
모니터링할 주요 로그 모듈:
ModulePurposeImportant Events
consensus/wbftWBFT consensusRound changes, validator proposals, commit messages
minerBlock productionBlock sealing, transaction inclusion, gas tip updates
eth/handlerChain syncPeer connections, block propagation, sync progress
core/blockchainChain processingBlock insertion, reorgs, state root mismatches
eth/downloaderSync progressSync mode, peer selection, download rates

메트릭 및 모니터링

StableNet 노드는 운영 가시성을 확보하기 위해 메트릭 수집 및 외부 모니터링 시스템 연동을 지원합니다. 메트릭 서버를 활성화하거나 InfluxDB와 같은 외부 저장소로 메트릭을 전송할 수 있습니다.
# 메트릭 서버 활성화
gstable --metrics --metrics.addr 0.0.0.0 --metrics.port 6060

# InfluxDB 메트릭 전송 활성화
gstable \
    --metrics.influxdb \
    --metrics.influxdb.endpoint http://influxdb:8086 \
    --metrics.influxdb.database gstable \
    --metrics.influxdb.username monitor \
    --metrics.influxdb.password secret

디스크 공간 관리

StableNet 노드는 블록체인 데이터를 저장하기 위해 상당한 디스크 공간을 사용합니다. 안정적인 운영을 위해 디스크 사용량을 지속적으로 모니터링하고, 필요 시 자동 보호 동작을 구성할 수 있습니다.

최소 여유 디스크 공간

디스크 공간 부족으로 인한 데이터 손상을 방지하기 위해,최소 여유 디스크 공간 기준을 설정할 수 있습니다. 설정된 임계값 미만으로 여유 공간이 감소할 경우노드는 자동으로 종료됩니다.
# 최소 여유 디스크 공간 설정 (MB 단위)
gstable --datadir.minfreedisk 50000  # 여유 공간이 50GB 미만일 경우 종료
노드는 주기적으로 사용 가능한 디스크 공간을 확인하며, 설정된 임계값에 도달할 경우 데이터베이스 손상을 방지하기 위해 정상 종료를 수행합니다.

데이터베이스 크기 모니터링

StableNet 노드는 동기화 모드 및 프루닝 구성에 따라 데이터베이스 사용량이 달라집니다. 아래 표는 일반적인 구성별 데이터베이스 크기와 월별 예상 증가량을 나타냅니다.
ConfigurationApproximate SizeGrowth Rate
Full node (archive)500+ GB~30 GB/month
Full node (pruned)150–200 GB~10 GB/month
Snap sync100–150 GB~8 GB/month
운영 환경에서는 다음 디렉터리의 디스크 사용량을 지속적으로 모니터링해야 합니다.
  • chaindata/: 메인 블록체인 상태 및 블록 데이터베이스
  • ancient/: 오래된 블록 데이터를 저장하는 프리저 디렉터리 (별도 구성 시)
  • blobpool/: Blob 트랜잭션 풀 관련 데이터
  • ethash/: Ethash 합의 사용 시 DAG 파일 저장소

프루닝 및 가비지 컬렉션

해시 스키마 상태 저장소를 사용하는 경우, 프루닝 및 가비지 컬렉션 동작을 구성하여 데이터베이스 크기와 디스크 사용량을 제어할 수 있습니다.
# Archive 모드 (프루닝 비활성화)
gstable --gcmode archive --cache.gc 0

# Full 모드 (프루닝 활성화)
gstable --gcmode full --cache.gc 25  # 캐시의 25%를 GC에 사용
참고: 경로 스키마 데이터베이스는 자동 프루닝을 사용하며 수동 가비지 컬렉션 제어를 지원하지 않습니다.

데이터베이스 유지 관리

상태 스키마 선택

StableNet은 두 가지 상태 저장소 스키마를 지원하며, 노드의 운영 목적에 따라 적절한 스키마를 선택할 수 있습니다.
# Hash-based scheme (traditional)
gstable --state.scheme hash

# Path-based scheme (recommended for new nodes)
gstable --state.scheme path
경로 스키마의 장점:
  • 상태 데이터가 자동으로 프루닝됨
  • 디스크 사용량이 상대적으로 낮음
  • 동기화 성능이 우수함
해시 스키마 장점:
  • 구조가 성숙하고 충분히 검증됨
  • 프루닝 및 가비지 컬렉션을 수동으로 제어 가능
  • 오프라인 프루닝 도구 사용이 필요한 환경에 적합

오프라인 프루닝 복구

해시 스키마를 사용하는 노드는 중단된 프루닝 작업이 감지될 경우 노드 시작 시 자동으로 복구 절차를 수행합니다.
// Automatic recovery at startup
if scheme == rawdb.HashScheme {
    if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb); err != nil {
        log.Error("Failed to recover state", "error", err)
    }
}
이 복구 과정은 노드 시작 중에 자동으로 실행되며, 프루닝이 비정상적으로 중단된 경우 데이터베이스를 일관된 상태로 복원합니다.

체인 복구 및 SetHead

블록체인 상태가 손상되었거나 특정 시점으로 되돌려야 하는 경우 debug_setHead RPC 메서드를 사용하여 체인 헤드를 재설정할 수 있습니다.
# 특정 블록 번호로 되돌리기
gstable attach /data/gstable.ipc --exec 'debug.setHead("0x10000")'  # 블록 65536으로 이동

# 블록 수 기준으로 되돌리기
gstable attach /data/gstable.ipc --exec 'debug.setHead("0x-100")'  # 현재 위치에서 256블록 이전으로 이동
사용 사례:
  • 손상된 블록 데이터로부터 복구
  • 체인 이상 감지 후 이전 상태로 롤백
  • 네트워크 분할 이후 올바른 포크로 체인 재구성
주의: setHead호출은 지정된 지점 이후의 블록과 상태 데이터를 삭제합니다. 실행 전에 반드시 백업이 존재하는지 확인하고, 동작의 영향을 충분히 이해한 상태에서 사용해야 합니다.

노드 업그레이드 절차

노드 업그레이드는 아래 절차에 따라 순차적으로 수행합니다.
  1. 노드 중지
    • 실행 중인 gstable 노드를 정상적으로 종료합니다.
  2. 바이너리 교체
    • 기존 바이너리를 백업한 후, 새 버전의 gstable 바이너리로 교체합니다.
    • 실행 권한 및 경로 설정이 올바른지 확인합니다.
  3. 구성 파일 확인
    • 새로운 버전에서 추가되거나 변경된 설정 항목이 있는지 확인합니다.
    • 기존 구성 파일과의 호환성을 검토하고 필요한 경우 값을 보완합니다.
  4. 노드 재시작
    • 기존과 동일한 옵션으로 노드를 재시작합니다.
    • 검증자 노드의 경우 --mine 옵션이 포함되었는지 확인합니다.
  5. 초기 로그 확인
    • 노드 시작 직후 로그를 확인하여 데이터베이스 마이그레이션, 합의 엔진 초기화, 네트워크 연결 과정에서 오류가 발생하지 않았는지 점검합니다.
업그레이드 전 체크리스트:
  • 변경 사항에 대한 릴리스 노트 검토
  • 데이터베이스 백업 (chaindata/ 디렉터리)
  • 중요하지 않은 노드에서 업그레이드 사전 테스트
  • 검증자 노드의 경우 계획된 다운타임을 피어에 사전 공지
업그레이드 후 검증:
# 노드 버전 확인
gstable version

# 데이터베이스 버전 확인
gstable --datadir /data version-check

# 동기화 상태 확인
gstable attach --exec 'eth.syncing'

# 피어 연결 상태 확인
gstable attach --exec 'admin.peers.length'

# 검증자 노드의 경우 마이닝 상태 확인
gstable attach --exec 'eth.mining'

비정상 종료 감지

StableNet 노드는 이전 실행에서의 비정상 종료 여부를 데이터베이스 상태를 기반으로 간접적으로 판단하여 노드 시작 시 데이터베이스 복구 메커니즘이 자동으로 수행됩니다.

비정상 종료 처리 방식

  • 노드 시작 시 LevelDB의 WAL(Write-Ahead Log)을 통해 이전 실행에서 미완료된 쓰기 작업을 자동으로 복구합니다.
  • 상태 데이터베이스, 스냅샷, freezer(ancient) 데이터 간의 정합성을 검사하고, 필요 시 내부 복구 로직을 수행합니다.
  • 데이터베이스가 일관된 상태로 복구되지 않을 경우 동기화 또는 상태 재구성이 트리거될 수 있습니다.
비정상 종료 후 수동 복구: 자동 복구 이후에도 데이터베이스 이상이 의심되는 경우, 다음 명령을 사용하여 수동 점검 및 복구 작업을 수행할 수 있습니다.
# 데이터베이스 무결성 확인
gstable --datadir /data verify-db

# 필요한 경우 인덱스 재구성
gstable --datadir /data rebuild-indexes

부트노드 운영

StableNet 네트워크의 피어 발견을 위해 전용 부트노드를 실행할 수 있습니다.
# 부트노드 키 생성
bootnode --genkey=boot.key

# 부트노드 실행
bootnode \
    --nodekey=boot.key \
    --addr=:30303 \
    --netrestrict=0.0.0.0/0 \
    --verbosity=3

# enode URL 출력
bootnode --nodekey=boot.key --writeaddress
부트노드는 전체 노드를 실행하지 않고 피어 발견을 위한 경량 서비스만 제공하며, 클라이언트는 다음과 같이 부트노드를 지정하여 사용하도록 구성할 수 있습니다.
gstable --bootnodes enode://[nodekey-pubkey]@[ip]:30303

네트워크 모니터링 대시보드

검증자 노드의 안정적인 운영을 위해 다음과 같은 모니터링 지표를 대시보드에 구성하는 것을 권장합니다. 검증자용 주요 성능 지표(KPI)
MetricTargetAlert Threshold
Block production rate~1 block/second< 0.9 blocks/sec
Missed blocks0%> 1%
Peer count10–50< 5 peers
Sync delay< 2 blocks> 10 blocks behind
Disk free space> 100 GB< 50 GB
Memory usage< 80%> 90%
CPU usage< 50%> 80% sustained