> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stablenet.network/llms.txt
> Use this file to discover all available pages before exploring further.

# 캐싱 및 스냅샷

## 목적 및 범위

이 문서는 StableNet에서 상태 액세스를 최적화하는 다층 캐싱 메커니즘과 스냅샷 시스템을 설명합니다.\
캐싱 아키텍처는 자주 액세스되는 데이터에 대한 메모리 내 LRU 캐시부터, trie 순회 없이 계정 및 저장소 데이터에 대한 빠른 액세스를 제공하는 상태 스냅샷 시스템까지 확장됩니다.

기본 Merkle Patricia Trie 데이터 구조 및 데이터베이스 인터페이스에 대한 정보는 [데이터베이스 레이어 및 Merkle Patricia Trie](/ko/storage-architecture/9.1-database-layer-and-merkle-patricia-tries)을 참조하세요.\
과거 데이터 관리 및 아카이브 전략은 [고대 저장소 및 데이터 라이프사이클](/ko/storage-architecture/9.3-ancient-store-and-data-lifecycle)을 참조하세요.

## StateDB 캐싱 아키텍처

StateDB는 모든 블록체인 상태에 대한 최상위 캐싱 레이어로 동작하며, 트랜잭션 실행 중 반복적이고 비용이 큰 trie 및 데이터베이스 접근을 최소화하기 위해 여러 메모리 내 데이터 구조를 유지합니다.

### 계정 및 저장소 캐시 맵

StateDB는 블록 실행 중 상태 변화를 추적하기 위해 다음과 같은 캐시 맵을 유지합니다:

| Cache Map              | Type                                        | Purpose                    |
| ---------------------- | ------------------------------------------- | -------------------------- |
| `stateObjects`         | `map[common.Address]*stateObject`           | 실행 중 수정되는 라이브 계정 객체        |
| `accounts`             | `map[common.Hash][]byte`                    | 커밋을 위한 slim RLP 인코딩 계정 데이터 |
| `storages`             | `map[common.Hash]map[common.Hash][]byte`    | 커밋 대상 저장소 슬롯 변경사항          |
| `accountsOrigin`       | `map[common.Address][]byte`                 | 변경 전 계정 상태(diff 계산용)       |
| `storagesOrigin`       | `map[common.Address]map[common.Hash][]byte` | 변경 전 저장소 상태(diff 계산용)      |
| `stateObjectsPending`  | `map[common.Address]struct{}`               | finalise 완료, trie 반영 전 객체  |
| `stateObjectsDirty`    | `map[common.Address]struct{}`               | 현재 실행에서 수정된 객체             |
| `stateObjectsDestruct` | `map[common.Address]*types.StateAccount`    | 블록 내에서 selfdestruct된 계정    |

`stateObjects`는 현재 블록 실행 동안 유지되는 **라이브 상태 객체 캐시**입니다.\
각 계정은 최초 접근 시 한 번만 로드되며, 이후에는 동일 객체가 재사용됩니다.

**계정 로딩 흐름 요약:**

1. `stateObjects` 캐시 확인
2. 미존재 시 스냅샷에서 로드 시도
3. 스냅샷 미사용 또는 미존재 시 trie 조회
4. `stateObject` 래퍼 생성
5. `stateObjects`에 캐시 후 반환

### 상태 객체 저장소 캐싱

각 `stateObject`는 저장소 슬롯 접근을 위해 **3단계 저장소 캐시**를 유지합니다.

저장소 단계별 역할:

* **dirtyStorage**\
  현재 트랜잭션에서 변경된 슬롯. 트랜잭션 종료 시 초기화됩니다.
* **pendingStorage**\
  트랜잭션이 종료되어 확정되었지만 아직 trie에 커밋되지 않은 변경사항.
* **originStorage**\
  스냅샷 또는 trie에서 로드된 기준 상태.

이 구조는 다음을 보장합니다:

* 트랜잭션 단위 롤백 가능
* 동일 슬롯에 대한 중복 trie 쓰기 방지
* 변경사항의 정확한 diff 계산

## 상태 스냅샷 시스템

스냅샷 시스템은 Merkle Patricia Trie를 직접 순회하지 않고도 계정 및 저장소 데이터를 조회할 수 있는 **평면(flat) 상태 표현**을 제공합니다.\
이는 snap 동기화와 일반 블록 실행 성능 모두에 핵심적인 역할을 합니다.

### 스냅샷 아키텍처

스냅샷 시스템은 다음 세 구성 요소로 이루어집니다:

1. **디스크 레이어**\
   특정 블록 높이의 영구 스냅샷으로,\
   계정 해시 → 계정 데이터, 저장소 해시 → 저장소 값의 평면 매핑을 보유합니다.
2. **Diff 레이어**\
   각 블록 단위의 상태 변경사항을 메모리에 체인 형태로 보관합니다.\
   변경된 계정과 저장소 슬롯만 저장합니다.
3. **스냅샷 트리**\
   상태 루트별 스냅샷을 관리하며 `Snapshot(root)` 인터페이스를 제공합니다.

