이더리움 백서

김태주·2021년 3월 18일

기획

목록 보기
2/2

서론

이더리움의 목적은 튜링완전언어로 작동하는 블록체인을 제공하는 것이다. 이 언어는 특정 조건이 성립되어야지 상태가 변하는 계약을 실행 및 생성할 수 있게 해준다. 이러한 것들을 바탕으로 다양한 어플리케이션을 쉽게 만들 수 있다.

비트코인의 역사

여기서 설명하는 것은 비트코인에 대해 설명하는 것으로 이더리움과 다른 점이 무엇인지 생각하면서 읽으면 좋다.

1. 상태 변환 시스템

  • 비트코인의 소유권 이전에 대한 업데이트를 계속하면서 새로운 장부를 만드는 시스템

상태: 현재 비트코인의 소유권 현황
상태 변환 함수: 현재 상태와 트랜잭션을 받아서 새로운 상태를 만드는 것. (트랜잭션: 누가 누구에게 얼마를 줄 것인지 적어 놓은 문서)

상태: S, 트랜잭션: TX, 상태 변환 함수: APPLY라고 하면 다음과 같은 식이 성립한다.
APPLY(S, TX) -> S’ or ERROR
Ex) APPLY({ALICE :50won, Bob: 20won}, {send 20won from Alice to Bob}) -> {Alice: 30won, Bob: 70won})
//현재 ALICE가 50원, Bob이 20원 있을 때 ALICE가 밥에게 20원 전송하면 ALICE는 30원, Bob은 40원이 된다.

UTXO (Unspent Transaction Outputs) : 아직 사용되지 않은 트랜잭션 출력값.
구체적으로 설명하자면 UTXO는 원화에서 동전이나 화폐같은 역할이다. 즉 우리가 누군가에게 1000원을 줄 때, 1000원짜리 지폐 하나를 주는 것처럼 비트코인을 거래할 때는 UTXO를 준다. 이 때 UTXO는 단위가 딱히 정해져 있지 않다. (1 btc, 0.7 btc 등 다양하다.) UTXO가 사용되면 없어지며 새로운 UTXO가 생성된다.
예를 들어, A가 B에게 1btc를 주면 A가 가지고 있던 1btc에 해당하는 UTXO는 사라지며 B는 1btc에 해당하는 UTXO가 새로 생성된다.

거래를 할 때 입력 값은 보내는 지갑 주소에서 선택된 UTXO (돈)과 해당 지갑 주소에 대응하는 개인키가 생성한암호화된 서명을 담고 있다. 서명을 담고 있는 이유는 그 돈을 소유한 사람만이 보낼 수 있도록 하기 위함이다.
출력값은 상태(장부)에 추가될 새로운 UTXO 정보를 담고 있다.

따라서 APPLY(S, TX) -> S’ 는 다음과 같이 정의할 수 있다.

1) TX(트랜잭션)의 각 입력에 대해:
	— 만약 참조된 UTXO가 S에 없으면 에러 발생 ( 돈이 존재하는지 확인)
	— 만약 서명이 UTXO의 소유자와 매치되지 않으면 에러 발생 (돈의 소유자가 일치하는지 확인)
2) 만약 입력에 사용된 UTXO 들 금액의 합이 출력 UTXO들 금액의 합보다 작으면 에러 발생
3) 입력에 사용된 UTXO가 삭제되고 출력 UTXO가 추가되 S’ 리턴

2. 채굴

비트코인의 분산 합의 과정은 트랜잭션 패키지인 블록을 계속적으로 생성해서 연결하는 과정이 필요한데 이 과정을 한 후 보상을 받는 것을 채굴이라고 한다. 각 블록은 타임스탬프, 논스, 이전 블록에 대한 참조(이전 블록의 해시), 그리고 이전 블록 이후에 발생한 모든 트랜잭션의 목록을 포함한다.

하나의 블록이 유효한지 확인하는 과정은 다음과 같다.

