본문 바로가기

IT/블록체인 Blockchain

[Ethereum] 이더리움 스마트 컨트랙트 #1 - testrpc에 올리기

반응형



이전 포스팅에서는 리눅스 환경에서 프라이빗 노드 설정하는 것 까지 알아 봤는데요, 오늘은 testrpc를 설치하고 간단한 스마트 컨트랙트를 블록에 올려보도록 하겠습니다.


본 포스팅은 아래 웹사이트의 내용을 참조했음을 알려 드립니다. (예제로 사용된 소스코드도 이곳에서 받을 수 있습니다)

https://medium.com/@mvmurthy/full-stack-hello-world-voting-ethereum-dapp-tutorial-part-1-40d2d0d807c2


testRPC


이더리움 블록체인에 스마트 컨트랙트를 올리기 위해서는 이더리움 네트워크에 접속할 필요가 있습니다.

실제 이더리움 메인 네트워크에 접속해서 테스트를 하려면 실제 이더가 필요하기 때문에 테스트 네트워크나 프라이빗 네트워크를 주로 사용하는데요, 개발 단계에서는 testRPC를 많이 사용합니다.

testRPC는 이더리움 시뮬레이터라고 생각하시면 됩니다. 실제 이더리움과 동일한 블록체인 구조를 가지고 있지만 마이닝이 필요 없기 때문에 마이닝 시간을 기다릴 필요 없이 바로 블록에 적용되므로 개발 및 테스트 시간이 훨씬 빨라지는 장점을 가지고 있답니다. (물론 블록체인 데이터 구조가 같다는 말이지 블록 내용이 같다는 말은 아닙니다)


testRPC는 python 기반 그리고 node.js 기반 두 가지가 있는데 많이 사용하는 node.js 기반을 설치해 보겠습니다.

