반응형
Ether02coin

이더리움 개발 관련된 사항

알아야 될 것.

  • view 값을 가져오는 것은 가스 소모가 되지 않는다.
  • 코인 발행은 계약을 만든 사람만이 가능하다.
  • 코인 전송시에는 ID/PWD가 필요없다. 단지 이더리움 키쌍이 필요하다.

코인 만들기

image

pragma solidity ^0.5.0;

contract Coin {
    // The keyword "public" makes those variables
    // easily readable from outside.
    address public minter;
    mapping (address => uint) public balances;

    // Events allow light clients to react to
    // changes efficiently.
    event Sent(address from, address to, uint amount);

    // This is the constructor whose code is
    // run only when the contract is created.
    constructor() public {
        minter = msg.sender;
    }

    function mint(address receiver, uint amount) public {
        require(msg.sender == minter);
        require(amount < 1e60);
        balances[receiver] += amount;
    }

    function send(address receiver, uint amount) public {
        require(amount <= balances[msg.sender], "Insufficient balance.");
        balances[msg.sender] -= amount;
        balances[receiver] += amount;
        emit Sent(msg.sender, receiver, amount);
    }
}

가상 화폐(코인) 계약은 위와 같다. 정말 간단하다. 저렇게 간단한데, 코인 발행와 송금, 조회가 가능하다.

위 코드를 한 줄씩 읽어나가면 이렇게 된다.

코드 요약

  • 코인 발행자는 minter 라는 주소. (위 계약을 deploy할때 선택한 계정이 발행자가 된다. 중요하다.)
  • 주소마다 매핑된 balances가 있다. 즉, 주소로 코인 잔고 조회가 가능하다.
  • Sent는 이벤트로 송금이 완료되면 발생시키려고 만든 것이다. send 함수 마지막에 보면 호출한다.
  • 생성자(constructor)에서는 최초에 deploy시 사용자를 minter 발행자로 지정한다.
  • mint는 코인을 receiver로 amount 만큼 발행해 준다. (코인을 찍어서 준다.)
  • mint 조건을 보면 발행자만 mint를 사용할 수 있다. 금액 제한은 걸려있다. 수신자의 balances에 금액을 추가한다.
  • send는 코인 송금이다. 수신자 주소와 금액을 넣게 되어 있다.
  • send의 조건은 요청자(msg.sender)의 잔고 금액이 amount(송금금액)보다 커야 한다.
  • send에서는 송신자의 잔고에서 금액을 빼서 수신자의 잔고에 추가한다. 마지막에 송금완료 이벤트(Sent)를 발생시킨다.

저렇게 간단한 코드로 이 기능이 다 되는건가? 실제 테스트를 해 볼 수 있다.

테스트

  • deploy 계정 : 0xCA… (주소는 길기 때문에 여기서는 생략함)
  • balances에 위 계정을 입력하여 확인. 코인 잔고는 0으로 나옴.
    image
  • 나부터 코인을 찍어보자. 1000개.
    발행자만 가능하니 account는 0xCA… 로 설정하고,
    mint로 수신자 0xCA…, amount는 1000으로 해서 tranact 발생! 이후 다시 balances로 확인. 1000 코인이 발행되어 잘 들어왔다.
    image
  • 이제 다른 계정으로 발행해 보자. 계정을 0x147…로 바꿔서 mint를 해보니, 발행자 권한이 아니라 거부된다. 현재 잔고는 0으로 조회된다.
    image
    -원래 계정 0xCA에서 100원만 0x147한테 주자. 전송할때는 계정을 0xCA로 바꾼다음, send에 receiver와 amount를 입력하고 transact를 한다. balances조회하면 100 코인이 정상적으로 수신되었다. 0xCA로 balances를 조회하면 100코인이 줄어 900코인이 된 것을 확인할 수 있다.
    imageimage

Author: crazyj7@gmail.com

'BlockChain' 카테고리의 다른 글

Solidity#2 HelloWorld  (0) 2019.12.06
Solidity 0.4 vs 0.5  (0) 2019.12.06
Windows Ethereum python module install error  (0) 2019.12.04
[ether01] solidity 맛보기  (0) 2019.11.10
이더리움개발 환경 준비  (1) 2019.11.10
반응형
Ethe00_Setup

Etherium

이더리움 주소

  1. 개인키 생성
  2. 개인키에서 공개키 생성
  3. keccak256으로 공개키의 해시값 생성
  4. 해시값에서 뒤쪽 20바이트를 이더리움 주소로 사용한다.

계정

  1. 외부 소유계정 (EOA)
    다른 계정과 이더 송수신 및 컨트랙트에 트랜잭션 전송도 가능

  2. 컨트랙트 계정
    개인키가 없다. 스마트계약을 블록체인에 배포시 생성됨.
    다른 계정과 이더 송수신 가능.
    코드를 감고 있다.
    EOA나 다른 컨트랙트의 영향으로 트랜잭션을 발생시킬 수 있다.