1) 이 블록에 의해 참조되는 이전 블록이 존재하고 유효한지 확인한다.
2) 타임스탬프 값이 이전 블록의 타임스탬프 값보다 크면서 2시간 이내인지 확인한다.
3) 작업증명이 유효한지 확인한다.
S[0]를 이전 블록의 마지막 상태가 되도록 설정한다. (블록은 이전 블록에 대한 참조를 가지고 있어야 한다.)
4) 0…n-1 범위를 가지는 i에 대해 S[i+1] = APPLY(S[i], TX[I]) 연산을 수행한다. 중간에 에러가 발생하면 종료한다. (트랜잭션을 연결해 장부를 만드는 과정)
5) S[n]를 블록의 마지막 상태로 등록하고 종료한다.

상태는 블록 내에 기록되지 않는다. 즉, S[i+1] = APPLY(S[i], TX[I]) 이 연산을 실행하면서 상태를 블록에 기록하지 않는다는 것이다.

채굴의 목적은 블록에 대한 신뢰성을 확보하기 위함이다. 밑에 예시를 가지고 한 번 이해해보자.

1) 어떤 상품을 구매하기 위해 판매자에게 100 BTC를 지불한다.
상품이 전송 되기를 기다린다.
2) 판매자에게 지불한 것과 같은 100 BTC를 공격자 자신에게 보내는 트랜잭션을 생성한다. (이중지불 문제)
3) 비트코인 네트워크가 공격자 자신에게 보내는 트랜잭션이 판매자에게 지불하는 트랜잭션보다 먼저 수행된 것으로 인식하도록 한다.

1번 과정을 실행하면 채굴자들이 이 트랜잭션을 블록(번호가 270000인)에 포함할 것이다. 1시간 정도 지나게 되면 270000 블록 뒤에 약 5개의 블록(270001 - 270005까지 생성)이 더 있을 것이다. 이후 3번 과정에서 실행하는데 이 때 이 트랜잭션 (자기 자신에게 보내는 것, 블록 번호: 270000’)을 270005 뒤에 붙이는 것이 아닌, 270000 블록의 부모인 269999에 붙이려고 시도한다. 그러면 269999 블록은 두 개의 자식이 생기는 데 이 때 이것을 분기점이라고 한다. 네트워크 상의 노드들은 이 중에서 하나만을 제대로 인식해야 하는데 이 때 기준은 가장 긴 것을 선택하게 된다. 따라서 270000’ 대신 270000을 선택하게 되어 270000’는 무시하게 된다. 이것이 진실성을 보장할 수 있는 이유는 공격자보다 진실된 사람의 계산 속도가 더 빠르다고 가정하기 때문이다. 만약 270000’가 진실된 블록이 되려면 전체 속도 중 51%를 가져와야 하는데 사실상 이것은 불가능하다.

3. 머클트리

머클트리란 이진 트리의 한 종류로 자식의 해시값을 이용해 부모의 해시값을 연산하는 트리이다.머클트리의 목적은 크게 두가지가 있다.

첫 번째는 진실성을 보장하기 위함이다.
머클트리의 자식 노드가 하나라도 변경이 되면 그와 관련된 부모 값과 루트 값이 다 변경되기 때문에 위조를 쉽게 파악할 수 있다.

두 번째는 블록의 데이터가 분리해서 전달될 수 있도록 하기 위함이다.
진실성이 보장되기 때문에 분리해서 보내도 항상 데이터가 같음을 보장할 수 있다.

블록체인에서는 머클트리의 자식들을 트랜잭션, 머클트리의 루트를 블록헤더라고 부른다.

4. 스크립트

스크립트란 비트코인 상에서 스마트 계약을 성립시킬 수 있는 언어인데 다음과 같은 단점이 있다.

1) 튜링불완전성: 모든 경우의 프로그래밍 언어를 지원하지 않는다. while, for문이 되지 않는다.

2) 가치무지: UTXO 스크립토만으로는 인출 액수를 세밀하게 통제할 방법이 없다. 만약 A와 B가 공동계좌에 각각 1000어치BTC넣는다고가정하자.30일후에A1000어치 BTC 넣는다고 가정하자. 30일 후에 A가 1000어치 BTC를 받고 나머지는 B가 가진다는 규칙이 있다. 이 때 BTC의 시세는 계속 변해서 현재의 BTC 와 30일 후의 BTC는 가격이 달라서 A가 받는 BTC 양과 B가 받는 BTC 양은 다른데, 이것을 세밀하게 조절할 수 없다. 왜냐하면 UTXO는 쪼개질 수 없기 때문이다.

