[Blockchain] 스마트 컨트랙트 - 이더리움

yooni·2022년 3월 10일
1

Blockchain

목록 보기
25/36
post-thumbnail

비탈릭 부테린은 블록체인에 화폐 거래 기록 뿐 아니라 계약서 등의 추가 정보를 기록할 수 있다는 점에 착안하여 스마트 컨트랙트 기능을 구현한 이더리움을 개발했다. 이더리움은 탈중앙 분산 어플리케이션(dApp)을 개발하고 운영할 수 있는 플랫폼이다. 누구나 이더리움 네트워크에 dApp을 배포할 수 있다.

dApp은 익명성, 무국적성, 탈중앙화, 분산화 등 블록체인의 특성을 고스란이 가지고 있어서 국가에서 직접 통제하는 것이 불가능하고 스마트 컨트랙트를 통해 수많은 주체들과 계약을 체결하여 자동화된 경제 생활을 누릴 수 있는 등 많은 가능성을 가지고 있다.

비탈릭 부테린은 이더리움을 이용한 스마트 컨트랙트 기능을 구현하기 위해 솔리디티라는 프로그래밍 언어를 채택했다. 솔리디티는 이더리움 플랫폼 안에 내장되어 있는 프로그래밍 언어로 튜링 완전 언어이다. 어떤 언어가 튜링 언어라는 것은 이 프로그램을 이용하면 어떠한 애플리케이션도 개발할 수 있고, 어떤 계산식도 풀 수 있다는 것을 의미한다. 튜링 완전 언어인 솔리디티를 이용해 어떠한 종류의 스마트 컨트랙트도 코딩할 수 있다. 솔리디티 코드는 이더리움 가상머신(EVM)을 통해 실행할 수 있다.



1. EVM (Ethereum Virtual Machine)

이더리움은 전 세계 수많은 사용자들이 보유하고 있는 컴퓨팅 자원을 활용해 이더리움 가상머신(EVM)을 만들어 실행 환경을 구축했다. 이더리움 네트워크 상의 모든 노드는 EVM을 사용해 모든 스마트 트랜잭션을 실행하고, 모든 노드는 동일한 계산을 수행하며 같은 값을 저장한다. 이렇게 모든 노드들이 동일한 연산을 수행하여 동일한 상태(state)에 합의한다.

스마트 컨트랙트에 기반한 dApp은 솔리디티 언어로 개발되어 있으며, 솔리디티 코드는 EVM을 통해 실행될 수 있다. 하지만 EVM은 고급언어인 솔리디티를 이해할 수 없기 때문에 솔리디티 코드를 컴파일하여 바이트코드 형태로 만든다. EVM은 바이트코드를 Opcode로 변환하여 실행하는 32바이트 스택 자료구조 기반 실행 환경으로 스택의 최대 크기는 1024바이트이다.

EVM은 튜링 완전 언어인 솔리디티로 작성된 코드를 작동시키는 튜링 완전 가상 머신이다. 하지만 일반 튜링 완전 머신과 달리 gas에 종속되어 있기 때문에 실행 가능한 연산은 제공되는 gas의 양에 의해 제한된다.

EVM은 휘발성, 비휘발성 메모리로 구분되어 있으며 휘발성 메모리에는 stack, args, memory가 비휘발성 메모리에는 storage, code가 저장된다.

✔️ 휘발성 메모리

  • stack : OP 코드를 실행하기 위한 스택영역
  • args : 컨트랙트 호출시 넘어 오는 인자를 저장
  • memory : word 단위로 아이템을 저장하는 바이트 배열

✔️ 비휘발성 메모리

  • storage : 상태(state) 저장
  • code : 컴파일된 바이트 코드 저장

