TIL 36 - 스마트 컨트랙트란?

프동프동·2023년 2월 10일
0

TIL

목록 보기
36/46
post-thumbnail

스마트 컨트랙트를 설명할 수 있다.

블록체인 네트워크에 호스팅되고 실행되는 프로그램이다.
조건을 지정해두고, 해당 조건이 충족되면 미리 정해둔 계약을 이행하는 방식으로 코드를 작성한다.

스마트 컨트랙트의 역사를 알 수 있다.

1994년 닉재보(Nick Szabo)에 의해 만들어졌다.

"계약 조건을 실행하는 전산화된 트랜잭션 프로토콜"은 "일반적인 계약 조건을 만족하고, 악의적이거나 우발적인 예외를 최소화하며, 신뢰할만한 중개자의 필요성을 최소화하는 것"을 목표로 한다.

닉 재보는 스마트 컨트랙트를 위한 비트 골드를 제안했으나, 기술적 한계로 인해 실제로 구현되지는 못했다.

스마트 컨트랙트를 실제로 지원하기 시작한 첫 화폐는 비트코인이다.
스크립트 언어를 사용하여 화폐 거래와 관련된 특정 로직을 설정할 수 있다.
본질적으로 비트코인은 전자 화폐를 중점으로 둔 시스템이기에 제한적인 프로그래밍만 가능했다.

이후 프로그래밍이 가능한 이더리움이라는 블록체인이 등장하였다
이더리움에서는 솔리디티라는 언어를 통해 스마트 컨트랙트를 위한 코드를 작성하고, EVM을 통해 이더리움 블록체인 위에서 코드를 실행시킬 수 있다.

스마트 컨트랙트의 동장 방식을 알 수 있다.

if or when (이벤트 x가 실행되면) {  // 조건
	액션 y를 실행하라  // 계약 이행
}
  1. 코드가 블록체인 네트워크에 올라가면
  2. 네트워크는 미리 제시된 조건이 충족되고, 검증된 경우 조건에 따른 액션을 실행한다.
  3. 이러한 액션은 트랜잭션에 기록되며
  4. 완료된 트랜잭션은 블록체인에 올라간다.

비트코인에서의 스마트 컨트랙트를 설명할 수 있다.

스크립트를 사용해 스마트 컨트랙트를 구현한다.
간단한 연산 목록으로 구성되어 있으며 스크립트에서 사용하는 연산들은 Opcode에 해당한다.
스크립트는 트랜잭션에 연결되어 있으며 네트워크의 모든 노드는 트랜잭션을 받을 때마다 자신의 로컬 컴퓨터에서 트랜잭션에 연결된 스크립트를 실행하며 이를 통해 송금이 이루어진다.

입력과 출력의 구조

입력 구조에 있는 Prev. TxID와 TxIndex는 해제하고자 하는 이전 출력을 가리킵니다. ScriptSig는 이전의 출력을 해제하는 키입니다.

💡 입력 구조

  • Prev. Tx ID, TxIndex: 해제하고자 하는 이전의 출력을 가리키는 포인터
  • ScriptSig: 이전의 출력을 해제하는 키

💡 출력 구조

  • ScriptPubkey: 잠금. ScriptPubkey의 소유자(해당 공개 키의 소유자)만이 ScriptSig를 만들 수 있습니다.
  • Amount: 잠긴 비트코인의 양 (단위:사토시)

비트코인 스마트 컨트랙트의 동작 원리를 이해할 수 있다.

스크립트는 역폴란드 표기법으로 작성된 스택 기반 튜링 불완전 언어

스택 구조로 작동한다.

스크립트 프로그램은 두 종류의 객체를 가지고 있습니다.

  • Opcode: 덧셈, 뺄셈, 곱셈과 같은 연산 작업을 나타냅니다.
  • 데이터: Opcode가 아닌 모든 데이터는 원시 데이터로 해석되며, 스택에 들어가게 됩니다.