3)상태표현제한: UTXO가 표현할 수 있는 상태는 사용되었거나 안 되거나 둘 뿐이다. 따라서 이 두가지 상태 이외에 다른 상태를 가지는 다중 계약을 표현할 수 없다.

이러한 문제점을 해결하고자 이더리움이 나오게 되었다.

이더리움

이더리움의 목적은 분산 어플리케이션 제작을 위한 대체 프로토콜을 만드는 것이다. 튜링 완전 언어를 사용함으로써 이 목적을 이루고자 한다. 또한 스마트 컨트랙트도 구현할 수 있게 한다.

1. 어카운트

상태란 어카운트의 집합으로 구성되어 있다. 이 때 어카운트는 지갑이라고 생각하면 된다.
어카운트는 다음 네 개의 필드를 가지고 있다.

  • 논스: 각 트랜잭션이 일어난 순서를 기록
  • 어카운트의 현재 이더 잔고, (이더: 트랜잭션 수수료를 지불하는데 사용.)
  • 어카운트의 계약 코드
  • 어카운트의 저장 공간

어카운트는 크게 2가지가 있다.

1) 외부 소유 어카운트
개인키에 의해 통제됨
코드를 가지고 있지 않으며 메시지를 보내기 위해서는 트랜잭션을 만들고 개인키로 서명을 해야 함.
지갑이라고 생각하면 된다.

2) 컨트랙트 어카운트
메시지를 받을 때마다 자신의 코드를 활성화시키고 코드의 내용을 실행
일종의 계약서라고 생각하면 된다.

컨트랙트는 트랜잭션(메시지)가 오면 항상 코드를 실행하고 자신의 키/값 저장소를 직접 관리한다. 즉, 우리가 어떤 특정한 계약을 실행 시키려면 그 계약과 관련된 컨트랙트에 외부 소유 어카운트를 이용해 메시지를 보내면 된다.

2. 트랜잭션

트랜잭션이란 누가 누구에게 얼마 보낼지 적어 놓은 것으로, 외부 소유 어카운트가 보낼 메시지를 가지고 있는 서명된 데이터 패키지이다.

트랜잭션에는 startgas와 gasprice라는 필드가 있다. 이 필드는 코드 내의 악의적인 무한루프, 또는 계산 낭비를 방지하기 위해 존재하는 것으로, 이것들의 곱한 값을 채굴자에게 수수료 형태로 지불한다.

3. 메시지

한 컨트랙트가 다른 컨트랙트에게 전달하는 것으로, 다음의 것들을 포함하고 있다

  • 메시지 발신처
  • 메시지 수신처
  • 메시지와 함께 전달되는 이더
  • 선택적 데이터 필드
  • Startgas 값

트랜잭션은 외부 사용자에 의해 생성되는 반면 메시지는 컨트랙트에 의해 생성된다.

코드 수행을 하고 있는 컨트랙트가 call 연산자를 만나면 메시지를 생성한다. 이 메시지는 해당 코드를 실행하는 수신자 어카운트에 도달한다. 즉, 어떤 사용자가 컨트랙트를 실행시키면 컨트랙트가 코드를 실행하는데 이 때 call 연산자를 수행하면 컨트랙트가 사용자에게 메시지를 보낸다.

4. 상태 변환 함수

트랜잭션이 10ether, 2000gas, 0.001ether gasprice, 64byte 데이터를 보내는 과정은 다음과 같다.

1) 트랜잭션 형식 및 유효성 검사
2) 수수료 (2000*0.001 = 2ether)를 발신자 어카운트에서 뺀다.
3) Gas = 2000으로 초기화하고 트랜잭션이 170byte이고 byte 당 수수료가 5gas이면 170*5 =850 만큼 빼야 하고 결국 1150 gas가 남는다.
4) 발신자 어카운트에서 10ether를 추가로 빼고 이것을 컨트랙트 어카운트에 더한다.
5) 코드를 실행시켜 64byte 데이터를 저장한다. 이 때 gas가 소모되면 남은 gas(1150)에서 뺀다
6) 남은 gas는 ether로 변환해서 발신자에게 준다.

