sayu.day

Celestia 데이터 구조와 저장 전략: ODS, EDS, ODSQ4

Celestia에서 블록 데이터는 곧바로 EDS(Extended Data Square)가 되지 않습니다. 트랜잭션 배열은 먼저 ODS(Original Data Square)로 정리된 뒤, 2차원 Reed-Solomon 확장을 거쳐 EDS가 됩니다. 이 글은 ODS 생성 파이프라인, EDS의 Q1~Q4 구조, 실제 저장 용량 계산과 윈도우별 저장 전략, 그리고 이를 구현하는 store/file 패키지 구조까지 데이터 구조와 스토리지 관점에서 정리합니다. 검증(DAS·NMT) 관점은 자매 글 Celestia 데이터 가용성 검증: 해시의 한계에서 DAS와 NMT까지에서 다룹니다.

트랜잭션 배열을 ODS로 변환하는 파이프라인

변환은 다섯 단계로 이루어집니다.

  1. 트랜잭션 분류
  2. Share 분할
  3. 네임스페이스 정렬
  4. 패딩 적용
  5. 정사각형 배치(ODS 생성)

1) 트랜잭션 분류

일반 트랜잭션과 PFB(PayForBlob)를 분리해 처리합니다. blob 데이터는 별도 경로로 배치됩니다.

2) Share 분할

  • Compact share: 일반 트랜잭션/PFB
  • Sparse share: blob

데이터 타입별로 인코딩 단위를 분리해 배치 효율을 높입니다.

3) 네임스페이스 정렬

Celestia는 네임스페이스 기반 검증을 지원하므로, share를 배치하는 단계에서 정렬 규칙이 중요합니다. 이 정렬 규칙이 뒤에서 다룰 NMT 기반 증명의 전제가 됩니다.

4) 패딩과 square size

최종 ODS는 2의 거듭제곱 크기의 정사각형이 되어야 하며, 부족한 영역은 정해진 규칙에 따라 패딩합니다.

실무 포인트

  1. max square size를 네트워크·메모리 한계와 함께 관리합니다.
  2. 패딩 비율이 높으면 데이터 배치 정책을 재검토합니다.
  3. 네임스페이스 정렬 규칙 변경은 하위 호환 영향을 검토해야 합니다.

ODS 생성은 단순한 포맷 변환이 아니라, 이후 DAS 샘플링과 증명 효율을 결정하는 전처리 단계입니다.

EDS: 2D Reed-Solomon 확장과 Q1~Q4 구조

EDS는 Celestia 데이터 가용성 설계의 중심입니다. ODS를 2차원 Reed-Solomon으로 확장해, 일부가 누락되어도 복구할 수 있는 구조를 만듭니다.

EDS는 네 개의 사분면으로 구성됩니다.

  • Q1: 원본 데이터(ODS)
  • Q2: 행 패리티
  • Q3: 열 패리티
  • Q4: 행+열 패리티

이 구조 덕분에 샘플링과 복구가 동시에 가능해집니다.

왜 2D 인코딩인가

  • 단순 복제보다 저장 효율이 높습니다.
  • 누락 패턴이 생겨도 복구 성공 가능성이 커집니다.
  • DAS와 결합할 때 탐지와 복구의 균형이 좋습니다.

저장 용량 계산과 윈도우별 저장 전략

전체 EDS 용량(이론값)

전체 EDS는 원본 데이터의 4배 크기를 차지합니다. Q1(원본, 100%), Q2(행 패리티, 100%), Q3(열 패리티, 100%), Q4(행+열 패리티, 100%)를 모두 저장한다면 원본 크기의 4배가 필요합니다.

실제 저장 전략

Celestia는 실제로 모든 사분면을 항상 저장하지 않고, 다음 두 가지 전략을 상황에 맞춰 사용합니다.

  1. ODS만 저장(원본 데이터만): 원본 데이터의 1배 용량을 사용합니다. 오래된 블록이나 아카이브 목적의 저장에 쓰이며, 필요하면 나머지 사분면(Q2, Q3, Q4)은 계산으로 복구할 수 있습니다.
  2. ODSQ4 저장(원본 + Q4 사분면): 원본 데이터의 2배 용량을 사용합니다. 가용성 윈도우 내의 최근 블록에 사용되며, 특정 접근 패턴에서 계산 효율성이 향상됩니다.

실제 코드에서는 가용성 윈도우 여부에 따라 저장 전략을 분기합니다.