💡 Opcode란?
Opcode는 로우 레벨 기계 언어로, 약 140 종류의 연산이 있습니다. Opcode의 연산 종류는 다음과 같습니다.

  • 스택 조작 연산: POP, PUSH, DUP, SWAP
  • 산술/비교/비트연산: ADD, SUB, GT, LT, OR
  • 환경 연산: CALLER, CALLVE, NUMBER
  • 메모리 조작 연산: MLOAD, MSTORE, MSTORE8, MSIZE
  • 스토리지 조작 연산: SLOAD, SSTORE
  • 프로그램 카운터 관련 연산: JUMP, JUMPI, PC, JUMPDEST
  • 작업 중지 연산: STOP, RETURN, REVERT, INVALID, SELFDESTRUCT
  • 스크립트 성공 시
    • 스택 상단에 있는 요소는 1이 된다.
  • 스크립트 실패 시
    • 스택 최상단에 있는 요소가 1이 아닌 다른값이 있다면 스크립트 실행을 실패한 것으로 간주한다.

스크립트가 성공하여 최상단 요소가 1일 경우 트랜잭션이 유효하다는 것으로 간주하고 주변 노드들에게 전파한다.

자주 쓰이는 비트코인 스크립트

  • Pay To PubKey(P2PK)

    • 퍼블릭 키에 직접 코인을 송금하는데 사용

      • 보안에 취약하여 쓰이지 않는다.
    • 자세한 순서
      자세한 순서는 다음과 같습니다.

      1. 빈 스택에서 포인터가 서명을 가리킵니다.

      2. 서명은 데이터이므로 스택에 들어갑니다. 포인터는 그다음 요소인 공개 키를 가리킵니다.

      3. 공개 키도 데이터이니 스택에 넣습니다. 포인터는 이제 OP_CHECKSIG를 가리킵니다.

      4. OP_CHECKSIG는 스택에서 아이템 두 개(공개키와 서명)를 꺼내는 Opcode입니다. OP_CHECKSIG는 스택에서 공개키와 서명을 꺼내고, ECDSA 알고리즘을 사용해 서명을 검증합니다. 만약 검증에 성공하면 1, 실패하면 0을 스택에 넣습니다.

        ECDSA 알고리즘 (ECDSA; Elliptic Curve Digital Signature Algorithm)은 타원곡선 알고리즘에 디지털 서명을 추가한 알고리즘입니다. 비트코인과 이더리움에서 서명을 검증할 때 사용합니다.

      5. 검증을 마치고 스택에 1이 들어있으면, 트랜잭션 검증이 완료되고 UTXO가 해제됩니다.

        스크립트가 성공적으로 실행되면 트랜잭션은 유효한 것으로 간주됩니다. 이전 UTXO가 소비되고, 해당 트랜잭션의 출력 목록에 따라 새로운 UTXO가 생성됩니다.

  • PayToPubKeyHash(P2PKH)

    • P2PKH는 P2PK 메커니즘과 거의 동일하며, 한 가지 차이점은 P2PKH에서는 ScriptPubkey가 공개 키의 해시값을 가지고 있다는 점

    • 자세한 순서

      자세한 순서는 다음과 같습니다.

      1. 빈 스택에서, 포인터는 서명을 가리킵니다.

      2. 서명은 데이터이기 때문에 스택에 들어가고, 포인터는 다음 요소인 공개 키를 가리킵니다.

      3. 공개 키도 데이터이기 때문에 스택에 들어가고, 포인터는 다음 요소인 OP_DUP을 가리킵니다.

      4. OP_DUP은 스택 최상단 요소를 복사하는 Opcode입니다. OP_DUP이 실행되면 스택에는 공개 키가 두 개 쌓이게 됩니다. 포인터는 다음 요소인 OP_HASH160을 가리킵니다.

      5. OP_HASH160은 스택 최상단 요소를 해싱하는 Opcode입니다. 최상단에 있는 공개 키가 해싱되어 Hash 2가 됩니다. 포인터는 다음 요소인 Hash 1을 가리킵니다.

      6. Hash 1은 데이터이기 때문에 스택에 쌓입니다. 포인터는 다음 요소인 OP_EQUALVERIFY를 가리킵니다.

          
      7. OP_EQUALVERIFY는 스택에 있는 두 요소가 같은지 확인하는 op_code입니다. 만약 두 요소가 같다면, 해당 요소 두 개를 제거하고, 다르다면 실행에 실패하게 됩니다.
        만약 ScriptSig에 올바른 공개 키가 들어있었다면 ScriptPubkey에 들어있던 Hash 1과 공개키를 해싱한 값인 Hash 2가 동일할 것이고, 스택에서 제거됩니다.
        이제 포인터는 다음 요소인 OP_CHECKSIG를 가리킵니다.

      8. OP_CHECKSIG는 앞서 P2PK와 동일하게 동작합니다. ECDSA 알고리즘으로 서명을 검증하고, 서명이 올바르다면 스택에 1을 쌓습니다.

        실행이 완료되고 1이 남아있다면 검증이 성공한 것이고, UTXO가 해제됩니다.

        P2PKH는 서명에 대해 공개 키로 검증을 한다는 점에서는 P2PK 스크립트와 동일하지만, 공개 키가 아닌 공개 키 해시값을 사용한다는 점에서 우회적인 방식으로 좀 더 좋은 프라이버시를 제공합니다.

        P2PK와 P2PKH라는 기본적인 비트코인 스크립트의 동작방식을 살펴보았습니다. 이러한 기존에 작성된 스크립트 외에도 직접 스크립트를 작성할 수도 있습니다. 직접 작성한 스크립트는 regtest라는 비트코인 테스트 네트워크에서 테스트할 수 있으며, btcdeb라는 CLI를 사용해 스크립트를 디버깅 할 수도 있습니다.

