mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
EIPs: add eip-4844.md
This commit is contained in:
parent
1581b6aabc
commit
cbea2d126f
1 changed files with 226 additions and 0 deletions
226
EIPs/eip-4844.md
Normal file
226
EIPs/eip-4844.md
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
# EIP-4844: Shard Blob Transactions
|
||||
샤드 블롭 트랜잭션은 이더리움의 데이터 가용성을 간단하고, 향후 호환가능한 방식으로 확장합니다.
|
||||
|
||||
## Abstract
|
||||
EVM execution에서는 접근할 수 없는 대량의 데이터를 가지고 있는 “Blob-carrying transactions”이라는 새로운 트랜잭션 포맷의 도입했습니다. 이 포맷은 full sharding 에서 완전히 호환가능한 방식으로 고안되었습니다.
|
||||
|
||||
## Motivation
|
||||
롤업은 단기, 중기적 그리고 장기적으로도 이더리움을 위한 유일하게 무신뢰 확장성 솔루션입니다. L1의 트랜잭션 수수료는 몇달간 매우 높았고, 생태계 전반의 롤업 전환을 촉진하는데 필요한 모든 조치를 취하는 것이 시급합니다. 롤업은 많은 이더리움 사용자의 수수료를 크게 절감합니다. Optimism과 Arbitrum은 이더리움 L1보다 3~8배 낮은 수수료를 제공하며, 더 많은 데이터 압축과 서명을 포함하지 않아도 되는 ZK롤업에는 40~100배 낮은 수수료를 제공합니다.
|
||||
|
||||
그러나 이러한 수수료조차도 많은 사용자들에게 비싸게 여겨집니다. 롤업 자체의 장기적인 문제의 해결책은 항상 데이터샤딩이었습니다. 이는 롤업이 사용할 수 있는 체인에 전용 데이터 공간 블록당 16MB를 추가하는 것입니다. 그러나 데이터 샤딩은 구현 및 배포하는데 상당한 시간이 필요합니다.
|
||||
|
||||
이 EIP는 샤딩에 사용되지만 실제로 해당 트랜잭션을 샤딩하지는 않는 트랜잭션 형태를 구현함으로써 그 시점까지 임시방편 솔루션을 제공합니다. 대신, 이 형식의 거래 데이터는 단순히 비콘 체인의 일부이며 모든 합의 노드에 의해 완전히 다운로드 됩니다.(그러나 상대적으로 짧은 지연 후에 삭제될 수 있음). fully 데이터 샤딩과 비교할때 이 EIP가 포함할 수 있는 트랜잭션 수의 한도는 감소되어 0.375MB를 목표로 하고, 최대 0.75MB의 리밋을 가집니다.
|
||||
|
||||
## Theoretical explain
|
||||
### 주요 변경사항 및 목표
|
||||
- blob으로 L2 롤업 데이터 게시비용 대폭 감소
|
||||
- Blob-carrying 트랜잭션 유형을 도입
|
||||
=> 더 저렴하게 L2롤업 데이터를 메인넷에 게시
|
||||
- 블록당 포함된 블롭의 크기와 수를 제한하여, 이더리움 노드 계산 및 저장 요구사항이 급격하게 증가하지 않도록 하여 분산화 유지
|
||||
|
||||
### 왜 더 저렴한가?
|
||||
Blob 데이터는 EVM에 접근할 수 없기 떄문, blob 데이터에 대한 참조만 EVM에 액세스 할 수 있음
|
||||
|
||||
### 트랜잭션
|
||||
기존 이더리움은 표준 이더리움 트랜잭션으로 채워짐
|
||||
이 업데이트 이후 표준 이더리움 트랜잭션 + blob carrying 트랜잭션의 조합
|
||||
|
||||
### 블롭 구조
|
||||

|
||||
블롭은 블록과 나란히 달리는 ‘사이드카’ 로 상상가능함
|
||||
블롭 자체는 블록에 들어가지 않지만, 관련 참조만 들어감.(각 블롭에 고유하고, 각 블롭을 블롭 운반 트랜잭션에 연결할 수 있는 참조)
|
||||
|
||||
각 블롭에 포함된 L2 트랜잭션은 EVM에서 실행될 수 없다. 단 이더리움의 consensus layer에서 4096에포크 혹은 18일 동안만 순환, 저장됨
|
||||
|
||||
### 블롭 마켓
|
||||
블록당 0~6개의 블롭 등록, 3개를 목표로함
|
||||
블록에 3개이상의 블롭이 연결되면 블롭의 가격이 더 비싸짐, 주어진 블록에 블롭이 3개 미만이면 블롭 가격은 더 저렴해짐
|
||||
|
||||
### 블롭 만료
|
||||
4096에포크 18일 동안 사용가능
|
||||
만료 후에는 블롭 내의 데이터를 consensus client에서 검색할 수 없음. 이전 존재에 대한 증거만 KZG형태로 메인넷에 남음
|
||||
|
||||
### 블롭 크기
|
||||
블록에 연결된 각 블롭은 128Kb의 임시 데이터를 보유, 그러나 블롭이 완전히 채워지지 않을 수 있음, 그러나 이때도 블롭의 크기는 항상 128kb
|
||||

