반응형

블록은 이전블록의 해시(prevHash라고 부르도록 하겠다.)와 트랜잭션의 묶음이라고 생각할 수 있다. 해시는 블록의 데이터를 통해 계산되기 때문에 체인의 형태로 구성될 수 있다. 만약, 블록이 생성된 이후에 블록의 데이터를 변경하게 되면, 해당 블록의 블록해시(block hash)가 바뀌고, 이는 이후 생성된 다른 블록들에 영향을 주어 모든 검증자들이 알아차릴 수 있기 때문에, 다음 블록이 모두 무효화되어 임의 변조를 막을 수 있다.

네트워크의 모든 참가자들이 동기화된(Syncronized) 상태(State)를 유지하고, 모든 트랜잭션에 동의를 하기 쉽게 하기 위해 다수의 트랜잭션들을 한 개의 블록으로 묶어서 Commit, agree, Syncronize를 한 번에 처리한다.

출처:  https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf

 

모든 블록들이 적절하게 검증을 받을 수 있도록, 네트워크는 참여자들에게 검증을 할 수 있는 충분한 시간을 부여한다. 트랜잭션은 초당 수십~수백개씩 발생할 수 있지만, 블록은 12초에 한 번 이더리움에서 생성되고 commite된다.

즉, 블록이 없다면, 모든 validator(트랜잭션(혹은 블록)을 검증하는 객체)는 매 초 모든 트랜잭션을 검증해야하며, 네트워크 상태에 따라 트랜잭션이 누락되는 경우에도 이를 검증하고, 블록을 네트워크에 추가해야하기 때문에, 블록을 사용할 때에 비해 Fork의 수가 수없이 많아지게 될 것이다.

(이정도면 블록이 있는 이유에 대해 충분히 알아본 것 같다…!)

블록의 작동 방식

transaction history를 보존하기 위해 블록은 상위 블록에 대한 참조를 가지고있어야 하며(prevHash에 대한 정보가 기록되어야 함), 블록 내에 있는 트랜잭션 또한 엄밀한 과정을 거쳐 블록에 정렬된다.

→ 추후에 더 알아볼 예정

PoS시스템에서, 네트워크에서 무작위로 선택된 검증자(PoS에서는, Proposer라고 부른다.)가 블록을 빌드하면, 이를 전체 네트워크에 Broadcast하게 되고, 합의의 과정 이후에 모든 노드는 이 블록을 블록체인의 끝에 추가하고 새로운 Proposer가 선출되어 다음 블록이 생성되는 과정을 통해 블록 추가해 대한 commitment와 consensus 프로세스를 명시하고 있다.

블록의 구조

slot 블록이 속한 슬롯

proposer_index Proposer의 ID
parent_root prevHash
state_root state root hash
body 블록 데이터를 담고있는 객체 (바로 아래에서 설명)

Body

randao_reveal 다음 block의 Proposer를 선택하기 위한 값(RANDAO seed)

eth1_data deposit contract에 대한 정보
graffiti 블록 태그를 위한 임의의 데이터
proposer_slashings slash당할 validator의 리스트
attester_slashings slash당할 attestor의 리스트
attestations 이 블록에 대한 attestation 리스트 (바로 아래에서 설명)
deposits list of new deposits to the deposit contract
voluntary_exits 네트워크를 떠난 validator 리스트
sync_aggregate light client에게 serve하는 validator subset
execution_payload execution client에서부터 넘어온 정보(트랜잭션 데이터 등) (아래에서 설명)

Attestations

→ list of attestations

aggregation_bits 어느 validator가 이 attesttation에 참여했는지에 대한 목록

data a container with multiple subfields (아래에서 설명)
signature 모든 attester들의 aggregate signature
  • data (in attestation)slot attestation이 실행된 slot
    index validator의 ID
    beacon_block_root 이 object를 포함하는 비콘블록의 루트해시
    source the last justified checkpoint
    target the latest epoch boundary block

Execution Payload header

parent_hash parent block의 hash

fee_recipient 트랜잭션 수수료를 받는 주소
state_root 이 블록으로 인한 state 변화를 적용한 global state의 root hash
receipts_root tx_receipt trie의 root hash
logs_bloom 이벤트로그를 포함하는 데이터 구조
prev_randao random validator selection에 사용된 value (RANDAO seed)
block_number 블록 번호
gas_limit 이 블록에 allow된 최대 gas
gas_used 이 블록에서 사용된 실제 가스
timestamp block time
extra_data arbitrary additional data as raw bytes
base_fee_per_gas base fee value
block_hash Hash of execution block
transactions_root 트랜잭션들의 root hash
withdrawal_root withdrawal 데이터의 root hash

