블록체인 Block-Chain - Ethereum Opcode가 뭘까?

dev_swan·2022년 12월 20일
3

블록체인

목록 보기
36/36
post-thumbnail

Opcode에 대해 배우기 전 EVM을 간단히 짚고 넘어가겠습니다.

EVM?

EVM은 이더리움 가상 머신으로 다들 알고계실겁니다.

우리가 흔히 geth 같은 이더리움 클라이언트를 설치하면 스마트 계약을 싱행하기 위해 특별히 제작된 경량 운영 체제인 EVM도 함께 제공됩니다.

EVM.. 쉽게 풀어볼까요? 그냥 간단히 이더리움 블록체인의 실행환경이라고 생각합시다.

우리가 이더리움 스마트 컨트랙트를 작성할 때, 주로 Solidity를 사용합니다.
Solidity는 고수준 언어로 인간이 이해할 수 있는 언어입니다. 인간은 이해할 수 있는데 기계는 이해할 수 없다..?

그렇다면 EVM은 어떻게 인간만 이해할 수 있는 코드를 해석해서 스마트컨트랙트를 실행시키는걸까요? 여기서 많이들 들어보신 바이트코드가 나옵니다.

그렇다면 바이트코드는 뭘까?

Solidity 컴파일러를 통해 Solidity로 작성된 스마트 컨트랙트를 네트워크에 배포하기전에 컴파일 많이들 해보셨을겁니다.

이러한 컴파일을 통해 EVM이 우리가 Solidity로 작성한 스마트 컨트랙트를 이해할 수 있도록 변환해주는 것입니다.

그렇다면 여기까지 인간이 이해할 수 있는 언어인 Soildity를 컴파일하여 EVM 같은 가상 머신에서 실행할 수 있도록 한다.로 정리할 수 있겠습니다.

자 그럼 실제 Remix IDE 툴을 이용해서 간단한 스마트 컨트랙트를 작성해 바이트코드를 확인해볼까요?
컴파일할 스마트 컨트랙트는 아래와 같습니다.

컴파일을 하였으면 하단에 Compilation Details를 클릭해서 우리가 작성한 스마트 컨트랙트에 대한 바이트코드를 확인해봅시다.

흠.. 형태를 보아하니 object는 컴파일된 바이트코드인것 같고.. 근데 Opcodes? 바이트코드만 있으면 EVM에서 스마트 컨트랙트를 실행할 수 있다고 했는데..

Opcode가 뭐야?

바로 구글링 해봅시다.

컴퓨터 과학에서 명령 코드(opcode←operation code, instruction syllable, instruction parcel, opstring[1][2][3][4][5][6][7])는 기계어의 일부이며 수행할 명령어를 나타내는 부호를 말한다. 이에 대한 규격과 형식은 프로세서 명령어 집합에 나와 있다. (프로세서는 일반 CPU일 수도 있고 특별한 처리 장치일 수도 있다) 기계어 명령어(Instruction)는 명령어를 나타내는 opcode를 가지며, 일반적으로 피연산자를 나타내는 하나 이상의 지정자를 가진다.

출처 : 위키트리

비전공자인 저에게는 너무나 어려운 말들만 써있군요.. 간단히 정리해봅시다.

  • 컴퓨터 과학에서 명령 코드(Opcode)는 기계어의 일부이며 수행할 명령어를 나타내는 부호를 말한다.
  • 기계어 명령어(Instruction)는 명령어를 나타내는 opcode를 가진다.

대충 이정도로 정리해보면 쉽겠네요.

자, 그렇다면 바이트코드는 EVM이 이해하는 코드입니다. 그럼 위키트리에 나온 내용을 이런식으로 해석해보면 어떨까요?

  • 바이트코드는는 명령어를 나타내는 명령코드(Opcode)를 가진다.

흠.. 뭔가 그럴듯해 보이죠? 바이트코드는 옵코드와 매칭이 된다라.. 당장 바이트코드와 옵코드를 가져와 비교해봅시다.

바이트코드

60806040526008600055348015601457600080fd5b50603f8060226000396000f3fe6080604052600080fdfea26469706673582212206c0b14387e23dca73af0f7e35c45eafa12422727271941b551af3573a43002ba64736f6c63430008110033

Opcode

PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x8 PUSH1 0x0 SSTORE CALLVALUE DUP1 ISZERO PUSH1 0x14 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x3F DUP1 PUSH1 0x22 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x0 DUP1 REVERT INVALID LOG2 PUSH5 0x6970667358 0x22 SLT KECCAK256 PUSH13 0xB14387E23DCA73AF0F7E35C45 0xEA STATICCALL SLT TIMESTAMP 0x27 0x27 0x27 NOT COINBASE 0xB5 MLOAD 0xAF CALLDATALOAD PUSH20 0xA43002BA64736F6C634300081100330000000000 

우리같은 인간은 바이트코드를 아무리 본다고 해도 해석할 수 없습니다. 기계가 아니니까요. 구글의 힘을 빌려 다시한번 구글링을 해봅시다.

EVM Opcode를 검색하여 정보를 얻어봅시다. 하지만 여러분들의 시간은 소중하니 링크를 올려놓을게요

OPCODES FOR THE EVM

위 사이트로 접속후 첫번째 OpcodePUSH1을 검색하면 60Stack을 가진것을 확인할 수 있습니다.

보아하니 바이트코드와 Opcode가 정말 매칭되는것을 확인할 수 있습니다.
흠.. 그렇다면 바이트코드와 옵코드가 매칭인건 알겠는데, 바이트코드만 있으면 되는거 아닌가?
옵코드는 왜 필요한거지? 라는 의문이 들 수 있습니다.

여기서 우리는 EVM에 동작방식에 대해 더 자세히 알아야 할 필요가 있습니다.

자, 우리는 위에서 바이트코드와 Opcode가 매칭된다는것을 확인했습니다.
따라서 우리는 EVM이 컴파일한 바이트코드와 매칭되는 Opcode를 실행한다는 것을 이해할 수 있습니다.

그렇다면 어떻게 실행하느냐도 간단히 알아볼까요?

EVM은 스택방식입니다. 다들 LIFO(Last In First Out)으로 한번씩은 들어보셨을 겁니다.

간단히 예를 들어보도록 하겠습니다

uint i = 2 + 2 * 2;

우리는 위같은 산술식에서 i는 6이라는걸 알 수 있습니다. 2 * 2 를 먼저 계산하고 후에 + 2를하여 나온 값임을 알 수 있죠.

하지만 스택방식에서는 아래와 같이 LIFO 원리로 작동합니다.

2 2 * 2 +

스택에 2를 넣고 다음으로 2를 넣은 다음 곱셈 작업을 합니다.
결과적으로 스택의 맨 위에는 4가 있죠, 이제 4 위에 다시 숫자 2를 추가하고 이를 더합니다.
따라서 스택의 최종값은 6이 됩니다.

이러한 유형의 산술을 역폴란드 표기법이라고 합니다.

자, 여기까지 EVM, 바이트코드, 옵코드에 대해 알아보았습니다.

최종적으로 EVM은 솔리디티 언어로 작성된 스마트 컨트랙트를 바이트코드로 변환하면 그에 해당하는 Opcode를 실행해준다. 이런식으로 정리할 수 있겠습니다.

그렇다면 어차피 옵코드를 실행한다는건데 옵코드로 컨트랙트를 작성할 수는 없을까요?
물론, 가능합니다.

Assembly??

스마트 컨트랙트 개발자라면 한번쯤은 마주쳤을 Assembly가 바로 솔리티디 내부에서 옵코드 작성을 가능하게 해줍니다.

간단하게 예시로 사용방법을 알아볼까요?

function addAssembly(uint x, uint y) public pure returns (uint) {
     assembly {
       
         let result := add(x, y)
       
         mstore(0x0, result)
         
         return(0x0, 32)
     }
 }

위의 addAssembly 함수는 옵코드 add를 사용해서 xy를 더한 값을 := 키워드로 result에 담고, 옵코드 mstore를 사용해서 메모리 주소 0x0result의 값을 저장합니다.
마지막으로 0x0 메모리 주소에 32Byte를 반환하는 코드입니다.

그렇다면 Assembly 왜 사용하는걸까요? 그냥 솔리디티로 x + y 하는게 더 편하지 않나? 라는 생각이 드실겁니다.

위의 예시에서 살짝 봤듯이 우리는 메모리주소 0x0에 값을 저장하는것을 알 수 있습니다.
솔리디티에서는 할 수 없는 미세한 조정도 가능하다는것을 확인할 수 있죠, 또한 컴파일된 바이트코드와 매칭되는 Opcode를 실행하는것이 아닌 순수 Opcode를 통해 EVM과 상호작용을 하기 때문에 가스비가 절감됩니다.

이상으로 EVM과 조금은 더 친해지는 시간을 가져보았습니다~

0개의 댓글