비트코인 스크립트가 스마트 컨트랙트인 이유

UTXO는 일종의 “계약”으로 정의될 수 있으며, 이 계약은 유효한 해제 조건이 주어지면 잠긴 비트코인을 이동시킨다.

이더리움에서의 스마트 컨트랙트를 설명할 수 있다.

EVM과 솔리디티를 이해할 수 있다.

EVM이란?

EVM 계층

모든 Peer는 EVM이라는 Virtual Machine을 가지고 있어야한다.

이더리움 스마트 컨트랙트에 기반한 dApp은 솔리디티라는 언어로 작성된다.

솔리디티로 작성된 dApp을 이더리움 네트워크에 올려야한다.

솔리디티는 고급 언어이기에 EVM이 해석하기 어렵다 → EVM은 기계이기 때문에 바이트코드로 변환해줘야한다.

  1. 작성한 솔리디티 코드를
  2. solc를 이용해 컴파일하여 EVM이 읽을 수 있는 바이트코드 형태로 만든다.
  3. 바이트 코드를 이더리움 클라이언트(Geth)를 이용해 이더리움 네트워크에 올린다.

솔리디티 코드 → 바이트 코드 → Opcode

스마트 컨트랙트 작동 플로우

스마트 컨트랙트 배포 플로우

블록체인에 저장된 바이트 코드 형태의 dApp은 EVM에서 실행하게 되며, EVM에서는 바이트 코드를 Opcode로 변환하여 실행한다.

바이트코드 동작방식

내부적으로 EVM은 명령어 집합(Opcode)을 사용하여 특정한 작업을 실행합니다.
모든 Opcode에는 1바이트가 할당됩니다.
100개가 넘는 고유한 Opcode가 있으며, 이는 충분한 리소스만 있다면 무엇이든 계산할 수 있습니다.

Opcode를 크게 7가지로 나눈다면 이렇습니다:

  • 스택 조작 : POP, PUSH, DUP, SWAP

  • 산술/비교/비트 연산 : ADD, SUB, GT, LT, AND, OR

  • 환경 : CALLER, CALLVALUE, NUMBER

  • 메모리 조작 : MLOAD, MSTORE, MSTORE8, MSIZE

  • 스토리지 조작 : SLOAD, SSTORE

  • 프로그램 카운터 : JUMP, JUMPI, PC, JUMPDEST

  • 중지 : STOP, RETURN, REVERT … etc
    가령 STOP 은 0x00입니다.

