블록체인: EVM과 바이트 코드

독수리박박·2024년 5월 20일
0

EVM (Ethereum Virtual Machine)


EVM은 이더리움 블록체인의 스마트 계약을 실행하는 분산 컴퓨팅 환경입니다. EVM은 분산된 상태에서도 동일한 결과를 보장하기 위해 설계되었습니다. 모든 이더리움 노드는 EVM을 실행하며, EVM은 스마트 계약을 바이트코드로 실행합니다.

바이트코드(Bytecode)


바이트코드는 고급 프로그래밍 언어(예: 솔리디티)로 작성된 스마트 계약이 컴파일된 후 생성되는 저수준 코드입니다. 이 바이트코드는 EVM이 이해하고 실행할 수 있는 명령어(opcode)로 구성됩니다.

EVM이 바이트 코드를 처리하는 방식은 CPU가 명령어를 처리하는 과정과 비슷하지만 EVM은 명령어(opcode)들을 순차적으로 실행하면서 파라미터나 연산의 결과 값을 스택(메모리)에 저장하면서 명령어들을 실행한다는 차이점이 있습니다.

바이트코드 생성 과정

  • 스마트 계약 작성: 개발자는 솔리디티(Solidity)와 같은 고급 프로그래밍 언어로 스마트 계약을 작성합니다.
  • 컴파일: 솔리디티 컴파일러(solc)를 사용하여 스마트 계약을 컴파일합니다. 이 과정에서 스마트 계약은 바이트코드와 ABI(Application Binary Interface)로 변환됩니다.
  • 배포: 바이트코드는 이더리움 블록체인에 배포됩니다. 배포된 스마트 계약은 특정 주소를 가지게 됩니다.
  • 실행: 사용자가 스마트 계약을 호출하면, EVM은 해당 스마트 계약의 바이트코드를 읽고 실행합니다.

바이트코드의 구성

바이트코드는 연속된 명령어 집합으로, 각 명령어는 특정한 작업을 수행합니다. 예를 들어, PUSH, POP, ADD 등의 명령어가 있습니다. 이 명령어들은 EVM 스택에서 작동합니다.

예시 코드

pragma solidity ^0.8.0;

contract SimpleStorage {
    uint256 storedData;

    function set(uint256 x) public {
        storedData = x;
    }

    function get() public view returns (uint256) {
        return storedData;
    }
}

위 예시코드를 EVM이 이해할 수 있는 바이트 코드로 컴파일하면 아래와 같은 바이트 코드가 생성됩니다.

608060405234801561001057600080fd5b50610133806100206000396000f3fe60806040526004361061003f5760003560e01c806360fe47b1146100445780636d4ce63c1461006e575b600080fd5b61004c61008a565b6040516100599190610101565b60405180910390f35b6100766100aa565b6040516100839190610101565b60405180910390f35b60008054905090565b600055565b6000548156fea2646970667358221220d1c4a65b9d24b8a6b8e173d15de24b5d4d5bfe82e69ad738f81a02ab8e764e0064736f6c63430008040033

그리고 위에서 얻은 바이트 코드를 아래의 파이썬 코드(바이트 코드를 분리해서 opcode를 추출하는 코드)에 넣어주면 다음과 같은 opcode가 추출되게 됩니다.

hashes = set()
for i in range(len(opcodes) - 3):
    if (
        opcodes[i].name == "PUSH4"
        and opcodes[i + 1].name == "EQ"
        and opcodes[i + 2].name == "PUSH2"
        and opcodes[i + 3].name == "JUMPI"
    ):
        hashes.add(opcodes[i].operand)
hashes = list(hashes)

['6d4ce63c', '60fe47b1']

이 두개의 opcode는 위 컨트랙트에 정의되어 있는 두개의 함수일 것이며 이 opcode를 target.call을 통해서 함수를 호출할 때 function selector(4 bytes)로도 사용 가능합니다.

함수 셀렉터란?
함수 셀렉터는 솔리디티에서 함수 호출을 구별하기 위해 사용되는 고유한 식별자입니다. 함수 셀렉터는 함수의 시그니처(signature)를 해시 함수 keccak256에 적용한 후 처음 4바이트를 취하여 생성됩니다.

위에서 추출한 옵코드 이외에는 스택에 데이터를 저장, 추출, 다음 목적지 지정 등 다른 많은 연산들이 바이트 코드를 이루게 됩니다.

EVM의 주요 명령어

  • 스택 조작:POP, PUSH, DUP, SWAP
  • 산술 연산: ADD, SUB, GT, LT, AND, OR
  • 메모리 접근: MLOAD, MSTORE, MSTORE8, MSIZE
  • 스토리지 접근: SLOAD, SSTORE

이 명령어들은 스마트 컨트랙트에서도 인라인 어셈블리를 통해서 저수준에서 직접 호출 가능합니다.

바이트코드 실행 과정

  • EVM 로드: EVM은 스마트 계약의 바이트코드를 메모리에 로드합니다.
  • 명령어 해석 및 실행: EVM은 바이트코드의 각 명령어를 순차적으로 해석하고 실행합니다.
  • 상태 변경: 스마트 계약이 상태를 변경해야 하는 경우, EVM은 이더리움 블록체인의 상태 트리에 이러한 변경 사항을 기록합니다.
  • 결과 반환: 스마트 계약 실행 결과는 호출자에게 반환되거나, 트랜잭션 로그에 기록됩니다.

요약

  • EVM: 이더리움 블록체인에서 스마트 계약을 실행하는 가상 머신.
  • 바이트코드: 고급 언어로 작성된 스마트 계약이 컴파일된 저수준 코드, EVM에서 실행 가능.
  • 바이트코드 생성 및 실행: 스마트 계약은 솔리디티로 작성되어 컴파일되고, EVM에서 바이트코드로 실행됨.

이와 같이 바이트코드는 EVM이 스마트 계약을 실행하는 데 있어 핵심적인 역할을 하며, 스마트 계약의 기능을 이더리움 네트워크에서 실현시킵니다.

0개의 댓글