지갑

이더리움 계정을 저장하고 관리
여러 계정을 관리하고 트랜잭션에 서명, 잔고 추적 등.

가스

스마트 계약 배포, 트랜잭션 실행등에 비용이 소모된다. 채굴자에게 이더를 지불해야한다. 트랜잭션에 얼마나 많은 단위연산이 포함되는지에 따라 비용이 결정됨. 연산의 단위를 가스라고 한다.

가스 가격

트랜잭션 생성자가 원하는 가스 가격을 정할 수 있다. 가스당 3wei 처럼 설정한다. 설정한 가스가격이 높을 수록 트랜잭션 처리 속도가 빠르다. 채굴자들이 높은 가격순으로 처리하기 때문.

가스 한도

트랜잭션 수행 최대 금액을 지정할 수 있다. 블록가스 한도와 다르다.

바이트 코드

스마트 계약 코드는 solidity 언어로 작성 EVM 바이트코드로 컴파일하여 EVM(이더리움 VM)에서 실행된다.

게스(Geth)/패리티(Parity) 클라이언트

geth는 이더리움재단에서 제공하는 공식 클라이언트. (Go로 개발). geth는 블록체인의 복사본을 최신 상태로 유지하고 위해 계속 통신한다. 블록을 채굴하고, 블록체인에 트랜잭션을 추가하고 검증하고 실행한다. API를 제공하기도 한다.

Web3JS

이더리움과 상호작용하는 javascript library.

가나슈. 메모리블록체인 개발테스트
https://www.trufflesuite.com/ganache

지갑관리
https://metamask.io/

메인넷 모니터링
https://etherscan.io/

https://www.etherstudy.net/geth.html

geth 다운로드 설치

https://geth.ethereum.org/downloads/

> geth --dev console
> eth.blockNumber

가나슈설치

Ganache
https://www.trufflesuite.com/ganache
또는
https://github.com/trufflesuite/ganache/releases

온라인 solidity 개발

https://remix.ethereum.org/#optimize=false&evmVersion=null

윈도우/linux solidity compiler

https://github.com/ethereum/solidity/releases

https://github.com/ethereum/solidity/releases/download/v0.5.12/solidity-windows.zip

가나슈가 개발 테스트시에는 빠르다. 추천! (단, 키스토어가 없다. 개인키 접근이 필요하면 복호화된 스트링을 복사해서 사용한다. UI에 열쇠모양 클릭.)

geth는 메모리를 많이 먹어서 느림. 대신 키스토어에 개인키 저장.

py-solc 모듈이 solidity 여러가지 버전에 대해서 잘 지원이 안되는 듯함. python내에서 source compile시도시 에러발생.
커맨드로 빌드하여 output을 파일에 생성하고, 그 파일을 파이썬에서 읽어서 설정하는 방식으로 해야 할 듯 하다.

solc 컴파일러는 버전에 따라 다르니 주의가 필요하다. ubuntu에서 구버전 solc 를 설치하려면?

우분투에서 apt-get 으로 설치하면 최신버전의 solc가 설치된다.
구버전을 사용하려면 위 사이트에서 구버전 soliidity-ubuntu-trusty-clang.zip을 받아서 설치한다.
실행시 libz3 에러가 발생?? 하면 아래와 같이 라이브러리를 설치해 준다. 그 외에도 여러가지 개발툴들을 설치한다.
apt-get -y install build-essential cmake g++ gcc git unzip
apt-get install libz3-dev
solc --version

강좌

https://www.ethereum.org/ko/developers/#%EC%8B%9C%EC%9E%91%ED%95%98%EB%A9%B4%EC%84%9C

https://solidity-kr.readthedocs.io/ko/latest/

https://winterj.me/smart-contract-with-python/


실습

  • geth 설치
sudo add-apt-respository -y ppa:ethereum/ethereum
sudo apt-get update
sudo apt-get install ethereum
sudo apt install golang-go

확인
geth version
1.9.6-stable
go version
1.10.4
  • genesis 블록 설정
    genesis.json 파일 생성
$ cat genesis.json 
{
    "config": {
        "chainId": 16,
        "homesteadBlock": 0,
        "eip150Block": 0,
        "eip155Block": 0,
        "eip158Block": 0
        },
    "nonce": "0x0000000000654123",
    "timestamp": "0x00",
    "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "extraData": "0x00",
    "gasLimit": "0x2db7579a600",
    "difficulty": "0x20",
    "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "coinbase": "0x0000000000000000000000000000000000000000",
    "alloc": {}
}
  • difficulty 값은 채굴난이도로 낮을수록 빨리캔다. 위의 설정에서는 32가 된다.
  • geth 접속 후, eth.getBlock(0) 으로 확인할 수 있다.

