Go

[GO] 블록체인 PoS 하드포크 프로젝트 - (구축완료/상세설명)

viviviviviid 2023. 12. 5. 19:17

 

PoS 하드포크 프로젝트가 마무리 되었다.

 

블록체인 코어를 직접 다룰거라 생각 못했는데, 강의를 통해 나만의 PoW기반 블록체인 코어를 구축할 수 있었고, 이를 가지고 평소 관심가지던 PoS를 직접 빌딩하게 되었다.

이번 프로젝트 정말 재밌었다. 진짜다. 그리고 나에게 PoS란

1년전 블록체인 부트캠프에서 PoS 이론을 처음 접한 것을 시작으로, 이더리움 PoS 하드포크를 진행할 때, 이더리움 파운데이션 유튜브를 틀어놔 도스창에서의 축하메세지와 전환 장면을 실시간으로 봤었고, 또한 NFT 커뮤니티의 팀원으로써 PoS라는 단어는 셀수도 없이 들은 듯하다.

이렇게 관심이 안 갈수없던 PoS 합의 프로토콜을 직접 빌딩하는것만으로도 설렜다. 내게 이런 기회가 생긴 것, 그리고 빌딩할 수 있는 최소한의 능력이 생긴것은 행복 그자체였다. 초기 계획 단계부터 너무 신나서 체크리스트를 평소보다 더 세분화하고 설계해나갔다.

 그리고 직접 개발해가는 과정에서 익히기 시작한지 3개월 밖에 안된
GO에 애착이 가기 시작했다.

 

임베디드 언어부터 JS에 이르기까지 많은 언어를 경험했는데, 자바스크립트와 파이썬의 사이 그 어딘가에 위치한 언어인듯 했다. 너무 편하고 속도도 빠르며 개성적인 툴들이 있었다. 리눅스와 윈도우를 사용하다 맥북을 접했을때 그 행복한 느낌과 비슷하달까..

 

리뷰는 여기까지하고 프로젝트에 대해 이야기해보자.

이전 글을 보면 필요한 내용들과 삭제할 내용들을 리스트해놨었다. 사실 실제로 구축하면서 더 많은 기능들이 요구되었지만, 이 리스트는 극초기 단계에서 작성한 것이므로 비어있는 내용들이 많다.

 

이전글 스크린샷

 

위 리스트에서 "악의적인 노드 처벌"을 제외하고 전부 수행되었다. 이유는 추후 실제 블록체인과 관련된 수학적 이론 등을 적용하면서 구축하고 싶은 내용이었기 때문이다. '비잔틴 장군 딜레마' 같은 이론을 적용하며 탄탄한 블록체인을 구축해 나갈 예정이다.

프로젝트를 선정한 이유

우선 이 프로젝트는 '노마드코더'의 강의를 듣고 구축된 PoW 기반의 블록체인 코어를 PoS로 하드포크하는 프로젝트이다. 

"PoS로 하드포크한다"라는 의미도 중요하겠지만, 필자가 GO언어를 제대로 접한 첫번째 강의였기때문에, GO언어의 추가적인 학습은 필수였었다. 프로그래밍 언어또한 하나의 언어기 때문에, 강의 한번 듣는다고 언어가 익숙해지고 능숙해지는 것은 아니기 때문이다. 그래서 추가적인 프로젝트를 진행하면서 언어를 추가적으로 익히고자했고, 새로 프로젝트를 진행하는 것보다, 이미 구축된 블록체인을 가지고 내게 익숙한 PoS 이론을 적용하면 많은 이득을 볼 수 있겠다고 생각하여 진행하게 되었다.

3개의 역할

이 프로젝트에는 세가지 역할이 존재한다.

1. PoS 스테이킹 풀 제공자

  1. PoS 참여자들이 스테이킹 자금을 보내는 곳으로, 스테이킹 노드들의 리스트를 종합
  2. 매 슬롯마다 참가조건에 부합하는 인원중에서 한 명을 선출 (블록 검증자 제외)
  3. 매 에포크마다 참가조건에 부합하는 인원중에서 세 명을 선출 (블록 제안자 제외)
  4. 검증자들로부터 검증결과를 받아 제안자에게 제안 결과를 전달
  5. 현재 구축된 체인에는 스마트컨트랙트 기능이 없어 노드를 이용했으며, 위 셋 PoS 필수 기능들을 갖춘 컨트랙트라고 간주

2. 블록 제안자

  1. 새로 선정된 블록 제안자는 멤풀의 트랜잭션으로 블록을 구성하고 검증자에게 검증을 요청
  2. 검증자들의 검증 결과의 과반수가 계산된 이후, 제안자에게 블록 생성 권한이 주어지면 블록을 체인에 추가

3. 블록 검증자

  1. 블록 제안자에게 블록을 전달받음과 동시에, 검증자 또한 임의로 블록을 구성해 전달받은 블록과 비교
  2. 유효성 검증이 완료되면, 블록이 유효하고 검증을 마쳤다는 증명으로 검증자의 지갑으로 블록을 서명해 서명값을 추가.
  3. 검증 결과를 전달