// 가용성 윈도우 내의 블록은 ODS와 Q4 모두 저장 (원본의 2배)
if availability.IsWithinWindow(eh.Time(), availability.StorageWindow) {
    err = store.PutODSQ4(ctx, eh.DAH, eh.Height(), eds)
} else {
    // 그 외 블록은 ODS만 저장 (원본의 1배)
    err = store.PutODS(ctx, eh.DAH, eh.Height(), eds)
}

저장 공간을 최적화하는 이유

  1. 디스크 공간 효율성: 모든 블록의 모든 사분면을 저장하는 것은 비효율적이며, 대부분의 경우 원본 데이터만으로도 충분합니다.
  2. 계산 비용과 저장 비용의 균형: Q2와 Q3는 Q1과 Q4로부터 계산할 수 있으므로 필요할 때만 계산하고, 가장 자주 접근하는 최근 블록에만 Q4를 함께 저장해 계산 비용을 절약합니다.
  3. 가용성과 검증의 균형: 데이터 가용성 검증은 최근 블록에 대해 더 중요하므로, 최근 블록은 더 많은 공간(ODS+Q4)을 쓰고 오래된 블록은 공간 효율성(ODS만)을 우선합니다.

결론적으로 Celestia는 원본 데이터의 약 1~2배 정도의 저장 공간을 사용하면서도, 데이터 가용성 검증과 복구 기능을 효율적으로 제공합니다. 이 윈도우 경계와 인코딩 실패를 어떻게 다루는지가 실제 운영에서 중요합니다.

체크리스트

  1. 가용성 윈도우 경계 정책을 명확히 정의합니다.
  2. EDS 생성 실패 원인을 인코딩/입력 데이터로 분리해 로깅합니다.
  3. 복구 경로 테스트를 정기적으로 실행합니다.

celestia-node의 store/file 패키지

store/file 패키지는 EDS 저장을 디스크 친화적으로 다루는 핵심 레이어입니다. 핵심 아이디어는 "모든 것을 항상 저장하지 않고, 필요한 형태만 저장한다"는 것입니다.

핵심 데이터 단위

  • ODS: 원본 데이터 사각형(Q1)
  • EDS: ODS를 확장한 데이터 사각형
  • Q4: 복구/샘플링 최적화에 쓰이는 사분면

저장 전략

  1. ODS 저장: 저장량이 작습니다(대략 EDS 대비 1/4). 오래된 블록이나 아카이브에 유리합니다.
  2. ODSQ4 저장: ODS + Q4를 저장합니다(대략 EDS 대비 1/2). 최근 블록의 샘플링/복구에서 계산 부담을 줄입니다.

시간축에 따라 저장 정책을 다르게 가져가 디스크와 CPU를 균형화하는 방식입니다.

코드 구조의 주요 타입

  • ODS: 기본 접근자/스트리머 구현
  • q4: Q4 전용 파일 접근
  • ODSQ4: ODS + Q4 조합 접근자
  • headerV0: 파일 포맷 메타데이터
  • codecCache: Reed-Solomon 인코더 캐시

운영 포인트

  1. 가용성 윈도우 기준으로 ODS/ODSQ4 정책을 분리합니다.
  2. Q4는 lazy loading으로 시작 지연을 최소화합니다.
  3. 파일 크기/해시 검증 실패는 즉시 격리합니다.
  4. 인코더 캐시 hit율을 모니터링해 CPU 급등을 방지합니다.

이 패키지는 단순 파일 저장소가 아니라, DAS와 복구 비용을 운영 가능한 수준으로 맞추기 위한 스토리지 전략 계층입니다.

정리

트랜잭션 배열은 분류·share 분할·네임스페이스 정렬·패딩을 거쳐 ODS가 되고, ODS는 2D Reed-Solomon 확장을 통해 Q1~Q4 구조의 EDS가 됩니다. 이 구조가 4배의 이론적 저장 비용을 만들지만, Celestia는 가용성 윈도우를 기준으로 최근 블록은 ODSQ4(2배), 오래된 블록은 ODS(1배)만 저장해 실제 비용을 크게 낮춥니다. store/file 패키지는 이 전략을 lazy loading, 인코더 캐시, 즉시 격리 같은 구체적인 장치로 구현한 계층이며, 여기서 확보한 데이터 구조는 자매 글에서 다루는 DAS·NMT 기반 검증의 토대가 됩니다.