이제부터는 Smart Contract 로 들어가기로 한다.
Ethereum 이 비트코인과 가장 크게 차별화되는 특징이기도 하며, Public/Consortium/Private Blockchain 에 공통으로 적용되어 기존 C/S 환경 대비 가장 큰 변화를 가져다줄 수 있는 기술이기도 하다.

일단 얼마전에, 블록체인의 응용방법을 주제로 한 Blockchain 초급 개발자를 대상으로 생각하여 만든 자료를 사용하여 설명 해보겠다.

▌Smart Contract 의 개요

쉽고 멋들어지게 일반화된 용어로 Smart Contract 를 표현한 뉴스기사나 글들이 참 많다. 그래서일까, 사람들이 Smart Contract (스마트 계약)이라는 용어를 나름 머릿속으로 해석하여 정말 무슨 계약 문서같은것이 블록체인에 담겨있다는 생각을 하는 이들도 많다. 그도 그럴것이, Blockchain 을 응용한 매우 낮은 수준의 응용 방법 중 대표적인 것이 "Proof of Existence" 였고, "진본증명" 이나 "외부거래증명" 같은 Use-Case 를 다수 접해온 Blockchain 초심자들이 상상해내기 딱 좋은 용어의 조합이기 때문이라고 생각한다.

Nick Szabo (닉 싸보)

Smart Contract 의 최초 발안자는 Nick Szabo 이다. 이양반은 Computer Scientist 이며 암호학과 법학에 조회가 깊고 경제학에도 관심이 많은, 보통 사람이 대하기에는 힘겨운 그런 사람이다.

1994년, Smart Contract 라는 개념에 대해 처음으로 발표하게 되고
1997년, The Idea of Smart Contract 라는 글로 실제로 이러한 Smart Contract 를 어디에 적용하면 좋을지에 대한 아이디어를 낸다

▌Smart Contract 키워드

Nick Szabo 가 말하는 Smart Contract 의 목적은, "신뢰할 수 없는 컴퓨터 네트워크환경" 에서 "(Machine 간에)고도로 발달된 자동 계약 이행 방법" 을 제시하는 것이다. 이러한 개념은 블록체인 기술을 만나면서 빛을 발하게 되었고, Ethereum 이 "Turing Complete Blockchain" 이라는 개념으로 Blockchain 을 진화시켜가며 Nick Szabo 의 아이디어를 실현시켜 준다.

Nick Szabo 는 블록체인 내의 Smart Contract 를 아래와 같이 이야기한다.
 
    ▪  코드 조각 이다
    ▪  공유장부와 상호작용할 수 있는 인터페이스
    ▪  Transaction 을 보내면 코드조각의 함수를 실행
    ▪  실행된 함수는 장부에서 값을 읽거나 씀

그리고, 금융을 의식해서인지, 어느 강연에서는 이렇게 이야기한다.


이제 조금 감이 왔을 것이라고 믿는다. 조금만 더 이해를 돕기 위한 이야기를 해보자.

▌Smart Contract 의 정체

Nick 이 말한대로이다. Smart Contract 는 계약가 아니라 코드 조각이다. 

아래는 실제 Solidity 언어로 구현 한 Smart Contract (Code) 이다.