|
||||
현재 블록크기 1.875Mb => 블롭 6개 연결시 0.75Mb 추가
|
||||
=> 블록 크기 40% 늘릴 수 있음
|
||||
|
||||
|
||||
## Specification
|
||||
### 블롭 트랜잭션
|
||||
EIP-4844에서는 EIP-2718의 새로운 타입 “blob transaction”을 제안하였습니다.
|
||||
Blob transaction의 TransactionPayloadBody:
|
||||
[chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to, value, data, access_list, max_fee_per_blob_gas, blob_versioned_hashes, y_parity, r, s]
|
||||
|
||||
새롭게 추가된 항목: max_fee_per_blob_gas, blob_versioned_hashes(kzg_to_versioned_hash의 해시 결과 리스트)
|
||||
EIP-1559를 계승한 항목: Chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, value, data, access_list
|
||||
변경된 항목: to(nil이 되어서는 안되며, 반드시 20byte의 address) – blob transaction은 create transaction이 될 수 없음을 의미
|
||||
|
||||
### 서명
|
||||
y_parity, r, s는 다음과 같이 secp256k1 서명으로 생성됩니다.
|
||||
keccak256(BLOB_TX_TYPE || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to, value, data, access_list, max_fee_per_blob_gas, blob_versioned_hashes])).
|
||||
|
||||
### Header extension
|
||||
현재 헤더 인코딩에 더해 두개의 새로운 64bit unsigned inter field가 추가됩니다.
|
||||
blob_gas_used: 블록 내의 트랜잭션에 의해 소모된 블롭가스의 총량
|
||||
excess_blob_gas: 블록 이전에 목표를 초과하여 소비된 블롭 가스의 누적 총량.
|
||||
|
||||
### Gas accounting
|
||||
블롭 가스는 새로운 타입의 가스입니다. 기존의 가스와는 독립적이고, EIP-1559비슷하게 자체적인 targeting rule을 따릅니다. excess_blob_gas 헤더필드로 영구 데이터를 저장하고, 이를 사용해 blob base fee를 계산합니다. 현재, 블롭은 블롭 가스에 의해서만 가격이 결정됩니다.
|
||||
|
||||
```python
|
||||
def calc_blob_fee(header: Header, tx: Transaction) -> int:
|
||||
return get_total_blob_gas(tx) * get_base_fee_per_blob_gas(header)
|
||||
|
||||
def get_total_blob_gas(tx: Transaction) -> int:
|
||||
return GAS_PER_BLOB * len(tx.blob_versioned_hashes)
|
||||
|
||||
def get_base_fee_per_blob_gas(header: Header) -> int:
|
||||
return fake_exponential(
|
||||
MIN_BASE_FEE_PER_BLOB_GAS,
|
||||
header.excess_blob_gas,
|
||||
BLOB_BASE_FEE_UPDATE_FRACTION
|
||||
)
|
||||
```
|
||||
|
||||
블록 유효성 조건에 블롭 가스 검사도 포함되었습니다.
|
||||
calc_blob_fee로 계산된 실제 blob_fee는 거래 실행 전 보낸 사람 잔액에서 차감되어 소각되며, 거래 실패시 환불되지 않습니다.
|
||||
|
||||
### Versioned hash를 위한 Opcode
|
||||
BLOBHASH 명령어는 스택에서 버전 해시를 읽어오는 기능을 제공합니다. 이 명령어를 사용하면 블록체인에 저장된 블롭(Blob) 데이터의 해시값을 쉽게 얻을 수 있습니다.
|
||||
명령어의 동작 방식은 다음과 같습니다:
|
||||
|
||||
1. 스택의 맨 위에서 인덱스 값(index)을 빅 엔디언(Big-endian) 방식의 uint256 형식으로 읽어옵니다.
|
||||
2. 읽어온 index가 현재 트랜잭션의 블롭 버전 해시 리스트(tx.blob_versioned_hashes)의 길이보다 작은 경우:
|
||||
- tx.blob_versioned_hashes[index] 값을 스택의 맨 위에 놓습니다.
|
||||
- 이는 해당 인덱스에 해당하는 블롭의 버전 해시값을 의미합니다.
|
||||
|
||||
3. 읽어온 index가 블롭 버전 해시 리스트의 길이 이상인 경우:
|
||||
- 0으로 채워진 bytes32 값을 스택의 맨 위에 놓습니다.
|
||||
- 이는 해당 인덱스에 해당하는 블롭이 존재하지 않음을 나타냅니다.
|
||||
|
||||
4. BLOBHASH 명령어를 실행하는 데에는 HASH_OPCODE_GAS만큼의 가스 비용이 소모됩니다.
|
||||
|
||||
이 명령어를 통해 스마트 컨트랙트는 트랜잭션에 포함된 블롭 데이터의 버전 해시를 손쉽게 확인할 수 있습니다. 이는 블롭 데이터의 무결성을 검증하거나, 블롭 데이터를 참조하는 다른 연산에서 활용될 수 있습니다.
|
||||
|
||||
### 포인트 평가 사전 컴파일
|
||||
POINT_EVALUATION_PRECOMPILE_ADDRESS라는 프리컴파일을 추가합니다. 이는 blob이 주어진 point에서 평가되었다고 주장하는 KZG proof를 검증합니다. 해당 사전 컴파일에는 POINT_EVALUATION_PRECOMPILE_GAS가 들고, 다음 함수가 실행됩니다.
|
||||
|
||||
```python
|
||||
def point_evaluation_precompile(input: Bytes) -> Bytes:
|
||||
"""
|
||||
Verify p(z) = y given commitment that corresponds to the polynomial p(x) and a KZG proof.
|
||||
Also verify that the provided commitment matches the provided versioned_hash.
|
||||
"""
|
||||
# The data is encoded as follows: versioned_hash | z | y | commitment | proof | with z and y being padded 32 byte big endian values
|
||||
assert len(input) == 192
|
||||
versioned_hash = input[:32]
|
||||
z = input[32:64]
|
||||
y = input[64:96]
|
||||
commitment = input[96:144]
|
||||
proof = input[144:192]
|
||||
|
||||
# Verify commitment matches versioned_hash
|
||||
assert kzg_to_versioned_hash(commitment) == versioned_hash
|
||||
|
||||
# Verify KZG proof with z and y in big endian format
|
||||
assert verify_kzg_proof(commitment, z, y, proof)
|
||||
|
||||
# Return FIELD_ELEMENTS_PER_BLOB and BLS_MODULUS as padded 32 byte big endian values
|
||||
return Bytes(U256(FIELD_ELEMENTS_PER_BLOB).to_be_bytes32() + U256(BLS_MODULUS).to_be_bytes32())
|
||||
```
|
||||
|
||||
### 합의 레이어 검증
|
||||
Blobs는 비콘 블록 본문에 직접 포함되지 않고, 별도의 "sidecar"로 전파됩니다. 이를 통해 향후 데이터 증가에 대한 호환성을 유지할 수 있습니다.
|
||||
is_data_available() 함수는 전체 샤딩 시스템에서 데이터 가용성 샘플링(DAS)으로 대체될 수 있어, 모든 비콘 노드가 모든 블롭을 다운로드하는 것을 피할 수 있습니다.
|
||||
합의 계층은 데이터 가용성을 위해 블롭을 유지하는 역할을 담당하며, 실행 계층은 이에 관여하지 않습니다.
|
||||
|
||||
ethereum/consensus-specs 저장소는 이 EIP와 관련된 다음과 같은 합의 계층 변경사항을 정의합니다:
|
||||
• 비콘 체인: 업데이트된 비콘 블록을 처리하고 블롭의 가용성을 확인합니다.
|
||||
• P2P 네트워크: 업데이트된 비콘 블록 유형과 새로운 블롭 사이드카를 전파하고 동기화합니다.
|
||||
• 정직한 검증자: 블롭이 포함된 비콘 블록을 생성하고, 관련 블롭 사이드카에 서명하고 게시합니다.
|
||||
|
||||
### 실행 레이어 검증
|
||||
```python
|
||||
def validate_block(block: Block) -> None:
|
||||
...
|
||||
|
||||
# check that the excess blob gas was updated correctly
|
||||
assert block.header.excess_blob_gas == calc_excess_blob_gas(block.parent.header)
|
||||
|
||||
blob_gas_used = 0
|
||||
|
||||
for tx in block.transactions:
|
||||
...
|
||||
|
||||
# modify the check for sufficient balance
|
||||
max_total_fee = tx.gas * tx.max_fee_per_gas
|
||||
if get_tx_type(tx) == BLOB_TX_TYPE:
|
||||
max_total_fee += get_total_blob_gas(tx) * tx.max_fee_per_blob_gas
|
||||
assert signer(tx).balance >= max_total_fee
|
||||
|
||||
...
|
||||
|
||||
# add validity logic specific to blob txs
|
||||
if get_tx_type(tx) == BLOB_TX_TYPE:
|
||||
# there must be at least one blob
|
||||
assert len(tx.blob_versioned_hashes) > 0
|
||||
|
||||
# all versioned blob hashes must start with VERSIONED_HASH_VERSION_KZG
|
||||
for h in tx.blob_versioned_hashes:
|
||||
assert h[0] == VERSIONED_HASH_VERSION_KZG
|
||||
|
||||
# ensure that the user was willing to at least pay the current blob base fee
|
||||
assert tx.max_fee_per_blob_gas >= get_base_fee_per_blob_gas(block.header)
|
||||
|
||||
# keep track of total blob gas spent in the block
|
||||
blob_gas_used += get_total_blob_gas(tx)
|
||||
|
||||
# ensure the total blob gas spent is at most equal to the limit
|
||||
assert blob_gas_used <= MAX_BLOB_GAS_PER_BLOCK
|
||||
|
||||
# ensure blob_gas_used matches header
|
||||
assert block.header.blob_gas_used == blob_gas_used
|
||||
```
|
||||
|
||||
### Networking
|
||||
|
||||
블록 트랜잭션은 두가지 네트워크 표현을 가집니다.
|
||||
1. 블록 트랜잭션 전파(트랜잭션이 아직 블록에 포함되지 않은 상태)
|
||||
트랜잭션 전파(Transaction Gossip) 응답: PooledTransactions 에서는 EIP-2718의 TransactionPayload 가 다음과 같이 래핑됩니다.
|
||||
|
||||
rlp([tx_payload_body, blobs, commitments, proofs])
|
||||
|
||||
tx_payload_body: 표준 EIP-2718 블록 트랜잭션의 TransactionPayloadBody
|
||||
blobs: Blob 항목의 리스트
|
||||
commitments: 해당 blobs의 KZGCommitment 리스트
|
||||
proofs: 해당 blobs와 commitments의 KZGProof 리스트
|
||||
|
||||
즉 트랜잭션 데이터와 함께 추가적인 정보(blobs, commitments, proofs)를 같이 보내서, 받는 사람이 트랜잭션이 유효한지 확인할 수 있게 합니다.
|
||||
|
||||
노드는 tx_payload_body를 검증하고, 래핑된 데이터를 확인해야합니다. 이를 위해 다음과 같이 확인합니다.
|
||||
• tx_payload_body.blob_versioned_hashes, blobs, commitments, proofs의 개수가 동일해야 합니다.
|
||||
• KZG commitments는 버전 해시로 해시되어야 합니다. 즉, kzg_to_versioned_hash(commitments[i]) == tx_payload_body.blob_versioned_hashes[i]
|
||||
• KZG commitments는 해당 blobs와 proofs와 일치해야 합니다. (참고: 이는 verify_blob_kzg_proof_batch를 사용하여 최적화할 수 있습니다.)
|
||||
|
||||
2. 블록 데이터 요청(새로운 블록이 만들어지면 노드들은 그 블록에 포함된 트랜잭션 데이터를 요청함)
|
||||
블록 본문 검색 응답(BlockBodies)에서는 표준 EIP-2718 블록 트랜잭션 TransactionPayload가 사용됩니다.
|
||||
|
||||
노드는 블록 트랜잭션을 피어에게 자동을 브로드캐스트 하지 않고, 대신 해당 트랜잭션은 NewPooledTransactionHashes 메시지로 알려지고, GetPooledTransactions로 수동으로 요청할 수 있습니다.
|
||||
|
||||
쉽게 말해서, 1은 "새로운 트랜잭션을 알리는 단계"이고, 2는 "블록에 포함된 트랜잭션 데이터를 요청하는 단계"입니다. 1에서는 트랜잭션의 유효성을 확인하기 위해 추가 데이터가 필요하지만, 2에서는 이미 유효성을 검증하고, 블록에 포함된 트랜잭션이기 때문에 추가 데이터 없이 전송됩니다.
|
||||
|
||||
## 이더리움 확장성의 진화
|
||||
|
||||

|
||||

|
||||
샤딩 구현에 대한 합의는 점점 더 실용적이고 롤업 중심 접근 방식으로 변함. EIP4844는 이상과 현실의 절충안
|
||||
샤딩: 이더리움 블록체인을 비콘 체인과 병렬로 실행되는 여러 샤드로 분할.
|
||||
각각의 샤드는 별개의 블록, 블록제안자를 갖고, 각 샤드가 무작위로 할당되고 지속적으로 변화하는 이더리움 활성 검증자 세트의 하위 집합에 의해 보호되는 병합 후 이더리움과 유사하게 작동
|
||||
|
||||
프로토 댕크샤딩 이후 댕크샤딩
|
||||
블롭의 수 8개 목표, 최대 16개
|
||||
각 블롭의 크기도 늘림
|
||||
삭제코딩 프로세스 => 각노드는 전체 블롭을 검증할 필요없이 일부만 검증하면 됨
|
||||
남은 문제: 좀 더 탄력적인 네트워크 토폴로지 생성
|
||||
Loading…
Reference in a new issue