### 스냅샷 기반 상태 액세스

스냅샷이 활성화되면 StateDB는 다음 순서로 상태를 조회합니다:

* 계정 조회: `snap.Account(hash)`
* 저장소 조회: `snap.Storage(addrHash, slotHash)`
* 미스 시에만 trie로 폴백

이 방식의 성능적 이점:

* trie 노드 디코딩 없음
* 해시 검증 없음
* 평면 구조 직접 접근
* 일반적으로 계정 조회 기준 **10\~100배 속도 향상**

## Trie 프리페처

Trie 프리페처는 트랜잭션 실행 중 접근 가능성이 높은 trie 노드를 백그라운드에서 선제적으로 로드하여 커밋 지연을 최소화합니다.

작동 흐름:

1. 블록 실행 시작 시 `StartPrefetcher()` 호출
2. `finalise()` 단계에서 수정된 저장소 슬롯 정보 수집
3. 워커 고루틴이 해당 경로의 trie 노드를 비동기 로딩
4. `IntermediateRoot()` 또는 커밋 시 캐시된 trie 재사용
5. 블록 종료 시 `StopPrefetcher()`로 정리

프리페처는 **실행과 병렬로 동작**하며, 트랜잭션 처리 지연을 증가시키지 않습니다.

## 저널 및 스냅샷 롤백

StateDB는 저널 기반 변경 추적을 통해 트랜잭션 실행 중 언제든 이전 상태로 롤백할 수 있습니다.

각 상태 변경은 `journalEntry`로 기록되며, 대표적인 항목은 다음과 같습니다:

* 잔액 변경
* nonce 변경
* 코드 변경
* 저장소 변경
* selfdestruct
* 계정 생성

`Snapshot()` 호출 시 현재 저널 길이가 저장되고, `RevertToSnapshot()` 호출 시 저널을 역순으로 재생하여 상태를 복원합니다.

이 메커니즘은 다음에 필수적입니다:

* EVM REVERT
* Out-of-gas 처리
* 예외 발생 시 상태 복구
* 추측 실행

## 상태 커밋 및 캐시 관리

상태 커밋은 다음 3단계로 진행됩니다.

### 단계 1: Finalise

* dirty 객체 정리
* selfdestruct 처리
* dirtyStorage → pendingStorage 이동
* 저널 초기화

### 단계 2: IntermediateRoot

* 모든 pending 객체의 저장소 trie 해싱
* 계정 trie 업데이트
* 중간 상태 루트 계산

### 단계 3: Commit

* 모든 저장소 trie 커밋
* 계정 trie 커밋
* 변경된 노드에 대한 `NodeSet` 생성
* `triedb.Update()`로 일괄 기록

## 빠른 저장소 삭제

대형 저장소 trie 삭제 시 전체 trie 순회는 비효율적입니다.\
StateDB는 스냅샷을 활용한 **빠른 삭제 경로**를 제공합니다.

작동 방식:

1. 스냅샷 기반 저장소 슬롯 평면 반복
2. 메모리 내 StackTrie 구성
3. 각 노드에 대한 삭제 마커 생성
4. 크기 제한 초과 시 기존 느린 경로로 폴백
5. 삭제 마커를 포함한 `NodeSet` 반환

이 방식은 디스크 접근 없이 순수 메모리 연산으로 동작합니다.

## StateDB 복사 의미론

`StateDB.Copy()`는 병렬 실행 및 추측 상태 생성을 위해 사용됩니다.

**공유(읽기 전용):**

* 데이터베이스 인터페이스
* 스냅샷 트리
* 기본 trie

**딥 복사(쓰기 가능):**

* 상태 객체 맵
* 변경 추적 맵
* journal
* logs, preimages
* accessList, transientStorage

이를 통해:

* 병렬 트랜잭션 실행 가능
* 메모리 중복 최소화
* 상태 간 완전한 격리 보장

## 성능 메트릭 및 계측

StateDB는 상태 처리 전반에 대해 상세한 메트릭을 수집합니다.

측정 항목 예:

* 계정/저장소 읽기 시간
* trie 해싱 시간
* 커밋 시간
* 스냅샷 접근 시간
* 업데이트/삭제 개수

이 메트릭은 다음에 사용됩니다:

* 병목 지점 식별
* 캐시 적중률 분석
* 스냅샷 효과 검증
* 성능 회귀 탐지

## 정리 및 캐시 제거

### 스냅샷 기반 정리

* 오래된 diff 레이어 병합
* 디스크 레이어 최신화
* 불필요한 trie 노드 제거 가능

### 캐시 제거 전략

* trie 노드 LRU 캐시
* clean / dirty 캐시 분리
* dirty 노드는 커밋 후 제거

### 메모리 관리

* 트랜잭션 종료 시 저널 정리
* pending 객체 초기화
* 프리페처 종료
* StateDB 복사 시 구조 공유

이러한 메커니즘은 장기 실행 환경에서도 메모리 사용량이 제한되도록 보장합니다.