contract CrowdFunding {
  struct Funder {
    address addr;
    uint amount;
  }
  struct Campaign {
    address beneficiary;
    uint fundingGoal;
    uint numFunders;
    uint amount;
    mapping (uint => Funder) funders;
  }
  uint numCampaigns;
  mapping (uint => Campaign) campaigns;
  function newCampaign(address beneficiary, uint goal) returns (uint campaignID){
    campaignID = numCampaigns++; 
    campaigns[campaignID] = Campaign(beneficiary, goal, 0, 0);
  }
 
...

이러한 Smart Contract Code 는 Ethereum 의 경우, Solidity, Serpent, LLL, Mutan 의 언어로 쓰여질 수 있는데, 현재는 Solidity 를 주로 밀고 있으며 문법은 JavaScript-Like 하다. Serpent 는 Frontier 가 Release 되기 전까지만 해도 C 언어와 유사한 문법이고 Solidity 의 완성도가 많이 떨어져서 두루두루 함께 썼지만 지금은 Solidity 의 승이다. Mutan 은 접은지 꽤 됐고, LLL 은 아직도 Assembly-Like 하게 Low Level 로 개발하고 Debug 하는데에 일부 해외 개발자들이 사용한다.

위에 보이는대로, Smart Contract 는 "변수"도 있고 "구조체"도 있고 "함수"도 있는 코드 이다. 물론 좀더 들어가면 'Storage 변수와 Memory 변수'로 변수의 종류가 나뉘고 Contract 간의 Address 기반 호출과 DELEGATECALL 등이 들어가면서 기존 프로그래밍 방식과 다른 점들이 많이 튀어나오긴 하지만 그래도 코드이다.

이러한 Smart Contract Code 는 Compile 과정을 거쳐 Byte Code 로 변환된다.


위 Bytecode 는 Solidity Realtime Compiler 를 통해 컴파일된 결과이다(도구 등에 대해서도 다음번에 다룰 것이다). 모두 16진수로 된 코드이며, 이 Bytecode 를 to: 주소가 없이 Payload (data: ) 로 할당하여 Blockchain 에 Transaction 을 날리면, Miner 에 의해 Block 이 생성되고, 이러한 Transaction은 Contract Creation Transaction 으로 간주되어 Transaction Receipt 의 contractAddress: 필드에 생성(배포)된 Contract 의 주소를 넣어서 리턴해주게 되어있다.

다음은 이러한 Smart Contract 의 응용 흐름에 대해 간략히 이해 해보자

▌Smart Contract 의 응용 흐름

Smart Contract Code 는 크게 [Creation/Deployment] [Invoke by Message] [Call] 의 응용방식으로 나뉜다.
우선 아래 그림을 보면서 해당 Smart Contract의 응용 흐름을 이해 해보자.


▪   Smart Contract 개발환경
 Smart Contract 개발환경은 개발도구와 Compiler 까지를 포함한 범위를 표시한다. Code 를 작성하고 컴파일 하면 모든 컴파일러는 [Byte Code] 와 [Function Signature], [ABI] 를 최소한 벹어낸다. 

  Byte Code 는 이미 위에서 설명한 것 처럼 Smart Contract Code 를 컴파일 한 결과이며, Blockchain 에 Contract Creation Transaction 을 발생시켜 배포하거나 Contract 로의 Message Tx 이나 Call 을 통해 EVM 위에서 실행된다.

  Function Signature 는 Contract 내의 함수 이름의 SHA3 한 Hash 값의 4바이트 값으로, Contract 의 함수를 실행시킬 때 Transaction 의 to: 주소에는 Contract Address 를, data: 부분에는 이 method signature 4바이트와 함께 파라미터 값이 payload 로 들어간다. JSON RPC API 를 통해 직접 실행시킬때에는 신경써야 하지만 web3.js 를 통해 contract 를 실행할때에는 신경 쓸 필요 없다. 아래 ABI 때문에 가능하다.

  ABI(Application Binary Interface) 는 특정 언어나 플랫폼에 종속되지 않은 방식으로 기술된 Application Interface 에 대한 정의이다. 쉽게 말하면, 이 ABI 정의를 컴파일러 혹은 ABI Generator 가 벹어내는데, 이 ABI 에는 Smart Contract 의 함수와 Parameter 에 대한 Metadata 가 정의되어있다. 이 ABI 를 갖고 JavaScript 언어 기반의 어플리케이션을 만들 때 객체를 만들게 할 수 있고, 쉽게 그 객체의 Method를 호출하는것 만으로 Contract 의 함수가 호출되도록 할 수 있는 것이다. 현재 Ethereum 은 web3.js 와 함께 JavaScript 응용에서 쉽게 ABI 로 객체를 만들어 사용하도록 지원하며, 1.4.0 이후의 go-ethereum 에서는 Go Native 언어 기반의 응용에서 Smart Contract 를 쉽게 Binding 가능하도록 ABI 기반으로 Go Code 를 생성 해주는 ABIGen 을 제공하고있다.

▪   Blockchain Engine
 geth 나 parity, eth 와 같은 Ethereum Node 를 의미한다. 결국 모든 Smart Contract 와 관련한 Transaction 처리와 Contract 실행을 위한 EVM 은 Node 가 갖고있다.

▪   Applications
 Smart Contract 는 Logic 만을 갖고있을 뿐이다. 사용자나 외부 시스템과의 상호작용을 위해서는 당연히 Application 이 필요하다. HTML+CSS+JavaScript 가 되었건 Application Server 가 되었건 Wallet 이건 간에, Ethereum 과의 Interface 를 통해 Smart Contract 와 상호작용하는 Application 에 해당하는 부분이다. Contract 파트를 뺀 Dapp 부분 정도로 봐도 된다.


[1] Contract Creation/Deployment

 일단 bytecode 가 생성되면, ABI 기반의 객체를 통하건 RPC API 를 통하건 Ethereum Network 으로 Contract Creation Transaction 을 날릴 수 있다. 이때 Transaction 에서 to: 주소는 빼고 payload 에 bytecode 를 넣고, 충분한 Gas 를 넣어 보내면(Gas Estimation 기능을 잘 활용해야 한다. 아니면 좀 과하게 넣고 남기면 된다) Contract 가 생성되게 된다.

 ABI 를 통해 생성한 객체의 new() 를 통해 Contract 를 Create 했다면 생성이 완료된 시점(Transaction 이 처리되고 블록으로 묶여서 Import 된 시점)에 callback 이 호출되며 그때 Transaction Receipt 를 보면 contractAddress 에 생성된 Contract 의 주소가 들어가 있게 된다. 이후 부터는 이 주소를 통해 Contract 를 사용하면 되는것이다.

[2] Message Transaction

 위에서 생성한 Contract 의 함수를 실행하는 Transaction 이다. JSON RPC API 로 호출할때에는 payload 에 4바이트의 Function Signature 를 제일 먼저 쓰고 그 다음부터 32바이트 단위의 파라미터 값들을 넣어서 보내게 된다. ABI 를 통한 Contract 객체는 단순히 객체의 Method 를 호출하듯 하면 된다. 

 이 Message Transaction 은 단순히 모든 함수 호출에 사용하면 낭패를 볼 수 있다. Message Transaction 또한 Transaction 이며, Transaction 을 발생시키면 당연히 Gas 가 소모된다. 단순히 현재 상태값을 조회하는 함수를 호출하거나 테스트 목적으로 함수를 호출한다면 Message Transaction 을 발생하면 안된다. 이때는 다음 설명하는 Call 방식을 사용해야 하며, Message Transaction 은, Smart Contract 를 통해 Global State 를 변경해야하는 경우 즉, 값이 변경되어야 하는 경우에만 사용하여야 한다. 나중에 상세히 설명하겠지만, Contract 개발자도 이러한 상태변화가 없는 함수는 constant 로 선언하여야 ABI 로 아무생각없이 함수를 호출하는 응용 사용자들이 Gas 를 소모당하지 않게할 수 있다.

[3] Call

 Contract 의 함수를 호출하는 두번째 방법이다. [2] 에서도 잠깐 언급했지만, Ethereum 의 Global State 에 변화를 주지 않는 함수를 Gas 소모 없이 호출하려면 이 call 을 사용해야 한다. Contract 함수를 Call 하게 되면, Transaction 을 발생시키지 않고 자기 Node 내에 이미 저장되어있는 Smart Contract 를 Local 에서 실행시킨다. constant 함수가 아니더라도 Transaction 발생 없이 함수를 실행시킬 수 있으나 Global State 에는 영향을 주지 않고, call 이 끝난 시점에 모든 state 는 원상복귀된다. 


아.. 오늘은 그냥 "이해" 인데 또 글이 길어졌다.. 더이상 쓰다가는 내일 출근에 지장을 줄 터, 이만 줄이고 앞으로도 많은 내용을 올려야 할 듯 하니 다음 글로 미루어 두도록 하겠다~ ^^;;


▌그래서..

Smart Contract 는, 보이는 대로 블록체인에 배포되는 Code 이다. 그래서 IBM 의 경우, OBC-Peer 를 만들 때 부터 Smart Contract 라는 개념을 가져다 쓰지만 용어는 좀더 Clear 하게, "Chain Code" 라고 부른다. Nick Szabo 에게는 좀 미안하긴 하지만, Contract 라는 표현 보다는 좀더 직관적이지 않나 싶다.

그러나 앞으로의 글들을 보다보면 무조건 Chain Code 라고 하기 보다는 어떤 때는 Contract 라는 용어가 더 맞는것 같다는 느낌이 종종 들 것이다. Public Blockchain 과 Private Blockchain 에서 Smart Contract 가 가져야할 특징과 역할이 약간 다르기 때문인데, 이건 앞으로의 글을 이해하면서 느껴보면 되겠다.

아.. 이젠 졸립다.. 그럼 이만..


반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,