메시지 실행 시 gas가 부족하면 그 메시지 실행과 이후 과정은 모두 되돌려지게 되지만 이전의 실행은 되돌려지지 않는다.

5. 블록체인과 채굴

이더리움 블록은 비트코인과 달리 트랜잭션 리스트와 가장 최근의 상태 복사본을 가지고 있다.

블록이 유효한지 판단하는 과정은 다음과 같다.

1) 참조하고 있는 이전 블록의 존재 및 유효성 판단
2) 현재 블록의 타임스탬프와 이전 블록의 타임스탬프를 비교
3) 블록의 구성 요소가 유효한지 판단
4) S[i+1] = APPLY(S[I], TX[I]) 연산을 수행해서 총 gas가 gaslimit보다 크면 오류를 반환 (TX = 현재 블록의 트랜잭션, i = 0부터 n-1까지)
5) 채굴자에게 지불된 보상 블록 S_FINAL 을 S[n] 끝에 붙임.
6) 상태 S_FINAL의 머클 트리 루트가 블록 헤더가 가지고 있는 최종 상태 루트와 같은지 검증 후, 이 값이 다르면 유효하지 않은 것으로 판단. 
—> 머클 트리에서 자식 값이 하나라도 바뀌면 헤더 값이 변경되어 그 트리는 유효하지 않게 된다.

상태가 트리 구조로 저장되고 트리의 작은 부분만이 변경되기 때문에 모든 상태를 각 블록에 저장해도 비효율적이지 않다. 또한 머클 트리를 이용해 노드를 수정하거나 삽입하기 쉽다. 모든 상태 정보가 마지막 블록에 포함되어 있기 때문에 전체 블록체인 히스토리를 모두 저장할 필요가 없어 공간적으로도 효율적이다.

6. 어플리케이션

이더리움으로 만들 수 있는 어플리케이션의 종류는 크게 3가지다.
금융 어플리케이션 - 돈과 직접적으로 연관된 컨트랙트를 계약참여자들로 하여금 보다 강력하게 설정 및 관리
준금융 어플리케이션 - 금전이 관여되어 있지만, 상당부분 화폐가 필요하지 않은 계약이 존재하는 것
비금융 어플리케이션 - 금융과 관련이 없는 것으로 온라인 투표 및 거버넌스 등이 있다.

1) 토큰 시스템 - 금융 어플리케이션

다양한 거래 시스템을 네트워크 상에서 구현할 수 있게 해준다. 이 때, 토큰은 코인이라고 생각하면 된다.

토큰 시스템은 근본적으로 특정 계좌에서 돈을 빼 다른 계좌에 넣는 연산만 한다.

비트코인과 차이점은 수수료를 거래 시 사용한 화폐로 직접 지불할 수 있다는 것이다. 즉, 수수료와 거래 화폐 모두 ether라는 것이다.

2) 금융 파생 상품 - 금융 어플리케이션

파생 상품은 스마트 컨트랙트의 가장 일반적인 어플리케이션이다.

여기서 문제는 어떻게 외부에 존재하는 계약에서 규정하는 자산에 대한 시세를 가져올 것인가 이다.
이 문제를 해결하는 가장 쉬운 방법은 특정한 제 3자가 실시간으로 데이터 피드 컨트랙트를 이용하는 것이다. 이 컨트랙트는 필요할 때마다 데이터를 제공할 수 있어야 하며 다른 컨트랙트와 환율에 대한 메시지를 주고 받을 수 있는 인터페이스가 있어야 한다.

데이터피드 컨트랙트를 이용하는 헷지컨트랙트의 사용법은 다음과 같다.

1) A가 1000 ether 입금할 때까지 기다린다.
2) B가 1000 ether 입금할 때까지 기다린다.
3) 입금된 이더의 달러가치를 기록하며 이를 $X라 한다. (데이터 피드 컨트랙트 사용)
4) 30일 이후, 당시의 환율을 적용한 금액을 계산하여 A에게 $X 를 송금하고 당시 총금액에 나머지를 B에게 송금하도록 컨트랙트를 작성한다. 이 컨트랙트는 A 또는 B가 활성화 시킬 수 있어야 한다.

이러한 컨트랙트는 가상화폐의 가치가 크게 변동하면 손해를 입을 수 있는데, 자산 보증을 통해 해결할 수 있다.

