Blockchain

[Solana] Sealevel - Parallel Processing Thousands of Smart Contracts

서바리바리 2022. 12. 8. 08:19

이번 글에서는 솔라나의 창립자인 아나톨리 야코벤코의 Medium 블로그 포스팅 중 하나인 Sealevel에 관한 내용을 공부하며 의역한 내용을 정리해 보려고 한다. 먼저 원본 글을 읽어보고 오는 것을 추천!

 

Sealevel — Parallel Processing Thousands of Smart Contracts

Understand 1 of 8 key technologies that make Solana the most performant blockchain in the world

medium.com


솔라나가 전세계에서 가장 성능이 좋은 블록체인이 되는 것을 가능하게 한 8가지 핵심 기술 중 1개를 이해해보자.

솔라나는 세계에서 가장 성능이 좋은 무허가형 블록체인이다. 현재 솔라나 테스트넷은, 물리적으로 구분된 200개의 노드가 GPU를 이용할 때 초당 50,000개 이상의 트랜잭션 처리량을 유지하고 있다. 이를 달성하기 위해서는 여러 최적화와 새로운 기술이 필요하며, 그 결과는 블록체인 개발에 있어 새로운 시대를 알리는 네트워크 용량의 돌파구가 된다.

솔라나 네트워크를 가능하게 하는 8가지 주요 혁신

  • Proof of History (POH) - 합의 전 사용되는 clock 역할
  • Tower BFT - PBFT의 PoH 최적화된 버전
  • Turbine - 블록 전파 프로토콜
  • Gulf Stream - Mempool-less 트랜잭션 포워딩 프로토콜
  • Sealevel - 병렬로 실행되는 스마트 컨트랙트 런타임
  • Pipelining - 검증 최적화를 위한 트랜잭션 처리 단위
  • Cloudbreak - 수평적으로 확장된 Account 데이터베이스
  • Archivers - 분산된 원장 저장소

이번 포스트에서, 우리는 솔라나의 병렬 스마트 컨트랙트 런타임인 Sealevel에 대해 알아볼 것이다. 시작하기에 앞서, 고려해야할 1가지는 EVM과 EOS's WASM 기반 런타임은 싱글 스레드를 사용한다는 것이다. 즉, 한번에 하나의 컨트랙트만 블록체인의 상태를 변경한다는 의미이다. 우리는 검증자 노드가 가지고 있는 코어를 가능한 한 많이 사용해서 수만 건의 컨트랙트를 병렬로 처리할 수 있는 런타임을 만들었다.

❓EVM(Ethereum Virtual Machine)이란?
이더리움에서 스마트 컨트랙트 코드를 실행하고, 그 결과로 변화된 상태를 업데이트하는 작업을 수행하는 가상머신이다. 자바 코드가 JVM에서 실행되듯이, 이더리움의 스마트 컨트랙트는 EVM 기반으로 실행된다고 생각하면 좋을 것 같다. 이더리움의 스마트 컨트랙트는 아래 다이어그램과 같은 과정을 통해 실행된다.


솔라나가 트랜잭션을 병렬로 처리할 수 있는 이유는, 솔라나 트랜잭션이 실행 중에 읽거나 쓸 모든 상태(state)를 가지고 있기 때문이다. 이는 중복되지 않는 트랜잭션의 동시 실행을 가능하게 할 뿐만 아니라, 항상 동일한 상태만 읽는 트랜잭션도 동시에 실행할 수 있게 한다.

Programs와 Accounts

솔라나의 account 데이터베이스인 Cloudbreak는 Public Key를 Account에 맵핑한다. Account는 잔액과 데이터를 유지하며, 여기서 데이터는 bytes의 벡터를 나타낸다. Account는 "owner" 필드를 가지고 있는데, owner는 해당 account의 상태 변경을 관리하는 program의 Public Key이다. Program은 코드이고, 상태가 없다. Program은 상태 변경을 위해 그들에게 할당된 Account의 데이터 벡터에 의존한다.

❓Vector란
Vector는 Collection 중 하나이다. 메모리 상에 서로 이웃하도록 값을 저장할 수 있는 데이터 구조이다. array와 다른 점은, array는 정적으로 메모리 할당이 일어나, 사이즈 변경이 불가능한 반면, vector는 동적으로 메모리 할당이 일어나기 때문에 사이즈 변경이 가능하다는 것이다.
[참고] Program in Solana
솔라나에서는 스마트 컨트랙트를 "Program"이라고 부른다.

 

  1. Program은 자신이 소유한 Account의 데이터만을 변경할 수 있다.
  2. Program은 자신이 소유한 Account에서만 출금할 수 있다.
  3. 모든 Program은 모든 Account에 입금할 수 있다.
  4. 모든 Program은 모든 Account의 데이터를 읽을 수 있다.

기본적으로, 모든 account는 System Program에 소유된 채로 생성된다.

  1. System Program은 account의 owner를 설정할 수 있는 유일한 program이다.
  2. System Program은 0으로 초기화된 데이터를 할당할 수 있는 유일한 program이다.
  3. Account의 owner 설정은 account의 lifetime에서 딱 1번만 발생할 수 있다.

