> ## 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 블록체인의 **블록 및 헤더 구조**, **인코딩 방식**, **해시 계산**, **머클 루트 구성**, 그리고 **WBFT 합의에 특화된 Extra 데이터 구조**를 설명합니다.\
블록이 어떻게 구성되고 검증되며, 합의 과정에서 어떤 데이터가 헤더에 포함되는지를 중심으로 다룹니다.

관련 문서:

* 트랜잭션 데이터 구조: [트랜잭션 유형 및 인코딩](/ko/core-architecture/3.5-transaction-types-and-encoding)
* 블록 검증 및 체인 삽입: [블록체인 관리](/ko/core-architecture/3.2-blockchain-management)
* 블록 생성 프로세스: [블록 생성](/ko/consensus-and-block-production/4.2-block-production-and-mining)

## 블록 구조 개요

블록은 메타데이터를 포함하는 **헤더**, 트랜잭션을 포함하는 **본문**, 선택적 **인출(withdrawals)** 목록과 **엉클(uncles)** 목록으로 구성됩니다.\
StableNet(WBFT 기반)에서는 엉클을 사용하지 않으며, 항상 비어 있습니다.

### Block 타입

`Block` 구조체(`core/types/block.go`)의 주요 필드:

| 필드             | 타입             | 설명                       |
| -------------- | -------------- | ------------------------ |
| `header`       | `*Header`      | 메타데이터 및 머클 루트를 포함한 블록 헤더 |
| `transactions` | `Transactions` | 블록에 포함된 트랜잭션 목록          |
| `uncles`       | `[]*Header`    | 엉클 블록 헤더 (사용안함)          |
| `withdrawals`  | `Withdrawals`  | 인출 목록 (Shanghai 이후 선택적)  |
| `hash`         | `atomic.Value` | 캐시된 블록 해시                |
| `size`         | `atomic.Value` | 캐시된 RLP 인코딩 크기           |

블록은 생성 이후 **불변(immutable)** 객체로 취급됩니다. 내부 데이터는 생성 시 복사되며, 해시와 크기 캐시는 이후 변경되지 않습니다.

## 헤더 구조

`Header`는 블록의 핵심 메타데이터로, 블록 내용과 실행 결과에 대한 암호학적 커밋을 포함합니다.

### 핵심 헤더 필드

| 필드            | 타입               | 설명                                       |
| ------------- | ---------------- | ---------------------------------------- |
| `ParentHash`  | `common.Hash`    | 부모 블록 헤더 해시                              |
| `UncleHash`   | `common.Hash`    | 엉클 목록 해시 (StableNet에서는 `EmptyUncleHash`) |
| `Coinbase`    | `common.Address` | 블록 수수료 수령 주소(검증자 주소)                     |
| `Root`        | `common.Hash`    | 블록 실행 후 상태 trie 루트                       |
| `TxHash`      | `common.Hash`    | 트랜잭션 머클 루트                               |
| `ReceiptHash` | `common.Hash`    | 영수증 머클 루트                                |
| `Bloom`       | `Bloom`          | 로그 블룸 필터                                 |
| `Difficulty`  | `*big.Int`       | 블록 난이도 (WBFT: 항상 1)                      |
| `Number`      | `*big.Int`       | 블록 번호                                    |
| `GasLimit`    | `uint64`         | 블록 가스 한도                                 |
| `GasUsed`     | `uint64`         | 사용된 총 가스                                 |
| `Time`        | `uint64`         | 블록 생성 시각                                 |
| `Extra`       | `[]byte`         | WBFT 합의 데이터 (RLP 인코딩)                    |
| `MixDigest`   | `common.Hash`    | PoW 필드 (WBFT에서는 사용되지 않음)                 |
| `Nonce`       | `BlockNonce`     | PoW 필드 (WBFT에서는 사용되지 않음)                 |

**StableNet 특이사항:**

* `Difficulty`는 항상 1로 설정되어 WBFT 블록임을 식별합니다
* `Coinbase`는 검증자의 합의 서명 주소이며 운영자 주소와 다를 수 있습니다
* `Extra`에는 WBFT 합의 라운드 정보, 집계 서명, 가스 팁, 에포크 정보가 포함됩니다
* `GasLimit`은 체인 파라미터에 의해 고정된 값으로 운영됩니다

### 포크별 선택적 필드

다음 필드들은 특정 포크 이후에만 존재하며, nil이 아닌 경우에만 RLP 인코딩에 포함됩니다.

| 필드                 | EIP      | 포크       | 설명          |
| ------------------ | -------- | -------- | ----------- |
| `BaseFee`          | EIP-1559 | London   | 블록 기본 수수료   |
| `WithdrawalsHash`  | EIP-4895 | Shanghai | 인출 머클 루트    |
| `BlobGasUsed`      | EIP-4844 | Cancun   | blob 가스 사용량 |
| `ExcessBlobGas`    | EIP-4844 | Cancun   | 초과 blob 가스  |
| `ParentBeaconRoot` | EIP-4788 | Cancun   | 비콘 체인 부모 루트 |

## 본문 구조

블록 본문은 실제 실행 데이터로 구성됩니다.

* **Transactions**: 트랜잭션 목록
* **Uncles**: 엉클 헤더 목록 (사용 안함)
* **Withdrawals**: 인출 목록 (해당 포크 이후)

## RLP 인코딩

블록과 헤더는 모두 Recursive Length Prefix(RLP) 인코딩을 사용합니다.