3) 신원 조회 / 평판 시스템 - 비금융 어플리케이션

다음과 같이 컨트랙트를 구성하면 추가만 가능하고 수정 및 삭제는 불가능한 함수를 제작할 수 있다.

function register(uint _name, uint_value) internal {
	if !this.storage[_name] {
		this.storage[_name] = _value }}
4) 분산형 파일 저장소 - 비금융 어플리케이션

데이터를 저장하는 방식은 다음과 같다

1) 유저가 업로드하려는 데이터를 블록으로 자른다.
2) 보호를 위해 해당 데이터를 암호화한다
3) 데이터로 머클트리를 만든다.

위 데이터에 대한 컨트랙트는 다음과 같은 방법으로 유지된다.

1) N개의 블록마다 무작위 방식으로 머클트리의 인덱스를 선택한다
2) 유저가 올린 파일에 해당하는 트리의 특정 인덱스에 대하여 해당 데이터를 저장해주겠다는 첫 주체에게 x 이더를 지불한다.

이러한 방식은 개인이 본인의 하드드라이브에 데이터를 저장해주는 것을 통해 돈을 벌 수 있도록 한다. 또한 사용자는 업로드한 파일을 수많은 암호화된 조각으로 잘라내서 여러 노드들과 공유하고 외부 노드들이 내가 올린 파일을 저장하고 있다는 것을 모니터링함으로써 분실 및 도용을 방지할 수 있다.

5) 탈중화된 자율 조직 - 준금융 어플리케이션

정 인원 수 이상이 동의해야지 어떠한 행동을 할 수 있는 조직
집행의 강제를 위해 암호화 블록체인 기술을 사용한다.

예를 들자면, 특정한 조직에 있는 구성원들은 의사결정에 있어서 모두 동일한 지분을 갖고 있으며, 기존 구성원의 67% 이상의 동의가 있을 때 구성원을 탈퇴시킬 수 있다라고 하자. 그러면은 컨트랙트에 투표 결과가 67% 이상일 때 특정 사람을 탈퇴시킨다는 코드를 작성하면 된다.

추가적인 어플리케이션으로는 예금용 전자지갑, 작물보험, 탈중앙화된 데이터피드, 스마트 멀티시그 공탁 계좌, 클라우드 컴퓨팅, P2P 도박, 예측 시장 등이 있다.

추가 이슈들

1. 수정된 GHOST 도입

현재 블록체인 시스템에서는 높은 스테일 비율로 인해 보안성 저하가 발생되고 있음. 이는 블록들이 네트워크를 통해 전파되는데 일정한 시간이 걸리기 때문. 또한 중앙집중화 이슈도 있다. 중앙집중화란 블록생성주기가 짧은 블록체인 일수록 큰 해시 파워를 가지는 풀에서 채굴을 해야 효율성이 커진다는 것이다. 즉, 해시 파워가 작을수록 스테일 블록이 될 가능성이 높고 이에 따라 독점이 발생할 수도 있다.

스테일 블록: 블록 생성에 성공하였고, 검증 작업 시, 오류가 없어서 네트워크를 통해 전파되었으나, 더 빨리 전파 된 다른 채굴자에 의한 블록에 순위가 밀리는 바람에 주체인에 삽입되지 못한 블록.

이러한 문제를 해결하기 위해 가장 긴 체인을 선택할 때 스테일 블록도 포함해서 계산한다. 이렇게 할 경우 네트워크 보안 손실이라는 문제를 해결한다. 또한 독점 문제를 해결한다.

2. 수수료

모든 트랜잭션은 채굴자만 처리하는 것이 아닌 네트워크의 모든 노드에 의해 처리되어야 한다. 따라서 트랜잭션 처리에 필요한 대부분의 비용은 채굴자가 아닌 제 3자 부담하는 것이다. 그러므로 채굴자들은 트랜잭션 처리 비용을 신경쓰지 않고 함부로 사용하다가 처리 비용이 부족해질 수 있다.

다음과 같은 전제를 해보자