먼저, node.js 패키지를 리눅스 환경에 설치하는데, apt-get 패키지로 바로 설치하면 예전 버전이 깔리기 때문에 아래와 같이 합니다. (https://nodejs.org/en/download/package-manager/#debian-and-ubuntu-based-linux-distributions 참조)


 $ curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash - sudo apt-get install -y nodejs


그리고 나서 testRPC를 설치 합니다. node.js 에 딸려 오는 npm 패키지 매니저를 사용 해서 간단히 설치 가능합니다.


 $ npm install -g ethereumjs-testrpc


설치 후, 특별한 옵션 없이 testrpc 명령어를 실행하면 바로 실행 됩니다.



testRPC에서는 따로 키 생성 명령을 수행하지 않아도 테스트에 사용할 수 있는 10개의 이더리움 주소 (공개키 - 개인키 쌍) 을 제공합니다.


예제 스마트 컨트랙트 : 투표하기


후보자들에게 투표를 할 수 있는 기능을 가진 예제 스마트 컨트랙트 입니다.

코드의 설명은 주석으로 처리 했습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
pragma solidity ^0.4.11;
// .sol 소스코드 파일은 첫 줄에 컴파일러 버전을 명기합니다.
 
contract Voting {
  /* 
  솔리디티의 'contract' 키워드는 자바의 'class'처럼 생각하면 됩니다.
  
  솔리디티의 매핑은 파이썬의 딕셔너리처럼 키-값의 쌍을 관리할 수 있습니다.
  여기서는 후보자의 이름과 득표수를 저장하기 위해 사용됩니다.
  */  
  mapping (bytes32 => uint8) public votesReceived;
  
  //후보자의 이름을 저장할 배열을 선언합니다.  
  bytes32[] public candidateList;
 
  /* 스마트 컨트랙트가 블록체인에 반영될 때 호출되는 컨스트럭터를 정의합니다.
  반영 시 후보자의 이름을 인수로 전달 합니다.
  */
  function Voting(bytes32[] candidateNames) {
    candidateList = candidateNames;
  }
 
  // 특정 후보자의 득표를 리턴하는 함수
  function totalVotesFor(bytes32 candidate) returns (uint8) {
    if (validCandidate(candidate) == falsethrow;
    return votesReceived[candidate];
  }
 
  // 특정 후보자에게 투표를 하는 함수
  function voteForCandidate(bytes32 candidate) {
    if (validCandidate(candidate) == falsethrow;
    votesReceived[candidate] += 1;
  }
 
  // 후보자의 이름이 리스트에 들어 있는지 확인하는 함수
  function validCandidate(bytes32 candidate) returns (bool) {
    for(uint i = 0; i < candidateList.length; i++) {
      if (candidateList[i] == candidate) {
        return true;
      }
    }
    return false;
  }
}
cs


위 파일을 Voting.sol 이라는 이름으로 저장합니다.

그리고 컴파일을 하기 위해 node.js기반의 solidity 컴파일러를 설치합니다.


$ npm install -g solc


컴파일러 설치가 완료 되면 이번에는 testRPC에 연결해서 명령어를 입력할 수 있는 콘솔 화면을 띄웁니다.

node 명령어로 node.js 콘솔을 띄운 후, 아래 명령어를 입력 합니다.


1
2
Web3 = require('web3')
 web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
cs


위 명령어로 콘솔에서 이더리움 testRPC의 Web3 인터페이스 연결이 완료되면 다음처럼 소스 코드를 컴파일 합니다.


1
2
3
code = fs.readFileSync('Voting.sol').toString()
 solc = require('solc')
 compiledCode = solc.compile(code)
cs


여기서 소스 코드가 저장된 곳에서 node console을 실행한 것이 아니면 Voting.sol 앞에 전체 경로를 입력해야 합니다.


컴파일이 완료되면 컴파일된 오브젝트의 정보가 콘솔로 출력 됩니다.

그 중에서 중요한 것은 바이트코드와 인터페이스 입니다.



바이트코드는 자바의 그것처럼 이더리움 가상 머신 위에서 실행되는 코드 입니다.



인터페이스는 해당 스마트 컨트랙트가 사용자에게 제공하는 메서드의 목록입니다.(abi라고 합니다)


이제 코드가 컴파일 되었으므로 블록체인에 반영해 보겠습니다.


1
2
3
4
5
abiDefinition = JSON.parse(compiledCode.contracts[':Voting'].interface)
VotingContract = web3.eth.contract(abiDefinition)
byteCode = compiledCode.contracts[':Voting'].bytecode
deployedContract = VotingContract.new(['Kim','Lee','Park'],{data: byteCode, from: web3.eth.accounts[0], gas: 4700000})
contractInstance = VotingContract.at(deployedContract.address)
cs


여기까지 했으면 이제 예제 스마트 컨트랙트가 블록체인에 반영 되었습니다.

해당 컨트랙트도 일반 어카운트처럼 주소를 가지는데, 콘솔에서 deployedContract.address 명령어로 확인할 수 있습니다.


이제, 블록체인에 반영된 컨트랙트와 콘솔을 통해서 interaction 해 보겠습니다.



투표를 할 때마다 트랜잭션이 일어나고, 해당 트랜잭션의 id가 콘솔에 표시 됩니다.


node.js 콘솔뿐 아니라 웹 인터페이스를 통해서도 스마트 컨트랙트를 통해 투표를 할 수 있습니다.

저는 이 부분을 생략하지만 해 보고 싶으신 분들은 위에서 알려드린 페이지를 참조하시면 됩니다.

(다만, 가상머신 위에 웹서버를 올리고, 버추얼박스의 설정에서 포트 리다이렉션 설정을 해야 호스트 pc의 웹 브라우저에서 볼 수 있습니다)


다음 포스팅에서는  testRPC 대신 실제 이더리움 테스트 네트워크를 이용하고, truffle 스마트 컨트랙트 프레임워크도 같이 살펴 보도록 하겠습니다.

반응형
  • 야차 2017.12.06 15:45

    안녕하세요
    npm install -g ethereumjs-testrpc
    설치중 not ok가 뜨는데
    조언 좀 구할 수 있을까요 ? ..
    npm ERR! error rolling back Error: ENOTEMPTY, rmdir '/usr/local/lib/node_modules/ethereumjs-testrpc/node_modules/webpack/node_modules/escope/node_modules/es6-weak-map/node_modules/es5-ext/object'
    npm ERR! error rolling back webpack@3.10.0 { [Error: ENOTEMPTY, rmdir '/usr/local/lib/node_modules/ethereumjs-testrpc/node_modules/webpack/node_modules/escope/node_modules/es6-weak-map/node_modules/es5-ext/object']
    npm ERR! error rolling back errno: 53,
    npm ERR! error rolling back code: 'ENOTEMPTY',
    npm ERR! error rolling back path: '/usr/local/lib/node_modules/ethereumjs-testrpc/node_modules/webpack/node_modules/escope/node_modules/es6-weak-map/node_modules/es5-ext/object' }
    npm ERR! error rolling back Error: ENOTEMPTY, rmdir '/usr/local/lib/node_modules/ethereumjs-testrpc/node_modules/webpack/node_modules/escope/node_modules/es6-weak-map/node_modules/es5-ext/object'
    npm ERR! error rolling back ethereumjs-testrpc@6.0.3 { [Error: ENOTEMPTY, rmdir '/usr/local/lib/node_modules/ethereumjs-testrpc/node_modules/webpack/node_modules/escope/node_modules/es6-weak-map/node_modules/es5-ext/object']
    npm ERR! error rolling back errno: 53,
    npm ERR! error rolling back code: 'ENOTEMPTY',
    npm ERR! error rolling back path: '/usr/local/lib/node_modules/ethereumjs-testrpc/node_modules/webpack/node_modules/escope/node_modules/es6-weak-map/node_modules/es5-ext/object' }
    npm ERR! weird error 127
    npm ERR! Error: ENOENT, open '/root/tmp/npm-13756-gduQMhiw/1512542647445-0.9158090823329985/package/node_modules/concat-map/LICENSE'
    npm ERR! If you need help, you may report this log at:
    npm ERR! <http://github.com/isaacs/npm/issues>
    npm ERR! or email it to:
    npm ERR! <npm-@googlegroups.com>

    npm ERR! System Linux 3.13.0-24-generic
    npm ERR! command "/usr/bin/nodejs" "/usr/bin/npm" "install" "-g" "ethereumjs-testrpc"
    npm ERR! cwd /root
    npm ERR! node -v v0.10.25
    npm ERR! npm -v 1.3.10
    npm ERR! path /root/tmp/npm-13756-gduQMhiw/1512542647445-0.9158090823329985/package/node_modules/concat-map/LICENSE
    npm ERR! code ENOENT
    npm ERR! errno 34
    npm ERR! Error: ENOENT, lstat '/root/tmp/npm-13756-gduQMhiw/1512542648068-0.812977482797578/package/lodash.js'
    npm ERR! If you need help, you may report this log at:
    npm ERR! <http://github.com/isaacs/npm/issues>
    npm ERR! or email it to:
    npm ERR! <npm-@googlegroups.com>

    npm ERR! System Linux 3.13.0-24-generic
    npm ERR! command "/usr/bin/nodejs" "/usr/bin/npm" "install" "-g" "ethereumjs-testrpc"
    npm ERR! cwd /root
    npm ERR! node -v v0.10.25
    npm ERR! npm -v 1.3.10
    npm ERR! path /root/tmp/npm-13756-gduQMhiw/1512542648068-0.812977482797578/package/lodash.js
    npm ERR! fstream_path /root/tmp/npm-13756-gduQMhiw/1512542648068-0.812977482797578/package/lodash.js
    npm ERR! fstream_type File
    npm ERR! fstream_class FileWriter
    npm ERR! code ENOENT
    npm ERR! errno 34
    npm ERR! fstream_stack /usr/lib/nodejs/fstream/lib/writer.js:284:26
    npm ERR! fstream_stack Object.oncomplete (fs.js:107:15)
    npm ERR!
    npm ERR! Additional logging details can be found in:
    npm ERR! /root/npm-debug.log
    npm ERR! not ok code 0

  • 야차 2017.12.06 17:02


    > solc = require('solc');
    Error: Cannot find module 'solc'
    at Function.Module._resolveFilename (module.js:469:15)
    at Function.Module._load (module.js:417:25)
    at Module.require (module.js:497:17)
    at require (internal/module.js:20:19)
    at repl:1:8
    at sigintHandlersWrap (vm.js:22:35)
    at sigintHandlersWrap (vm.js:73:12)
    at ContextifyScript.Script.runInThisContext (vm.js:21:12)
    at REPLServer.defaultEval (repl.js:340:29)
    at bound (domain.js:280:14)

    이 에러는 제가 어떻게 잡아야 할까요 ?