✔️ Geth (Go-ethereum)
Go 언어로 개발된 이더리움재단 제공 공식 클라이언트 소프트웨어이다. 게스는 블록체인의 복사본을 최신 상태로 유지하기 위해 끊임없이 다른 노드와 통신한다. 또한 블록을 채굴하고, 블록체인에 트랜잭션을 추가하고 블록의 트랜잭션을 검증하며 트랜잭션을 실행할 수도 있다. 이더리움 가상머신(EVM)을 만들 수 있는 프로그램이다.

✔️ 바이트코드 (Bytecode)
Opcode를 효율적으로 저장하기 위해, Opcode는 바이트코드로 인코딩된다.



2. 솔리디티 (Solidity)

이더리움 네트워크에서 스마트 컨트랙트 작성과 구현에 사용되는 계약 지향 프로그래밍 언어이며, dApp을 개발하기 위한 핵심 프로그래밍 언어이다.

솔리디티는 정적타입의 프로그래밍 언어로 스마트 컨트랙트를 작성하기 위한 언어로 EVM을 타깃으로 디자인되었다. 솔리디티는 EVM에서 작동 가능한 바이트코드로 컴파일 된다.

개발자는 솔리디티를 통해 스스로 비즈니스 로직을 만들어 스마트 컨트랙트에 담아 구현할 수 있다. 블록체인 특성상 블록체인에 올라간 스마트 컨트랙트는 수정할 수 없고 누구나 확인할 수 있기 때문에 신중하게 작성해야 한다.


❓ 튜링 완전 언어

튜링은 수학자 앨런 튜링에 의해 제시된 개념으로, 계산하는 기계의 일반적인 개념을 설명하기 위한 가상의 기계를 의미한다. 튜링머신이란 모든 수학문제를 해결할 수 있는 일반적인 알고리즘을 만들어낼 수 있는 튜링 완전 언어와 무한한 저장공간이 합쳐져 모든 문제를 계산해내는 기계이다. 튜링 완전 언어는 튜링머신에 넣어야 할 알고리즘을 만들 수 있는 언어이다. 튜링 완전 언어는 프로세스를 충분히 분할할 수 있을 만큼 작은 단위를 사용할 수 있어야 하며 조건 설정과 반복 명령어가 있어야 한다.

1세대 블록체인인 비트코인은 스마트 컨트랙트를 위해 스크립트 언어를 제공한다. 스크립트는 많은 연산을 수행할 수 있지만 의도적으로 조건문과 반복문의 사용을 제한하고 있다. 따라서 비트코인의 스크립트는 튜링 불완전한 언어이다. 스크립트 언어는 다용도로 쓰일 수 없고 비트코인에 제한되는 동시에 비트코인 거래 안에서 무한 루프를 구현하거나 논리 폭탄의 복잡한 형태를 구현하기 어렵다. 비트코인 스크립트에서 반복문의 사용을 의도적으로 제한한 이유는 DOS 공격과 악용의 사례를 방지하기 위함이었다.

2세대 블록체인 이더리움은 코드 작업마다 가스(Gas)라는 수수료를 부과하여 튜링 완전성을 확보하였다. 연산 부호마다 가스 가격이 책정되어 있으며 처음 코드를 설계할 때 가스량을 정할 수 있다. 가스가 부족하면 코드를 끝까지 실행시킬 수 없다. 따라서 반복문을 계속 실행하기 위해서는 이에 비례하는 양의 가스가 필요하여 무한정 이더를 소모해야 한다. 따라서 무한 루프문을 통한 악용을 방지할 수 있다.



3. 상태 머신 (State Machine)

이더리움은 트랜잭션에 기반한 상태머신이다.

특정 상태로부터 다음 상태로 넘어가기 위해서는 반드시 해당 트랜잭션이 유효한 트랜잭션이어야만 한다. 만약 특정 트랜잭션이 유효하다면 채굴이라고 불리는 증명 과정으로 넘어간다.

트랜잭션은 이더리움 전역 상태를 다음 상태로 이동시킨다.
트랜잭션 실행 = state 변화