### 블록 인코딩

블록은 다음과 같은 RLP 리스트로 인코딩됩니다.

```
[header, transactions, uncles, withdrawals]
```

Shanghai 이전 블록에서는 `withdrawals` 항목이 존재하지 않습니다.

### 헤더 인코딩

헤더는 정의된 필드 순서대로 RLP 인코딩되며, 선택적 필드는 값이 존재할 때만 포함됩니다.

## 블록 및 헤더 해싱

### 표준 해싱

블록 해시는 **헤더만**을 기준으로 계산됩니다.

```
block_hash = keccak256(rlp(header))
```

계산된 해시는 캐시되어 반복 계산을 방지합니다.

### WBFT 전용 헤더 해싱

WBFT에서는 합의 서명이 헤더의 `Extra` 필드에 포함되므로, **서명 대상 해시 계산 시 서명 자체를 제외**해야 합니다.

이를 위해 `WBFTFilteredHeader()`가 사용됩니다.

* `PreparedSeal`, `CommittedSeal` 제거
* 라운드 번호, 에포크 정보, 가스 팁은 유지
* `Difficulty == 1`인 경우에만 적용

이로 인해 서명과 해시 간 순환 의존성이 발생하지 않습니다.

### 라운드 포함 해시

WBFT 합의 라운드에서는 라운드 번호를 포함한 별도의 해시를 사용하여, 동일 블록 제안이라도 라운드별로 다른 서명 대상이 됩니다.

## WBFT Extra 데이터 구조

WBFT 합의 데이터는 헤더의 `Extra` 필드에 RLP 인코딩되어 저장됩니다.

### WBFTExtra 구조

| 필드                  | 타입                    | 설명                       |
| ------------------- | --------------------- | ------------------------ |
| `VanityData`        | `[]byte`              | vanity 데이터               |
| `RandaoReveal`      | `[]byte`              | 랜덤성용 BLS 서명              |
| `PrevRound`         | `uint32`              | 이전 합의 라운드                |
| `PrevPreparedSeal`  | `*WBFTAggregatedSeal` | 이전 prepare 집계 서명         |
| `PrevCommittedSeal` | `*WBFTAggregatedSeal` | 이전 commit 집계 서명          |
| `Round`             | `uint32`              | 현재 합의 라운드                |
| `PreparedSeal`      | `*WBFTAggregatedSeal` | 현재 prepare 집계 서명         |
| `CommittedSeal`     | `*WBFTAggregatedSeal` | 현재 commit 집계 서명          |
| `GasTip`            | `*big.Int`            | 거버넌스가 결정한 가스 팁           |
| `EpochInfo`         | `*EpochInfo`          | 다음 에포크 정보 (에포크 블록에서만 포함) |

nil인 필드는 RLP 인코딩에서 제외됩니다.

### WBFTAggregatedSeal

여러 검증자의 BLS 서명을 하나로 집계한 구조입니다.

| 필드          | 타입          | 설명          |
| ----------- | ----------- | ----------- |
| `Sealers`   | `SealerSet` | 서명한 검증자 비트맵 |
| `Signature` | `[]byte`    | 집계된 BLS 서명  |

### EpochInfo

에포크 블록에만 포함되며, 다음 에포크의 검증자 세트를 정의합니다.

| 필드              | 타입             | 설명           |
| --------------- | -------------- | ------------ |
| `Candidates`    | `[]*Candidate` | 모든 검증자 후보    |
| `Validators`    | `[]uint32`     | 활성 검증자 인덱스   |
| `BLSPublicKeys` | `[][]byte`     | 검증자 BLS 공개 키 |

## 머클 루트 계산

### TxHash

트랜잭션 목록을 Merkle Patricia Trie로 구성하여 계산됩니다.\
빈 목록은 `EmptyTxsHash`를 사용합니다.

### ReceiptHash

영수증 목록으로 동일한 방식으로 계산되며, 블룸 필터는 영수증에서 파생됩니다.

### UncleHash

엉클 헤더 목록의 해시이며, StableNet에서는 항상 `EmptyUncleHash`입니다.

### WithdrawalsHash

Shanghai 이후 블록에서 인출 목록에 대해 계산됩니다.

## 블록 구성

### NewBlock 함수

`NewBlock()`은 다음 절차로 블록을 생성합니다.

1. 헤더 복사
2. 트랜잭션 머클 루트 계산
3. 영수증 루트 및 블룸 계산
4. 엉클 해시 계산
5. 본문 데이터 결합

WBFT 블록의 경우:

* `Difficulty = 1`
* `Extra`에 WBFTExtra 인코딩
* 에포크 블록에서만 `EpochInfo` 포함

Shanghai 이후에는 `NewBlockWithWithdrawals()`를 사용합니다.

## 헤더 무결성 검사

`Header.SanityCheck()`는 비정상 입력으로 인한 DoS를 방지합니다.

| 필드           | 제한         |
| ------------ | ---------- |
| `Number`     | 64비트 범위    |
| `Difficulty` | 합리적 비트 길이  |
| `Extra`      | 최대 크기 제한   |
| `BaseFee`    | uint256 범위 |

## 블록 크기 계산

블록 크기는 RLP 인코딩된 전체 크기이며, `Block.Size()`로 조회합니다.\
Blob 트랜잭션이 포함된 경우 사이드카 데이터도 크기에 포함됩니다.