1. 하나의 트랜잭션이 처리하는데 k개의 연산이 필요한데, 이 트랜잭션을 포함하는 채굴자에게 kR 만큼의 보상을 제공하게 된다. 여기서 R은 송신자에 의해서 설정되고, k와 R은 채굴자에게 사전에 노출된다.
-R: 가스 비용
2. 하나의 작업은 어떤 노드에 대해서든 C 만큼의 처리비용을 가진다. (즉, 모든 노드들은 똑같은 효율성을 가지고 있다.)
3. N 개의 채굴 노드들이 있고, 각각은 정확히 똑같은 처리파워 (전체의 1/N)를 가지고 있다.
4. 채굴을 하지 않는 완전노드는 없다.

채굴자는 트랜잭션을 처리할 때 드는 비용보다 트랜잭션을 처리하고 나서 얻는 비용이 클 때 트랜잭션을 처리하고자 할 것이다. 트랜잭션을 처리할 때 드는 비용은 kC이고, 얻는 비용의 기대값은 kR/N이다. (채굴자가 다음 번 블록을 처리할 확률이 1/N)

따라서 kR/N > kC 이거나 R > NC 일 때 채굴자들은 트랜잭션을 처리하고자 할 것이다. NC는 하나의 작업을 처리하기 위해 전체 네트워크에 부과된 비용이므로 채굴자들은 비용보다 전체 공리적인 혜택이 큰 트랜잭션만 포함하려 하는 인센티브를 가지게 된다.

하지만 위의 전제는 현실과는 맞지 않다.

1. 채굴자는 다른 검증 노드들보다 트랜잭션을 처리하는데 더 많은 비용을 지불한다.
-> 채굴자가 더 적은 수의 트랜잭션을 포함하려고 한다.

2. 비채굴 완전노드들이 존재한다.
-> NC를 증가시키게 된다. 1번과 상쇄작용을 하게 된다.

3. 채굴 파워의 분포는 실제로 심각하게 불평등하게 될 수 있다.

4. 악의적인 사람이 존재하고 그들은 다른 검증노드가 지불하는 비용보다 훨씬 적은 비용이 들게 될 그런 컨트랙트들을 교묘하게 만들 수 있다.

3,4 번 문제를 해결하기 위해 플로팅 상한값을 도입한다. 어떤 블록이던지 BLK_LIMIT_FACTOR * 장기 지수 이동평균 보다 더 많은 오퍼레이션들을 가질 수 없다는 것이다.

3. 연산과 튜링완전성

이더리움 가상 머신은 튜링-완전하다. 따라서 무한 루프를 생성할 수 있는데 실제로는 이것이 불가능하다. 왜냐하면 공격자가 무한 루프 트랜잭션을 발생시키면 그와 동시에 실제 실행되는 계산 단계의 상한선을 규정하는 STARTGAS 명령어에 대한 값을 제출해야 한다. 다른 사람들은 STARTGAS 값을 보고 무한 루프에 있다는 것을 알 수 있다.

4. 이더 장기 공급 성장률

매년 신규발행량이 일정함에도 불구하고, 비트코인이 그러한 것처럼, 발행된 총 이더에 대한 신규 이더의 발행률은 그 비중이 0을 향하여 계속 줄어들게 된다.

위의 모델에서 결정되어야 할 두 가지 선택이 있다.

1. 재단보유금의 존재유무 및 규모

재단 보유금이 없다 -> 같은 인플레이션율을 유지하기 위해 연간 발행량을 낮춘다. -> 이더 총량이 감소한다. -> 이더의 가치는 증가하게 된다.

이러한 경우가 발생하면 가치가 올라간 이더는 더 프리세일에서 판매되어야 한다. 그렇게 되면 각 경우의 이더 가치는 동일해져 이전 상황과 다른게 없다.

2. 신규코인을 끊임없이 발행해야 하는지의 여부

정해진 양의 이더를 영구적으로 신규발행하는 모델은 비트코인이 겪고있는 부의 집중현상을 완화시킬 수 있다. 공급성장률은 계속해서 0을 향해 줄어들어 가면서 참여자들이 이더를 시장이 아닌 채굴을 통해 얻을 수 있는 기회를 제공한다.

  • 공급성장률: 신규발행 이더량 / 기발행 이더총량 * 100

나머지는 채굴 중앙집중화,확장성 등이 있다.

0개의 댓글