즉, 이더리움에서 특정 트랜잭션의 유효성을 검증한 후 새로운 블럭을 만들어 해당 블럭에 새로운 트랜잭션을 기록하면 상태가 변경된다. 이더리움은 단일한 상태 변이 과정에 관련된 트랜잭션들과 상태 정보를 하나의 블록으로 구성하고, 이 블록을 시간순으로 연결하며 단일 상태를 유지한다.

특정 시점에서 유효한 상태 S는 단일한 글로벌 신뢰 지점이다. 또한 이러한 신뢰는 해당 네트워크에 참여한 모든 사람이 동의해야 가능해진다. 특정 시점에서 유효한 상태 혹은 체인이 여러개라면, 시스템을 혼란스럽게 하고 사람들에게 유효한 체인을 선택하도록 해야하기 때문에 이를 피하는 것이 좋다.


전역 상태 (Global State)

이더리움의 전역 상태 정보는 어카운트 주소와 어카운트 간의 맵핑으로 구성되며 머클 패트리샤 트리의 형태로 저장되어 있다.

✔️ 머클패트리샤 트리
트리 구조를 형성하고 있는 암호화 과정이다. 거래에 대한 해시값이 리프이고, 이를 두 개씩 묶어 더한 후 같은 방식으로 진행하여 최종 값인 머클루트를 얻는다. 거래의 원본이 아닌 해시값을 이용하는 것은, 위변조에 대한 검증이 손쉽게 가능하기 때문이다. 위변조 방지라는 장점 외에도 '어떠한 거래가 들어있다'고 확인하는 탐색을 빠르게 할 수 있다.
이더리움 블록 헤더에는 총 3가지의 머클 패트리샤 트리를 사용하는데 그 중 하나가 상태 트리이다.

  • 상태 트리 (State tree)
  • 트랜잭션 트리 (Transaction tree)
  • 영수증 트리 (Receipt tree)



4. Account - EOA, CA

이더리움의 상태(state)는 어카운트 객체들의 집합이다. 어카운트는 메시지 전달 프레임워크를 통해 다른 어카운트와 상호작용한다. 계정(어카운트)은 두 가지 종류가 있다.


4-1. 어카운트의 종류

  • 외부 소유 계정 (EOA, Externally Owned Account)
    개인키로 제어되는 계정으로 코드를 저장할 수 없다. EOA는 다른 EOA 또는 CA에 메시지를 보낼 수 있으며 이를 위해 개인키를 사용하여 트랜잭션을 생성하고 서명한다. 두 개의 EOA 사이에서 발생하는 메시지는 단순히 ETH만을 전송한다. EOA에서 CA에 보내는 메시지는 CA에 저장된 코드를 활성화시킨다. 이더리움 블록체인의 모든 기능은 EOA가 날린 트랜잭션으로부터 시작된다.

  • 계약 계정 (CA, Contract Account)
    EOA와 달리 개인키를 가지고 있지 않으며 스스로 새로운 트랜잭션을 개시할 수 없다. CA는 다른 CA 또는 EOA로부터 받은 트랜잭션에 대한 응답으로만 트랜잭션을 실행할 수 있다.

EOA는 누군가 소유한 지갑과 같은 계정이며 CA는 배포된 코드와 저장공간이 추가로 존재하며 스마트 컨트랙트 역할을 수행한다. EOA가 상위 계정이며 새로 생성되는 트랜잭션은 모두 EOA에서 시작한다. EOA에서 컨트랙트와 관련된 트랜잭션을 만들면 CA에서 받아서 처리하는 것이다.


4-2. 어카운트의 구성 요소

EOA, CA 모두 동일하게 4가지 구성 요소로 이루어져 있다.

  • Balance
    어카운트가 소유하고 있는 이더 잔고(정확히는 Wei의 양)이다.

  • Nonce
    EOA의 경우 Nonce는 해당 어카운트의 주소로부터 보내진 트랜잭션의 숫자를 의미하며 CA의 경우 Nonce는 해당 어카운트에 의해 생성된 컨트랙트의 숫자를 의미한다. Nonce는 숫자를 세는 일종의 카운터 역할을 한다.

  • StorageRoot
    머클 패트리샤 트리의 루트 노드를 해시한 값이다.

  • Contract Code
    EVM에서 실행될 코드를 해시한 값이다. EOA의 경우, 코드를 저장할 수 없기 때문에 비어있는 문자열이다.