Start Nodes & Code Review

1. 프로젝트 폴더내의 run_nodes 폴더에 들어가 아래의 커맨드를 터미널에 입력해주면, 3000번(스테이킹 풀 제공자 대체), 4000~4009번으로 총 10개의 노드들이 실행된다.

./run_nodes.sh

 

2. 세팅시간은 총 15초 걸리며, 그 동안 노드들끼리 peer을 맺고 서로가 가진 기존 데이터들을 비교한다. 그 뒤 본인의 데이터(블록 높이)가 남들보다 뒤쳐진다면, 앞서나간 노드들의 블록 전체를 요청하고 본인의 블록체인 데이터를 대체한다.

 

3. 그 뒤, 4001~4009번 노드들은 일반노드로써 http API 요청과 Websocket 메시지를 기다린다. 둘 다 비동기로 진행된다.

 

4. 이제 3000번 노드(스테이킹 풀 컨트랙트 대체)의 PoS 함수를 보자.

func PoS(aPort int) {
  go rest.Start(aPort)
  time.Sleep(nodeSettingTime * time.Second)

4-1. 위 두 줄 코드는 3000번의 초기 세팅이므로, 위에서 설명한 세팅시간때 실행되고 있다.

    for {
      lastHeight := blockchain.Blockchain().Height
      roleInfo, err := blockchain.Blockchain().Selector()
      if err != "" {
        continue
      }
      p2p.PointingProposer(roleInfo)
      p2p.PointingValidator(roleInfo)
      time.Sleep(slotTime * time.Second)
      blockchain.Blockchain().CheckProposalSuccess(lastHeight)
    }
}

4-2. for문 내부가 PoS 블록합의의 메인이나 다름없는데 순서대로 이야기해보자면,

lastHeight := blockchain.Blockchain().Height

로 현재 블록 높이를 저장한다. 나중에 블록이 추가되었는지 확인할때 필요하다.

roleInfo, err := blockchain.Blockchain().Selector()

4-3. Selector()는 스테이킹 중인 노드들의 리스트를 종합하고, 블록제안자와 검증자를 선출하여 roleInfo라는 struct로 반환해준다.

블록제안자 한명을 1슬롯(1개의 블록이 추가되는 시간), 3명 검증자를 1에포크(32슬롯)마다 새롭게 선출한다. 

p2p.PointingProposer(roleInfo)
p2p.PointingValidator(roleInfo)
time.Sleep(slotTime * time.Second)

4-4. Selector로부터 받은 roleInfo를 이용하여 블록제안자와 검증자에게 Websocket으로 선출되었다는 메시지를 보내준다.

위 코드를 쪼개서 보면,

p2p.PointingProposer(roleInfo)

제안자 지목을 하면, 제안자는 제안할 블록을 구성하여 검증자들에게 전달해준다.

p2p.PointingValidator(roleInfo)

검증자 지목을 하면, 몇번째 블록부터 몇번째 블록까지 검증자로 선정되었다는 공지만 해주고, 제안자로부터 제안블록이 올때까지 대기한다. (블록 제안자의 블록 구성과는 비동기로 이뤄짐)

 

4-5. 검증자가 블록 검증을 마치고, 3000번 노드에게 결과들을 보내면, 3000번 노드는 검증자들의 검증결과를 종합하고 과반수를 계산하여 검증 최종 결과를 제안자에게 전달하여, 블록 제안 결과를 알려준다.


4-6. 블록 제안자는 블록 검증 결과를 토대로 블록을 블록체인에 추가할 수 있다.

 

4-7. 이제 3000번 노드는, 1슬롯 시간인 12초가 지나서 블록이 제대로 추가되었는지 확인한다. 블록이 추가되었다면 다시 처음으로 돌아가 Selector을 실행하며 역할들을 재선출하는 알고리즘이다.

 


시나리오 알고리즘

다음 세개의 시각자료는, 시나리오에 대해 각각 알맞는 다이어그램을 이용하여 만든 알고리즘 내용이다.

1. PoS 블록 합의

스테이킹 풀 제공자가 선출하는 것을 시작으로, 제안자의 블록이 제안되고 검증을 거쳐 체인에 블록이 추가되는 과정

2. PoS 스테이킹 / 언스테이킹

블록 합의에 참여하길 원하는 노드가 스테이킹 트랜잭션을 구성하고 블록에 추가되는 과정

3. UTXO 기반 트랜잭션 추가

하나의 지갑이 체인 내에서 트랜잭션을 구성하고 멤풀에 추가하는 과정

 

 

Notion Page

 

PoS 페이지

📌 프로젝트 메인 페이지

noble-walker-465.notion.site

Github Repository

 

GitHub - viviviviviid/go-pos-hardfork: Hardfork Project (PoW -> PoS)

Hardfork Project (PoW -> PoS). Contribute to viviviviviid/go-pos-hardfork development by creating an account on GitHub.

github.com