사용자 정의 program은 loader program에 의해 로드된다. loader program은 account에 저장된 데이터가 executable하다고 표시할 수 있다. 사용자는 커스텀 program을 로드하기 위해 다음과 같은 트랜잭션을 실행한다.

  1. 새로운 public key를 생성
  2. 해당 public key에 코인을 전송
  3. System Program에게 메모리 할당을 요청
  4. System Program에게 해당 account를 Loader에게 배정해달라고 요청
  5. 메모리에 바이트코드를 나누어 업로드
  6. Loader Program에게 해당 메모리가 executable함을 표시해달라고 요청

이 시점에서 loader는 바이트코드를 확인하고, 바이트코드가 로드된 account는 executable program으로 실행될 수 있게 된다. 새로운 account는 사용자 정의 program에 의해 소유되었다고 표시될 수 있다.

여기서의 핵심 인사이트는 program이 코드이고, 솔라나의 key-value 저장소 내에는 해당 program만이 쓰기 접근 권한을 갖는 일부 하위 key 집합이 존재한다는 것이다.

Transactions

  1. 모든 instructions를 program ID로 정렬
  2. 모든 accounts에 대하여 동시에 같은 program을 실행

트랜잭션은 instruction 벡터를 특정한다. 각각의 instruction은 program과 program instruction, 트랜잭션이 읽거나 쓰려고하는 account의 리스트를 포함하고 있다. 이러한 방식의 인터페이스는 low level OS와 기기 사이의 인터페이스에서 영감을 받은 것이다.
SIMD instructions는 하나의 코드가 여러 개의 데이터 스트림을 통해 실행될 수 있도록 한다. 즉, Sealevel은 솔라나 설계에서만 볼 수 있는 추가적인 최적화를 실행할 수 있는 것이다:

❓SIMD(Single Instruction Multiple Data)란
SIMD는 CPU에서 지원되는 instruction set으로, 하나의 명령어로 동일한 형태/구조의 여러 데이터를 한번에 처리하는 병렬처리기법을 말한다.
자세한 내용은 아래 블로그 포스팅을 참고!
SIMD(Single Instruction Multiple Data)에 대한 집중탐구!
size_t

readv(int d, const struct iovec *iov, int iovcnt);

struct iovec {
	char *iov_base; /* Base address. */
	size_t iov_len; /* Length. */
};

readv나 writev 같은 인터페이스는 커널에게 사용자가 읽거나 쓰려고 하는 모든 메모리 정보를 미리 알려준다. 이는 OS가, 필요하다고 생각하는 명령이나 데이터를 사전에 판독할 수 있게 하고, 기기를 준비하고, 기기가 허락한다면 해당 명령을 동시에 실행할 수 있도록 한다.

솔라나에서, 각 instruction은 VM에게 어떤 account를 읽고 쓸 것인지 미리 알려준다. 이것이 솔라나 VM 최적화의 근간이다.

  1. 실행 대기중인 수백만의 트랜잭션을 정렬한다.
  2. 중복이 없는 모든 트랜잭션들을 병렬로 스케줄링한다.

더욱이 우리는 CPU와 GPU 하드웨어가 설계된 방식을 활용할 수 있다.

왜 이것이 강력한 최적화인지 알고 싶다면, CUDA 개발자 가이드를 읽어보기 바란다.

CUDA 아키텍쳐는 확장 가능한 멀티스레드 Streaming Multiprocessors(SMs) 배열을 기반으로 설계되었다. 호스트 CPU의 CUDA 프로그램이 커널 grid를 호출하면, grid의 블록이 열거되어 사용 가능한 실행 용량을 가진 멀티프로세서에 분배된다.
❓ Streaming Multiprocessor와 Kernel Grid
아래 블로그 포스팅에 설명이 이해하기 쉽게 나와 있으니, 참고하면 좋을 것 같다.
CUDA - Streaming Multiprocessors

현대의 엔비디아 GPU는 4000개의 CUDA 코어를 가지고 있으나, 멀티프로세서는 대략 50개 밖에 가지고 있지 않다. 멀티프로세서는 한번에 1개의 program instruction만 실행 가능한 반면, GPU는 80개 이상의 다른 input instructions을 병렬로 처리할 수 있다. 따라서, Sealevel에 의해 로드되는 입력 트랜잭션들이 모두 같은 program의 instruction을 호출한다면, 솔라나는 사용 가능한 모든 CUDA 코어를 사용해서 모든 트랜잭션들을 동시에 실행할 수 있다.

 

성능 향상에는 항상 대가가 따르는 법이다. SIMD 최적화가 실현되기 위해서는, 실행되는 instructions는 소수의 분기를 포함해야 하며, 모두 동일한 분기를 가져야 한다. 멀티프로세서는 배치에서 실행되는 가장 느린 경로로 바인딩된다. 이러한 모든 것을 고려해도, Sealevel을 통한 병렬 처리는 싱글 스레드 런타임과 비교했을 때, 블록체인 네트워크가 동작하는 방식에 근본적인 발전을 보여 주고, 예외적으로 높은 처리량과 사용성을 가능하게 한다.