4-3. 트랜잭션과 메시지

트랜잭션EOA에서 이루어진다.

EOA가 스마트 컨트랙트를 만들어 보내면 CA가 그것을 받아 자동적으로 처리한다. CA는 코드화된 계약에 의해서만 움직이고 EOA가 마음대로 변경할 수 없다. CA는 어떠한 새로운 계약도 만들어낼 수 없다. EOA가 만든 계약을 실행시킬 뿐이다. 모든 계약에는 이것이 참이라는 인증이 들어가야 하는데 이더리움 블록체인에서는 개인키를 통한 서명이 그러한 인증을 담당하고 개인키를 가진 EOA만이 서명이 가능하다.

트랜잭션은 EOA가 메시지를 시스템에 전달하는 방법이기도 하다. 모든 트랜잭션은 외부 세계를 이더리움 내부의 상태(state)로 연결하는 다리와도 같다. 그 연결의 창구 역할을 담당하는 것이 CA이다. 트랜잭션은 EVM에 이더 전송, 신규 계약 생성, 기존 계약 활성화, 특정 계산 수행 등을 알린다.

메시지CA에서 CA로 전달되는 데이터 덩어리이다.

CA는 메시지나 내부 트랜잭션을 통해 다른 CA와 상호작용할 수 있다. 트랜잭션과 매우 유사하지만 EOA에서는 생성되지 않으며 오직 CA에게서만 생성된다. CA는 EOA가 하는 유사한 방식으로 다른 CA와 관계를 맺는다.

메시지는 블록체인에 저장될 필요가 없고 가상의 객체로 EVM에서만 존재한다. 메시지는 트랜잭션과 달리 EVM 내부에서만 존재하므로 가스 비용이 발생하지 않는다. 이더리움 네트워크에서 채굴자가 수수료를 지불하는 동작은 채굴자의 계정 잔액을 증가시키는 메시지를 통해 이루어지며 이는 트랜잭션을 구성하지 않는다.



5. 이더리움 스마트 컨트랙트 생성

Geth와 같은 이더리움 클라이언트는 이더리움 블록체인에 참여하는 노드이다. 블록이 생성되면 그 정보를 정파받는 역할을 한다. 따라서 동기화된 블록체인 데이터를 가지고 있어야 한다. 이더리움 클라이언트는 블록체인 네트워크의 노드이면서 일반 사용자의 접속을 허용하고 블록체인과 연결시켜주는 역할까지 담당한다. 일반 사용자는 클라이언트에 접속하여 블록체인 정보를 얻거나 스마트 컨트랙트를 사용할 수 있다.

블록체인 상의 모든 노드들은 동일한 스마트 컨트랙트 코드를 가지고 있다. 어떤 사용자가 생성한 스마트 컨트랙트 코드는 블록에 기록되어 다른 노드에서도 복사된 코드를 갖게 된다. 따라서 각 노드의 EVM에서 코드를 실행시킬 수 있다.


5-1. 스마트 컨트랙트 생성 과정

스마트 컨트랙트를 생성하는과정은 다음과 같다.

솔리디티로 스마트 컨트랙트 코딩 → 소스코드를 바이트코드로 컴파일 → 스마트 컨트랙트 배포


1. 솔리디티를 이용하여 스마트 컨트랙트 코딩

2. 구현한 소스 코드를 컴파일 하여 바이트코드 생성

솔리디티를 이용해 구현한 소스 코드를 컴파일 하여 EVM 바이트 코드를 생성한다. remix나 geth의 solidity 컴파일러로 컴파일을 수행할 수 있다. 컴파일된 바이트코드는 기계만 이해할 수 있는 코드이다.