초기화

현재 폴더에서 chain-data 폴더가 만들어진다. 데이터는 다 그곳에 저장됨. (geth, keystore 등)

geth init genesis.json --datadir chain-data
geth --datadir chain-data console

구동

접속을 쉽게하려면 rpc를 만들어 놓자. 아래와 같은 start.sh 스크립트를 만들어 저장해 두고 실행하자. 기본 포트는 8545인데, 여기서는 8485로 변경하였다. (주의!)
원격에서 계정 unlock을 허용하려면 --allow-insecure-unlock 옵션을 추가한다.

just running...
> geth --datadir ./chain-data console
> 최초 계정을 만들어 주어야 한다. 없으면 마이닝 모드 구동시 
> ether base가 없다고 에러가 남.
> 
> personal.newAccount('pass')
> 파라미터가 암호임. 반복하여 여러개의 계정을 임시로 만들어 본다.
> exit

start with options...
> cat start.sh
geth --rpc --rpcport 8485 --rpccorsdomain "*" --datadir "./chain-data" --port 30303 --nodiscover --rpcapi "db,eth,net,web3" --networkid 15 console
다른예) 위와 같이 실행해서 계정을 만든 다음 다음부터 아래처럼 실행
geth --rpc --rpcport 8545 --rpccorsdomain "*" --datadir "./chain-data" --port 30303 --nodiscover --mine --minerthreads 1 --allow-insecure-unlock --rpcapi "admin,personal,miner,db,eth,net,web3" --networkid 15 console
> ./start.sh
실행하면 메시지와 함께 콘솔이 뜬다.

내가 쓰는 구동 스크립트

> cat start3.sh
> geth --rpc --rpcport 8485 --rpcaddr "0.0.0.0" --rpccorsdomain "*" --datadir "./chain-data" --port 30303 \
--allow-insecure-unlock --mine --minerthreads 5 --identity private_chain \
--rpcapi "personal,miner,admin,db,eth,net,web3" --networkid 15 console
  • 윈도우에서 구동시 CPU100% 먹길래 "minerthreads 1"을 삭제해주니까 CPU가 정상적으로 떨어졌다. (참고) 또는 5나 10정도로 설정한다.
  • 구동해 놓으면 coinbase 계정으로 이더가 알아서 쌓이기 시작한다.
  • 마이닝이 안되면 miner.start(5) 이렇게 쓰레드를 지정해서 시작해 보자.
  • 그래도 마이닝이 계속 안되면, 작업관리자를 띄워서 메모리를 살펴보자. 메모리가 점점 증가하다가 1기가 좀 넘어서 기다리면 그 때 부터 CPU를 막 잡아먹기 시작하면서 마이닝을 할 것이다. 컴퓨터 성능에 따라 마이닝 하는데 시간이 좀 걸릴 수 있으니 기다려라.

로컬의 다른 쉘에서 geth 연결하기

geth 구동시 datadir에 설정된 경로에 geth.ipc라는 파일이 생기는데 그것으로 연결한다.

$ geth attach ./chain-data/geth.ipc
or
$ geth attach http://localhost:8485 (rpc:http://... 이렇게도 가능)
일부 작업이 제한될 수 있다. geth 시작시 옵션 설정이 필요.
  • 간단한 명령어
    eth.accounts : 계정 목록
    eth.blockNumber : 현재 채쿨된 블록 번호
    eth.hashrate
    eth.coinbase : 채굴 보상받을 계정. 디폴트는 eth.accounts[0]
    eth.mining : 마이닝 상태 on/off
    eth.getBalance(account) : 잔고
    eth.getTransaction(tx) : TX 정보
    miner.start() : 함수를 호출하여 마이닝 시작. 파라미터 1,2등 thread개수옵션
    miner.stop() : 마이닝 중지
    miner.setEtherbase() : 채굴 보상 계정 설정
    personal.newAccount(password) : 계정 생성
    personal.unlockAccount(account, password) : 계정 잠금 해제 (송금등 TX발생시 사전필요작업임)

  • 콘솔 연결 후 작업

personal.newAccount('pass')
personal.newAccount('pass')
personal.newAccount('pass')
personal.newAccount('pass')
위와 같이 테스트 계정들을 만들어 준다. 암호는 일단 다 pass로 하였음.
eth.mining : 마이닝 상태 확인. 
miner.start() : 마이닝이 멈춰있으면 마이닝을 시작한다.
잠시 후,첫번째 계정 잔고를확인한다.
eth.blockNumber
eth.getBalance( eth.accounts[0] ) : 0번 사용자 잔고 확인.