Execution payload

parent_hash parent block의 hash

fee_recipient 트랜잭션 수수료를 받는 주소
state_root 이 블록으로 인한 state 변화를 적용한 global state의 root hash
receipts_root tx_receipt trie의 root hash
logs_bloom 이벤트로그를 포함하는 데이터 구조
prev_randao random validator selection에 사용된 value (RANDAO seed)
block_number 블록 번호
gas_limit 이 블록에 allow된 최대 gas
gas_used 이 블록에서 사용된 실제 가스
timestamp block time
extra_data arbitrary additional data as raw bytes
base_fee_per_gas base fee value
block_hash Hash of execution block
transactions 실행될 트랜잭션들의 리스트
withdrawals withdrawal 객체의 리스트
  • withdrawalsaddress withdraw한 객체의 주소
    amount withdraw한 ETH총량
    index withdrawal index value
    validatorIndex validator index value
  • 스테이킹된 이더를 인출하는것과 관련된 데이터 필드

Blocktime

블록타임(Blocktime)은 블록을 나누는 시간 단위. 이더리움에서는 12초 단위로 시간이 쪼개지며, 이를 slot(슬롯)이라는 시간 단위로 사용한다. 각 slot에서, 랜덤한 프로세스를 거쳐(RANDAO) single validator가 선출되어 블록을 propose한다. 모든 validator가 온라인 상태이고 문제없이 작동한다고 가정했을 때의 blocktime이 12초가 된다. 그러나, 종종 validator가 오프라인상태라면, 해당 검증자의 슬롯은 비워질 수 있다.

Blocksize

블록은 블록 사이즈에 의해 나눠지기도 한다. (Blocktime에서는 한 블록이 몇 초에 한 번 생성되는지를 이야기했다면, 이 말은 한 블록의 사이즈가 얼마나 되는냐는 말이다.) 각 블록의 일반적인 크기는 1500만 gas이며, 네트워크 상태에 따라 증가, 감소가 가능하여 최대 3000만 gas까지 늘어날 수 있다.

Blocksize가 늘어나는 매커니즘

블록의 크기는 한번에 확 증가하는 것이 아닌, 점진적으로 증가/감소하는 방식을 가지고 있다. 그 증가/감소 비율을 최대 $\frac{1}{1024}$의 비율만큼 늘어날 수 있는 것인데, 예를 들어 현재 블록의 크기가 1500만 gas라면, 다음 블록의 최대 크기는 $15,000,000 + (15,000,000/1024==14,648)=15,014,648$ 만큼의 크기를 가질 수 있게 된다는 말이며, 이러한 블록 크기 증가가 여러번 반복되어 최대 30,000,000 gas 크기까지 도달할 수 있다는 말이다.

결과적으로, validator는 합의를 통해 블록의 gas limit을 변경할 수 있으며, 블록의 모든 트랜잭션의 gas 소비량이 블록의 gas limit보다 작을 수 있도록 이를 조절하여야 한다. 블록의 사이즈가 임의대로 커질 수 있다면, 성능이 떨어지는 Full node는 공간 및 속도 요구사항을 충족시키지 못하여 네트워크의 속도를 따라잡을 수 없을 것이다. 블록이 클수록 다음 슬롯에 맞춰 처리하는 데 필요한 컴퓨팅 성능을 더 많이 요구하기 떄문에, 이는 적절히 조절되어야 할 것이다.

반응형
반응형

요약)

  1. The merge 업데이트에서 PoW → PoS로 consensus protocol을 변경.
  2. 기존에 사용되던 Casper FFG와 LMD Ghost를 ETH2에 적절히 조합한 PoS consensus algorithm.

Fork-Choice-Rule: Nakamoto consensus (classic)

비트코인과 이더리움 1.0 PoW의 가장 근간이 되는 합의 프로토콜.

다른 말로 Longest Chain Rule이라고도 표현한다. 말그대로 Fork가 발생했을 때, 여러 Fork중, 더 긴 체인을 선택하는 (즉, 더 많은 hash power가 들어간 체인이 나열한 트랜잭션 순서를 valid하다고 인정하는) 프로토콜이다.

이렇게 인정된 체인을 Canonical Chain이라고 부른다.


Safety & Liveness