3. 스마트 컨트랙트 배포

컴파일된 바이트코드를 배포하기 위해서는 ABI가 필요하다. remix를 사용하는 경우 소스 코드를 바이트코드로 컴파일 할 때 자동으로 얻어지지만 geth를 사용한다면 직접 생성해야 한다. ABI로부터 스마트 컨트랙트 객체를 생성할 수 있다.

ABI (Application Binary Interface)
컨트랙트의 함수와 매개변수들을 JSON 형식으로 나타낸 리스트이다. ABI는 보통 두 프로그램 모듈의 인터페이스 역할을 한다. ABI는 데이터를 기계어로 인코딩/디코딩 하기 위한 방법이다. 이더리움에서는 EVM에 스마트 컨트랙트를 호출할 때 인코딩을 하거나 트랜잭션들로부터 데이터를 읽는 방법이다.

ABI로부터 생성된 스마트 컨트랙트 객체를 실제로 블록 내용에 포함시켜 채굴되어 블록체인에 포함되도록 한다. 이렇게 스마트 컨트랙트가 블록체인에 포함되면 생성한 스마트 컨트랙트에 접근할 수 있는 주소가 생성될 것이다.

스마트 컨트랙트 객체로부터 인스턴스를 하나 만들고 최초 배포시에만 생성자에 입력될 매개변수를 넣어준다. 매개변수와 함께 스마트 컨트랙트를 하나의 트랜잭션처럼 생성한다. 이 때 트랜잭션의 송신자, 바이트 코드, 사용될 예상 gas량을 같이 입력한다. 이후 채굴자가 스마트 컨트랙트가 포함된 블록을 채굴하게 되면 스마트 컨트랙트 주소가 생성된다.

스마트 컨트랙트가 일반 트랜잭션과 다른 점은 바이트코드를 input으로 받는다는 점과, 수신자가 없다는 점이다. 스마트 컨트랙트는 계약을 생성한 송신자가 특정 수신인 지정 없이 자신이 생성한 컨트랙트 코드를 블록체인에 올리는 것이기 때문이다.


5-2. 스마트 컨트랙트 접근 및 사용

스마트 컨트랙트가 블록체인에 올라가면 블록체인 상의 모든 노드는 해당 스마트 컨트랙트의 바이트코드를 가지게 된다. 각 노드(이더리움 클라이언트)는 해당 스마트 컨트랙트를 자신의 EVM에서 실행시킬 수 있다. 어떤 노드에서 스마트 컨트랙트의 내용을 변경시키는 명령은 새로운 트랜잭션을 발생시킨다. 다른 노드가 컨트랙트에 접근하면 바뀐 내용을 얻게 된다.


5-3. 스마트 컨트랙트 호출

이더리움의 스마트 컨트랙트는 이더리움의 상태를 변경할 수 있는 프로그램 코드이다. 블록에 포함되어 각 노드에 전파되고 EVM에서 작동되어 상태 전이를 발생시킨다. 즉 스마트 컨트랙트는 블록헤더의 데이터 뿐 아니라 특정 값이나 발신자 및 수신되는 메시지의 데이터를 조작하는 등 이더리움의 상태 변화와 데이터 저장 등이 가능한 프로그램 코드이다.


❓ 스마트 컨트랙트는 언제/어떻게 실행될까?

  • 새로운 스마트 컨트랙트를 생성할 때
  • 특정 스마트 컨트랙트상의 함수를 실행할 때
  • 이더를 전송하는 방식 중의 하나로 실행될 때

EOA에 의해 발생한 트랜잭션이나 다른 컨트랙트에 의해서만 실행된다.


스마트 컨트랙트는 무한반복과 같은 악의적 코드의 실행을 막고 데이터의 무결성을 지키기 위해 모든 트랜잭션을 실행할 때 비용을 지급하도록 규정한다. 모든 트랜잭션의 기본 실행 비용은 21,000가스이다. 이 비용에는 다음과 같은 것들이 포함된다.

  • 발송자 Account 주소에 대한 ECDSA를 위한 비용
  • 트랜잭션 저장을 위한 스토리지 비용
  • 네트워크 대역폭 비용