계정의 키는 데이터 루트 폴더(chain-data)안에 keystore 폴더에 계정별로 저장되어 있다.

  • 방화벽
    아까 rpc port로 설정했던 포트를 연다.
    ufw allow 8485

  • remix연결
    Env. web3provider
    http://172.16.100.88:8485
    원격 주소로는 접속이 안되는 것인지??? 계속 실패하였음.
    그래서 ssh로 포트 터널링하여 로컬로 연결함. (참고로 서버 ssh포트는 2222로 변경된 상태)
    접속 실패 원인을 찾아보니, rpcaddr을 안 줘서 그런 거였다.

ssh -L 8545:localhost:8485 blockchain@172.16.100.88
   -p 2222

위와 같이 로컬 8545를 원격의 8485로 연결해 놓고, remix에서 web3 provider에 주소를 로컬 주소를 주었다.
http://localhost:8545

  • smart contract deploy (배포)

계정 unlock을 해 주어야 한다 (unlock을 해주지 않으면 deploy나 set이 안된다.)
한 번 해두면 일정시간만 허용되는 것 같고, 시간이 지나면 자동으로 잠긴다.
personal.unlockAccount(eth.accounts[0])
위 커맨드가 작동하지 않는다면, geth 구동 스크립트에 옵션을 추가해 주어야 한다. –allow-insecure-unlock

remix로 contract를 deploy 시도 및 API 테스트를 했는데, 계속 가스 초과 에러가 발생하였다.
여러가지 시도 끝에, solidity compiler 버전을 0.4.23으로 낮추고 deploy를 하니 정상적으로 작동하였다. 계속 삽질을 했다는…
또 어디서는 genesis에 chainId가 0이면 그런 증상이 발생해서 42정도로 설정하여 해결했다는 얘기도 있다. 나의 경우는 chainId 설정을 하지 않았는데( config 필드가 empty) 위와 같이 해결하였음.
잘 안되면 남들하는 버전을 보고 연관되어 돌아가는 버전을 모두 맞춰 시도해보는 것도 좋다.

참고
원격 접속용 geth 구동

$ nohup geth --networkid 4649 --nodiscover --maxpeers 0 --datadir ~/Blockchain/data_testnet --mine --minerthreads 1 --rpc --rpcaddr "0.0.0.0" --rpcport 8545 --rpccorsdomain "*" --rpcapi "admin,db,eth,debug,miner,net,shh,txpool,personal,web3" --unlock 0,1 --password ~/Blockchain/data_testnet/passwd --verbosity 6 2>> ~/Blockchain/data_testnet/geth.log &

rpc ; http-rpc 활성화
rpcaddr : 접속 가능한 주소 0.0.0.0는 any 허용. 127.0.0.1을 입력하면 로컬호스트에서만 접속 가능. 자신의 IP 주소를 주면 그 IP로 접근이 허용된다.
rpcapi : rpc에서 허용가능한 모듈을 지정. 여기에 miner, personal 등이 들어가면 사용 가능.
unlock : 계정 잠금 해제. geth에서 해당 계정에 암호없이 접근 가능.

많이 쓰는 명령어

잔고 조회
eth.getBalance(eth.accounts[0])

전송 : 10이더를 해당 사용자에게 전송
personal.unlockAccount(eth.accounts[0])
패스워드(pass) 입력

eth.sendTransaction( {from: eth.accounts[0], 
   to:"0xc8cafbebb42f522f040d5690b1b220c3a9aed8f1", 
   value:web3.toWei(10,"ether")})

eth.getBalance("0xc8cafbebb42f522f040d5690b1b220c3a9aed8f1")

마이닝
eth.mining  : 현재 마이닝 상태
miner.start(1)
miner.stop()

계정
eth.accounts : 계정 목록 조회
personal.newAccount('password') : 계정 생성
personal.unlockAccount(eth.accounts[0]) : 잠금해제

SubLimeText 에서 solidity code intelligence 지원

Ctrl+Shift+P를 누르고 install 을 치고 install package 실행
잠시 기다리면, 입력창이 뜸.
ethereum을 입력. Ethereum을 설치
다시 한 번 반복하고 이번엔 EthereumSoliditySnippets를 설치
다시 시작하면 적용 완료.

강좌

https://www.ethereum.org/ko/developers/#%EC%8B%9C%EC%9E%91%ED%95%98%EB%A9%B4%EC%84%9C

https://solidity-kr.readthedocs.io/ko/latest/

https://winterj.me/smart-contract-with-python/

Author: crazyj7@gmail.com

'BlockChain' 카테고리의 다른 글

Solidity#2 HelloWorld  (0) 2019.12.06
Solidity 0.4 vs 0.5  (0) 2019.12.06
Windows Ethereum python module install error  (0) 2019.12.04
[ether02] 코인만들기  (0) 2019.11.10
[ether01] solidity 맛보기  (0) 2019.11.10

+ Recent posts