FLP impossibility: 결정론적(Safety)하고 비동기적인(Liveness)프로세스에서 합의에 이르는 것이 불가능하다는 것

  • Safety: Finality로 fork발생 없이 오직 하나의 블록체인만을 유지할 수 있도록 하는 것.
  • → consensus에 도달하지 못해, 무한 교착상태에 빠질 수 있음
  • Liveness: 단 하나의 consensus에 도달하지 못하더라도, 불완전한 합의를 우선 진행하여 지연없이 새로운 블록을 계속 생성할 수 있는 것.
  • → fork가 발생하여 이중지불문제를 야기할 수 있음

FLP inpossibility로 인해, 이 두 속성이 모두 충족되기 힘들기 때문에, 각 블록체인들은 이 두 속성의 비중을 조절하여 체인의 특성을 결정함.

 


Casper FFG

32block(1 epoch)마다 블록을 Finalize시키는 알고리즘

ETH1(Before The Merge)에서의 Casper FFG

Casper FFG는 이더리움이 PoW인 시절(ETH1)에도 존재하던 프로토콜이었는데, 원래는 그러한 Nakamoto Consensus에 의해 발생한 여러 Fork 중 Canonical Chain을 결정하기 위해 블록을 Finalize시켜 해당 블록을 checkpoint로 쓰기 위해 위해 사용되었다.

따라서, 이로 인해 51%공격 등의 공격이 발생한다고 해도, 체크포인트 이전의 블록은 수정하지 못하도록 하여 블록체인을 보호한다.

합의의 과정에서, 총 Staking Amount중, 자신의 예치금(deposit)이 차지하는 지분만큼 의결권을 행사할 수 있으며, 이 과정에서 전체 Validator의 $\frac{2}{3}$만큼 투표를 받으면, Supermajority Link로 인정받을 수 있으며, 이 Link와 연결된 checkpoint가 다음 checkpoint가 되는 구조이다.

ETH2 (After The Merge)에서의 Casper FFG

Slot, Epoch

The Merge이후, ethereum에서는 block의 개념보다, slot, epoch이라는 개념을 주로 사용하게 된다. 자세히 살펴보면, 1개의 블록(block)은 1개의 슬롯(slot)이라는, 12초의 단위시간으로 표현되며, 이러한 슬롯이 32개 모여 에폭(Epoch)이라는 384초(6.4분)의 단위시간으로 표현된다.

Casper FFG

Casper FFG는 매 32슬롯(1에폭)마다 여러 포크 중 하나의 포크를 선택하도록 하는데, 부모 체크포인트가 여러 자손 체크포인트 중 하나를 선택하도록 하는 것이 Casper FFG의 역할이다.


LMD GHOST

(Last Message Driven Greediest heaviest Observed SubTree)

네트워크 지연 등으로 인해 fork발생 시, fork를 선택하는 알고리즘

참조: Combining GHOST and Casper

Message = Attestation message

Fork가 발생했을 때, 어떤 블록을 기존 체인에 연결할지, Attestation Message를 통해 투표하는 프로토콜.

Combining GHOST and Casper

위 그림에서 사각형으로 표현된 것이 block(또는 slot), 원으로 표현된 것이 Message.

가장 많은 Last Attestation Message가 지지하고 있는 block이 인정되게 된다.

Last Attestation Message?

→ 그림에서 보이는 모든 원들을 말한다. 즉, 몇 번째 블록인지와 상관 없이, 모든, “가장 최근”의 Attestation Message.

이를 통해, 블록체인의 Safety를 어느정도 보장하게 된다.


Gasper

위에서 본 것과 같이, Casper FFG와 LMD Ghost는 모두 결국 Fork중, 어느 Fork를 인정할지를 선택하는 프로토콜이다. 그럼, 왜 이 둘을 구분하여 사용할까.

slot과 slot간의 관계 즉, slot 단위에서 발생하는 fork에 대하여 LMD Ghost에 의해 하나의 fork로 합의된다.

이렇게 만들어진 epoch은 Casper에 의해 체크포인트 블록을 연결(또는 확정)하는 단위로 사용된다. 즉, epoch과 epoch의 관계를 Casper를 통해 결정짓는다.

이러한 epoch과, slot의 개념이 있는 것은 알겠는데, 그래서 어떤 과정을 통해 검증(Validate)를 하는 것일까?

Committees

참조: DSRV Research

  1. 매 slot마다 하나의 Validator집단을 랜덤하게 만든다.
  2. 각 집단을 Committee(위원회)라 부른다.
  3. 각 위원회에서 랜덤하게 한 명의 리더를 선출하여 이 리더는 블록을 제안한다.
  4. 블록 제안자를 포함한 위원회의 모든 validator는 블록을 검증한다.
  5. 한 에폭은 32개의 슬롯으로 이루어져있기 때문에, 전체 validator 집단을 32개로 랜덤하게 쪼개 슬롯에 배정하여 모든 validator가 한 epoch에서 validating에 참여할 수 있도록 함
  6. 한 epoch이 끝나면, 다시 랜덤하게 commitee를 구성하여 위의 과정을 반복한다.

