×
Crocus
공부한 내용을 정리하는 블로그로 시작한
Crocus는 2014년 1월 14일 부터 시작하여
현재 월 6만명, 총 1,488,492명의 방문자 수를 기록하고 있습니다.
Donation
이제 많은 사용자들이 이용하는 만큼
더 다양한 서비스 개발/제공을 위해 후원금을 모금하고자 합니다.
후원을 해주시는 분들은 Donators 명단에 성명, 후원금을 기입해드리며
Crocus 블로그가 아닌 다른 곳에 정리해둔 저만의 내용을 공유해 드리고자 합니다.
Account
예금주 : 고관우
신한은행 : 110-334-866541
카카오뱅크 : 3333-01-7888060

👉 후원 페이지 바로가기 Donators
익명 : 5000원(Crocus응원합니다.)
busyhuman: 5000원(유용한 지식 감사합니다.)
익명 : 5000원(알고리즘 학습러)

Public network 구축


이더리움 dApp을 만들기 위해 이더리움 메인넷 혹은 테스트넷을 이용해도 되지만, 빠른 마이닝을 통해 빠른 결과를 얻고 싶거나, 자신의 dApp을 빠르게 확인해보기 위해 자신만의 퍼블릭 네트워크를 구축하는 것이 좋다.



1. 제네시스 json 파일


genesis.json


위의 파일을 다운받고 chainId의 40039298을 자신만의 Id로 변경하자.



2. 제네시스 json으로 네트워크 환경 구성 초기화


D:\Geth\geth --datadir local init genesis.json


이제 자신의 geth가 있는 경로에서 geth를 실행하며 옵션을 위와같이 주자.


이때 --datadir에는 자신이 원하는 폴더명을 작성하면 된다.(필자는 local이라고 작성했다.)


그리고 init는 제네시스 블록을 만들기 위한 json 파일을 포함해야하는데 genesis.json이 있는 경로와 함께 json을 추가해주면 된다.



3. geth를 이용하여 Public network 구축


d:\Geth\geth --networkid 40039298 --datadir local --rpc --rpcaddr "0.0.0.0" --rpcport 8545 --rpccorsdomain "*" --rpcapi "admin, db, eth, debug, miner, net, shh, txpool, personal, web3" console


이제 자신의 geth가 있는 경로에서 geth를 실행하고 위와 같이 설정해주자. 이때 40039298은 자신이 바꾼 chainId와 동일하게 networkId를 설정해준다.


옵션에 대한 설명은 아래 링크를 참고하자


http://www.crocus.co.kr/1282?category=270981



이제 console에서 geth가 구동됨을 알 수 있고 퍼블릭 네트워크가 구축됨을 알 수 있다.



4. Mist를 이용하여 지갑 생성


다른 콘솔을 열어 mist가 있는 디렉토리에서 아래와 같이 실행해주자.


mist --rpc //./pipe/geth.ipc


옵션에 대한 설명은 아래 링크를 참고하자


http://www.crocus.co.kr/1282?category=270981


그리고 지갑 생성을 통해 지갑을 생성해주자.




5. Remix에서 솔리디티 프로그래밍(dApp 프로그래밍 하기)


이제 http://remix.ethereum.org/ 에서 솔리디티 프로그램을 만들어보자.


필자가 연습으로 이용할 코드는 아래와 같다.


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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
pragma solidity ^0.4.19;
 