예를 들어 0x6001600101이라는 바이트코드가 있다고 합시다.

코드가 실행되면 바이트코드는 바이트로 쪼개집니다. (1 바이트는 2개의 16진수 문자입니다. 0x60~0x7f(opcode PUSH1 ~ PUSH32) 사이의 바이트는 데이터를 스택에 넣기 때문에 다른 Opcode와는 다르게 처리됩니다.

  • 0x60 01 | 60 01 | 01

첫 번째 명령어의 첫 번째 바이트 0x60PUSH1 연산입니다.
PUSH1 연산 뒤에는 스택에 추가할 데이터가 옵니다. 따라서 명령어의 두 번째 바이트 0x01을 스택에 추가합니다.
두 번째 명령어는 첫 번째 명령어(0x60)와 같기 때문에 동일하게 스택에 0x01이 쌓입니다.
세 번째 명령어 0x01은 ADD 연산입니다. 이 연산은 스택에서 요소 두 개를 꺼내오고 두 요소의 합을 스택에 추가합니다. 스택에서 0x01, 0x01 두 개를 꺼내오고 더한 결과 값 0x02를 스택에 추가합니다.

EVM의 내부 동작 구조

거래에 기반을 둔 상태머신(transaction-based state machine)
상태 머신이란 일련의 입력을 읽고, 그 입력을 기반으로 새로운 상태로 전환하는 것을 의미한다.
상태 머신은 Genesis state에서 시작한다. 그리고 트랜잭션이 실행되면, 다음 상태로 전환하게 된다. 더이상 트랜잭션이 들어오지 않은 마지막 상태가 바로 이더리움의 현재 상태

이더리움의 상태 관리

State 기반 Account

  • JVM과 같이 어떤 환경에도 구애받지 않고 모든 노드에서도 쉽게 스마트 컨트랙트를 실행하고 동작하도록 제공하기 위함
  • Account Field에는 아래 4가지가 있다. 그중 스토리지가 EVM의 World state 값으로 들어간다.
    • Nonce
    • 사용자의 잔액
    • 코드 해시값
    • 스토리지(account)
  • EVM Code
    • 실제 스마트 컨트랙트 코드를 컴파일한 바이트 코드

솔리디티(Solidity)

솔리디티는 스마트 컨트랙트를 실행하는 객체 지향, 정적 타입, 고급 스크립트 언어로 EVM 위에서 실행된다.

  • 튜링 완전 언어이다
    • 튜링 완전 언어란
      어떤 프로그래밍 언어나 추상 기계가 튜링 머신과 동일한 연산 능력을 갖출 때, 우리는 그것이 튜링 완전(Turing-Complete)하다고 말합니다.
      반대로 튜링 머신보다 연산 능력이 떨어질 경우 튜링 불완전(Turing-Incomplete)하다고 합니다.
      일반적으로 아는 컴퓨터 언어들처럼 기본적인 연산과 조건문, 반복문 등을 모두 수행할 수 있는 기계 정도로 이해하시면 됩니다.
      사토시 나카모토는 무한 반복 공격과 같은 보안상의 이슈를 고려해 의도적으로 반복문 Opcode를 제외했습니다. 따라서 비트코인 스크립트를 두고 튜링 불완전하다고 말합니다.

스마트 컨트랙트의 동작 원리를 이해할 수 있다.

스마트 컨트랙트의 활용 사례를 설명할 수 있다.

  • Defi
  • 게임과 NFT
  • DAO
  • ICO
  • 브릿지(Bridge)

활용 사례

일정한 형식의 반복적인 계약이 많은 경우

원격자 간 계약 체결이 필요한 경우

제품의 유통 추적이 필요한 경우

그 외 : 저작권 등

profile
좋은 개발자가 되고싶은

0개의 댓글