6. 스마트 컨트랙트 실행 비용

이더리움은 튜링 완전 언어이기 때문에 반복문을 지원한다. 이로 인해 무한 루프가 발생할 수 있고 악의적인 사용자가 무한 루프 트랜잭션을 실행시킨다면 이더리움 네트워크 상의 엄청난 자원을 소모하여 악영향을 끼칠 수 있다. 이러한 악의적 공격으로부터 이더리움 네트워크를 보호하기 위해 각 연산에 대한 수수료를 부과하고 있다. 수수료를 부과함으로써 악의적인 공격을 차단할 수 있고, 설령 의도치 않게 무한루프를 실행시키더라도 Gas Limit까지만 가스를 소모하고 멈출 수 있다.

✔️ Gas (가스)
이더리움 트랜잭션의 결과로 발생하는 모든 Opcode 실행에 대한 수수료

가스 가격은 이더의 하위 단위인 기가웨이(Gwei)로 계산된다. 이더리움 거래시 데이터를 옮기기 위해 채굴자들의 연산 작업이 필요한데 이들이 한 계산에 대한 보상으로 이더리움 가스를 제공한다. 즉 채굴자들은 채굴을 통해 채굴 보상과 연산 작업 보상을 함께 받는 것이다.


ether의 기본 단위

이더리움의 가장 작은 단위는 wei이다. Gwei는 가스 비용을 계산할 때 주로 사용한다.

1 ether = 10^18 wei
1 Gwei = 10^9 wei


Max Transaction Fee

이더리움에서 어떤 트랜잭션을 실행하는데 사용자가 지불해야 하는 수수료를 최대 트랜잭션 비용이라고 한다. 트랜잭션을 실행하려면 사용자 계정에 있는 이더 잔액이 최대 트랜잭션 비용보다 많아야 한다.

  • Gas Limit
    트랜잭션을 실행하는 데 예상되는 총 가스량이며, 송신자가 지불하고자 하는 가스의 최대값이다.

  • Gas Price
    1가스당 가격이다. 이 가격이 높을수록 마이너들이 보상을 많이 받기 때문에 트랜잭션이 빨리 처리된다.

송신자는 트랜잭션 완료 후 사용되지 않은 가스를 기존 비율로 환불받는다. 송신자가 트랜잭션을 실행할 만한 충분한 가스를 제공하지 않은 경우라면 트랜잭션은 OOG 상태가 되어 실행이 중지된다. 상태는 트랜잭션이 실행되기 이전의 상태로 돌아가고 실패한 트랜잭션에 대한 기록이 남는다. 트랜잭션은 실패했지만 EVM은 연산을 수행했기 때문에 사용된 가스는 환불되지 않는다. 이 가스 수수료는 자원을 소모한 것에 대한 보상으로 채굴자에게 송금된다.

채굴자들은 수수료를 많이 받을 수 있는 트랜잭션을 선택하려고 한다. 채굴자들은 트랜잭션 송신자가 설정해야 할 Gas Price의 최소값을 광고하기도 한다.



📌 Reference
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=mage7th&logNo=221561274756
https://hersheythings.xyz/entry/ethtereumstructure
https://opentutorials.org/course/2869/19273
https://medium.com/pocs/ethereum-abi%EC%99%80-%EA%B4%80%EB%A0%A8%EB%90%9C-q-a-%EC%A0%95%EB%A6%AC-40e639ee1a03
https://ihpark92.tistory.com/50
https://steemit.com/kr/@brownbears/ethereum-account-transaction-message
https://steemit.com/kr/@feyee95/5lzztc
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=lool2389&logNo=221286888653
https://cheonmro.github.io/2019/03/22/icon-unit/

profile
멋쟁이 코린이

0개의 댓글