Validate (Block 검증)

LMD GHOST프로토콜에서, 한 명의 block proposer가 해당하는 committee에 블록을 제안하면, 해당 committee를 구성하는 validator들은 블록을 확인하고, 블록에 대한 Attestation Message를 broadcast한다. 이러한 Attestation Message를 통해 지지되는 Fork마다 LMD GHOST점수가 매겨지고, 다음 블록 생성자는 어떤 fork 위에 블록을 생성해야 하는지 결정하게 된다.

위에서 Finalize라는 개념이 등장했었는데, 이는 체크포인트를 확정짓는 과정에 속하게 된다. 여기서, 체크포인트는 각 epoch의 첫 번째 슬롯의 블록으로 설정하여 Finalize과정을 거치도록 한다. 이를 더 자세히 뜯어보자.

class AttestationData(Container):
    slot: Slot # attestation message 전파하는 slot number
    index: CommitteeIndex # validator가 속한 commitee number
    beacon_block_root: Root # fork결정에 대한 attestation message 즉, LMD GHOST
    source: Checkpoint # Casper FFG vote: last justified epoch's first block
    target: Checkpoint # Casper FFG vote: last epoch's first block

위의 코드는 Validator가 committee에 broadcast하는 Attestation message의 구조이다.

source와 target, 그리고 beacon_block_root가 중요한 내용인데, source는 가장 최근에 justificate된 즉, 현재 epoch이전에 인정된 epoch의 첫 번째 블록(체크포인트)를 의미한다. target은 이번 그 체크포인트의 다음 epoch의 체크포인트라고 생각되는 block을 가리킨다. 이를 통해, Casper FFG투표(Supermajority vote)를 진행할 수 있으며, BPFT(비잔틴 장군 문제)에 따라, $\frac{2}{3}$이상의 validator가 동의하면, epoch의 상태가 justified로 변한다. (여기서, justified는 finalized와 다른 개념으로, Finalized되기 이전의 상태를 말한다.)

그렇다면, Finalize는 어떤 과정을 거쳐 진행될 수 있을까?

  1. Epoch0과 Epoch1의 checkpoint간 연결이 justified되었다고 하자.
  2. Epoch2에서 블록을 검증하는 validator들이 Epoch1과 Epoch2의 Supermajority Link를 지지하는 투표를 한다.
  3. 이 투표 비율이 전체 validator 수의 $\frac{2}{3}$이 되면, Epoch1과 Epoch2의 체크포인트 사이에 Supermajority Link가 생성되고, 이 Link가 Justified된다.
  4. 이 과정을 통해, Epoch1은 Epoch0과 Epoch2 모두로부터 Supermajority Link가 생성되어 그 결과, Epoch1에 있는 체크포인트가 Finalize되어 더 이상 변경할 수 없게 된다.

이렇게 Casper FFG와 LMD GHOST가 합쳐져 Gasper가 만들어지게 된다.


추가적인 궁금증🤨

Fork가 발생하는 이유.

Q. 블록체인에서 Fork가 발생하는 이유를 두고, 51%공격, 그리고 네트워크 지연 등 이유로 Fork가 발생하는 것으로 알고 있는데, 한 Slot당 하나의 Committee가 구성되고, 한 Committee에서 한 Proposer가 block을 제안하는 구조에서, 대체 왜 Fork가 발생하는가?

A(Mentor Troy). 현재 이더리움 PoS에서 가장 흔히 fork (reorg)가 발생하는 이유는 네트워크 지연이라고 볼 수 있다. 예를들어, 1번 슬롯에서 A 밸리데이터가 정해진 시간 내에 N번에 해당하는 블록을 만들어서 전파해야하는데, 이 시간 내에 전달받지 못한 경우 이를 Missed로 처리하고 2번 슬롯의 밸리데이터가 만든 블록을 N번 블록으로 포함되게 된다. 그렇지만 일부 밸리데이터들은 A가 만든 블록을 수신했을 수도 있지만, vote를 받지 못했기 때문에 그 뒤로 이어나가지 않을 가능성이 크다. 이런 식으로 Reorg가 발생하곤 한다.

참고자료

https://arxiv.org/pdf/2003.03052

https://medium.com/curg/gasper-casper-ghost-5aa9c226265c

 

반응형

+ Recent posts