contract AnyWear{
    address public owner;
  
    string public name;
    string public symbol;
    uint public decimals;
    uint public totalSupply;
    
    mapping(address => uintpublic balanceOf;
    mapping(address => mapping(address => string)) public hashTable;
    
    event event_transfer(address indexed from, address indexed to, uint value);
    event event_saveHash(address indexed addr, string hashValue);
    
    modifier isOwner(){
        require(msg.sender == owner);
        _;
    }
    
    function getMsgSender() public view returns(address){
        return (msg.sender);
    }
    
    function AnyWear(string _name, string _symbol, uint _decimals, uint _supply) public {
        name = _name;
        symbol = _symbol;
        decimals = _decimals;
        totalSupply = _supply;
        balanceOf[msg.sender= _supply;
        owner = msg.sender;
    }
    
    function transfer(address _to, uint _value) public{
        require(balanceOf[msg.sender>= _value);
        require(balanceOf[_to] + _value >= balanceOf[_to]);
        
        balanceOf[msg.sender-= _value;
        balanceOf[_to] += _value;
        
        emit event_transfer(msg.sender, _to, _value);
    }
    
    function getCoin(address _addr) public view returns (uint){
        return (balanceOf[_addr]);
    }
    
    function saveHash(address _seller, address _buyer, string _hashValue) public {
        require(_seller == msg.sender || _buyer == msg.sender);
        hashTable[_seller][_buyer] = _hashValue;
        
        emit event_saveHash(msg.sender, _hashValue);
    }
    
    function findHash(address _seller, address _buyer) public view returns (string) {
        return hashTable[_seller][_buyer];
    }
    
    function checkHash(address _seller, address _buyer, string _hashValue) public view returns (bool){
        if(keccak256(findHash(_seller, _buyer)) == keccak256(_hashValue)) {
            return true;
        }
        else{
            return false;
        }
    }
}
cs


코드에 대한 자세한 설명은 생략하고(솔리디티 프로그래밍을 할 줄 알면 파악하기 쉽다.)


코인 생성, 송금 기능, 코인 확인 기능, 해시값 저장 및 판별 기능이 있다.




리믹스에서 이제 Web3 Provider을 클릭하고 위와같이 설정 후 확인을 눌러준다.


이제 그럼 로컬에서 web3를 이용할 환경이 구축되었다.


이제 Account를 보면 자신이 아까 Mist에서 지갑을 생성했던 주소들이 보일 것이다.


즉, 현재 geth - mist - remix 3가지가 연동되어있음을 확인 할 수 있다.



6. web3.js 이용하기


https://github.com/ethereum/web3.js/releases 에서 web3.js를 적절한 폴더에 다운 받아둔다.


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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
<html lang="en">
<head>
    <script src="D:/web3js/web3/dist/web3.js" charset="utf-8"></script>
    <script src="JS.js" charset="utf-8"></script>
</head>
<body>
 
    <form method="GET" action="a.html" id="form1">
        보내는이 : <input type="text" class="senderName" /><br />
        받는이 : <input type="text" class="receiverName" /><br />
        코인 : <input type="text" class="amount" /><br />
        <input type="submit" value="보내기"/>
    </form>
 
    <form method="GET" action="a.html" id="form2">
        주소 : <input type="text" class="addrName" /><br />
        <input type="submit" value="금액확인" />
        <p id="display_getCoin">확인된 금액 :: </p>
    </form>
 
    <form method="GET" action="a.html" id="form3">
        지갑 주소 <input type="text" class="saveHash_senderName" /><br />
        지갑 주소 <input type="text" class="saveHash_receiverName" /><br />
        해시값 : <input type="text" class="saveHash" /><br />
        <input type="submit" value="저장" />
    </form>
 
    <form method="GET" action="a.html" id="form4">
        지갑 주소 <input type="text" class="chkHash_senderName" /><br />
        지갑 주소 <input type="text" class="chkHash_receiverName" /><br />
        해시값 : <input type="text" class="chkHash" /><br />
        <input type="submit" value="확인" />
        <p id="display_chkHash">해시 일치 여부</p>
    </form>
 
    <form method="GET" action="a.html" id="form5">
        지갑 주소 <input type="text" class="findHash_senderName" /><br />
        지갑 주소 <input type="text" class="findHash_receiverName" /><br />
        <input type="submit" value="검색" />
        <p id="display_findHash">해시 값</p>
    </form>
 
    <script>
        // transfer Script
        var evt_transfer = document.getElementById("form1");
        evt_transfer.onsubmit = function evt_transfer_Submit() {
            var _senderName = document.getElementsByClassName("senderName").valueOf()[0].value;
            var _receiverName = document.getElementsByClassName("receiverName").valueOf()[0].value;
            var _amount = document.getElementsByClassName("amount").valueOf()[0].value;
 
            if (_senderName != "" && _receiverName != "" && _amount != 0)
                transfer(_senderName, _receiverName, _amount);
            else
                console.log("transfer 입력값 부족");
 
            return false;
        }
 
        // getCoin Script
        var evt_getCoin = document.getElementById("form2");
        evt_getCoin.onsubmit = function evt_getCoin_Submit() {
            var _addrName = document.getElementsByClassName("addrName").valueOf()[0].value;
            
            if (_addrName != "") {
                getCoin(_addrName);
            }
            else
                console.log("getCoin 입력값 부족");
 
            return false;
        }
 
        // saveHash Script
        var evt_saveHash = document.getElementById("form3");
        evt_saveHash.onsubmit = function evt_saveHash_Submit() {
            var _senderName = document.getElementsByClassName("saveHash_senderName").valueOf()[0].value;
            var _receiverName = document.getElementsByClassName("saveHash_receiverName").valueOf()[0].value;
            var _hash = document.getElementsByClassName("saveHash").valueOf()[0].value;
 
            if (_senderName != "" && _receiverName != "" && _hash != "")
                saveHash(_senderName, _receiverName, _hash);
            else
                console.log("saveHash 입력값 부족");
 
            return false;
        }
 
 
        // checkHash Script
        var evt_checkHash = document.getElementById("form4");
        evt_checkHash.onsubmit = function evt_checkHash_Submit() {
            var _senderName = document.getElementsByClassName("chkHash_senderName").valueOf()[0].value;
            var _receiverName = document.getElementsByClassName("chkHash_receiverName").valueOf()[0].value;
            var _hash = document.getElementsByClassName("chkHash").valueOf()[0].value;
 
            if (_senderName != "" && _receiverName != "" && _hash != "")
                checkHash(_senderName, _receiverName, _hash);
            else
                console.log("checkHash 입력값 부족");
 
            return false;
        }
 
 
        // findash Script
        var evt_findHash = document.getElementById("form5");
        evt_findHash.onsubmit = function evt_findHash_Submit() {
            var _senderName = document.getElementsByClassName("findHash_senderName").valueOf()[0].value;
            var _receiverName = document.getElementsByClassName("findHash_receiverName").valueOf()[0].value;
 
            if (_senderName != "" && _receiverName != "")
                findHash(_senderName, _receiverName);
            else
                console.log("findHash 입력값 부족");
 
            return false;
        }
 
       // AnyWear Start
       var AnyWear;
 
       function startApp() {
           var contractAddress = "0xaf654ff434e0ced71a5ba689068a30bb57ff4cf1";
           AnyWear = new web3.eth.Contract(AnyWearABI, contractAddress);
       }
 
       var web3;
       window.addEventListener('load'function(){
           if(typeof web3 !== 'undefined'){
               web3 = new Web3(web3.currentProvider);
           }
           else {
               web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
           }
 
           startApp();
       })
 
       
       function transfer(_senderName, _receiverName, _amount) {
           return AnyWear.methods.transfer(_receiverName, _amount).send({ from: _senderName }); // {from : _senderName}
       }
       function getCoin(_receiverName) {
           var ret = AnyWear.methods.getCoin(_receiverName).call();
           ret.then(function (result) {
               document.getElementById("display_getCoin").innerHTML = result;
           })
       }
 
       function saveHash(_senderName, _receiverName, _hash) {
           AnyWear.methods.saveHash(_senderName, _receiverName, _hash).send({ from: _senderName });
       }
 
       function checkHash(_senderName, _receiverName, _hash) {
           var ret = AnyWear.methods.checkHash(_senderName, _receiverName, _hash).call();
           ret.then(function (result) {
               document.getElementById("display_chkHash").innerHTML = result;
           })
       }
 
       function findHash(_senderName, _receiverName) {
           var ret = AnyWear.methods.findHash(_senderName, _receiverName).call();
           ret.then(function (result) {
               document.getElementById("display_findHash").innerHTML = result;
           })
       }
       
    </script>
</body>
</html>
cs


코드 그대로 한번 a.html에 붙여넣고 이용해보자.


이때 수정해야할 부분은 다음과 같다.


- script src에서 경로는 자신이 조절해줘야 한다.

- 컨트랙트 주소를 넣는 부분에 자신의 컨트랙트 주소를 넣어주자.

- JS.js에는 ABI 값이 저장되어있다.

현재 컨트랙트의 ABI 값을 받아오는건 어렵지 않다. 검색을 통해 알아보거나 블로그 내에서 어떻게 하는지 찾아보자.





이제 a.html을 이용하여 간단한 것들을 트랜잭션으로 요청해보고 마이닝을 해서 다양한 결과를 확인해보자.


이때 트랜잭션이 안보내진다면 어카운트가 잠겨서이다.


자신의 어카운트를 풀어주기 위한 명령어는 다음과 같다.



geth에서 어카운트 생성 및 어카운트 unlock


personal.newAccount()

personal.unlockAccount(eth.accounts[인덱스번호],"비밀번호")


이때 인덱스번호에는 현재 컨트랙트를 이용하고자 하는 어카운트의 인덱스번호를 입력해준다.