Solidity

실습

정영태

Agenda

  1. geth 예제 / 명령어 확인
  2. solidity 소개/문법
  3. solidity 시연/코드 리뷰

블럭 생성 및 Geth 구동 예제

  1. genesis.json 설정 파일 생성
  2. 최초 블럭 생성
  3. geth console 기동
  4. 계정 생성 / 확인
  5. 채굴 명령
  6. 송금
  7. 트랜잭션 확인
  8. geth rpc 접속 테스트
  9. geth 원격 활성화

블럭 생성 및 Geth 구동 예제 - genesis.json

{
    "config": {},
    "coinbase" : "0x0000000000000000000000000000000000000000",
    "difficulty" : "0x1",
    "extraData" : "0x00",
    "gasLimit" : "0x47e7c5",
    "nonce" : "0x0000000000000042",
    "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
    "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
    "timestamp" : "0x00",
    "alloc" : { }
}
  1. 프로젝트 디렉토리 생성
    ex) c:\blockchain\test
  2. genesis 파일 저장

블럭 생성 및 Geth 구동 예제 - 블럭 생성

geth --datadir "프로젝트 경로" init "프로젝트 경로"/genesis.json
-----------------------------------------------------------------

geth --datadir "c:\blockchain\test" init "c:\blockchain\test\genesis.json"

블럭 생성 및 Geth 구동 예제 - geth 구동

geth --networkid 4648 --nodiscover --maxpeers 0 --datadir "c:\blockchain\test" console 2>> "c:\blockchain\test\geth.log"

블럭 생성 및 Geth 구동 예제 - 계정 생성 / 확인

-- 계정 추가
personal.newAccount("패스워드")
---------------------------------

personal.newAccount("study1")
personal.newAccount("study2")
personal.newAccount("study3")

-- 계정 확인
eth.accounts

블럭 생성 및 Geth 구동 예제 - 채굴 명령

-- 채굴 명령
miner.start(1) 
    => (thread_number) 채굴할 떄 사용되는 스레드 수
	- 생성이 안될 경우(블럭카운트) : miner.start() 로 실행
	- 최초 채굴에서 DAG(Directed Acyclic Graph) 파일이 생성되며, C:\Users\Administrator\AppData\Ethash에서 확인(홈경로임)

-- 채굴 중지
miner.stop()

-- 채굴 확인
eth.mining

블럭 생성 및 Geth 구동 예제 - 송금

-- 송금
eth.sendTransaction({from: eth.accounts[0], to:eth.accounts[1], value:web3.toWei(10, "ether")})
    => 잘못된 실행 방지로 계정이 잠겨있으므로 계정을 풀어주어야지 송금할 수 있음(송금자가 수수료를 내서 송금자 계정을 풀어줌)

-- 계정 잠금 해제
personal.unlockAccount(eth.accounts[0])
Passphrase: study1 입력

-- 재송금 실행
eth.sendTransaction({from: eth.accounts[0], to:eth.accounts[1], value:web3.toWei(10, "ether")})
    => 트랜잭션 코드 저장: 0x7b4480536323d1a7bf0120a64b68137af81dfe55c008bbe4a55ddcf44c4b8dec

-- 잔고 확인
eth.getBalance(eth.accounts[1])
    => 아직 블럭 생성 전이라 입금되지 않음

블럭 생성 및 Geth 구동 예제 - 트랜잭션 / 잔고 확인

-- 트랜잭션 확인 
eth.getTransaction("0x7b4480536323d1a7bf0120a64b68137af81dfe55c008bbe4a55ddcf44c4b8dec")
    => 블럭안에 트랜잭션이 포함되어야지만 처리가 된다. 현재 block생성 중지 상태임.
    => blockNumber: null 값 확인 
        => 미처리, 계류중의 상태를 의미

-- 계류 중인 트랜잭션 확인
eth.pendingTransactions

-- 채굴 재개
miner.start(1)

-- 계류 중인 트랜잭션 확인
eth.pendingTransactions

-- 트랜잭션 재확인
eth.getTransaction("0x7b4480536323d1a7bf0120a64b68137af81dfe55c008bbe4a55ddcf44c4b8dec")
    => blockNumber 기록

-- 블록 내용 확인
eth.getBlock(116)
    => 트랜잭션 정보 확인

-- 잔고 확인
web3.fromWei(eth.getBalance(eth.accounts[1]), "ether")

블럭 생성 및 Geth 구동 예제 - RPC 접속 테스트

-- 백그라운드 geth 기동
geth --networkid 4648 --nodiscover --mine --minerthreads 1 --rpc --maxpeers 0 --datadir "c:\blockchain\test" 2>> "c:\blockchain\test\geth.log"
    => mine: 채굴 활성화
    => minerthreads: 채굴에 사용할 CPU 쓰레드 수
    => rpc: HTTP-RPC 서버를 활성화

-- geth rpc 콘솔 접속
geth attach rpc:http://localhost:8545

-- 채굴 확인
eth.mining

블럭 생성 및 Geth 구동 예제 - RPC 원격 활성화

-- 백그라운드 geth 기동 - 원격 활성화
geth --networkid 4648 --datadir "c:\blockchain\test" --nodiscover --mine --minerthreads 1 --maxpeers 0 --rpc --rpcaddr "0.0.0.0" --rpcport 8545 --rpccorsdomain "*" --unlock 0 --password "c:\blockchain\test\password"
    => rpc 
	HTTP-RPC 서버를 활성화
    => rpcaddr "0.0.0.0"
	HTTP-RPC 서버의 수신 IP지정, 기본값 localhost이며, "0.0.0.0"으로 지정하면 어떠한 인터페이스에 대한 접근도 허용한다.
    => rpcport 8545
	기본 포트는 8545
    => rpccorsdomain "*"
	자산의 노드에 RPC로 접속할 IP주소를 지정한다. 쉼표로 구분할 수 있으며, "*" 지정하면 모든 IP를 허용한다.
    => rpcapi "admin,db,eth,debug,miner,net,ssh,txpool,personal,web3"
        RPC API 허가 대상을 지정하며, 기본값은 "eth,net,web3"

Solidity

  • 이더리움 스마트 계약에서 사용되는 언어

Solidity - 설치

Solidity Code

pragma solidity ^0.4.0;

contract HelloWorld {

    string public greeting;

    function HelloWorld(string _greeting){
        greeting = _greeting;
    }

    function setGreeting(string _greeting) public{
        greeting = _greeting;
    }
    
    // 블럭체인에 저장된 데이터 변경을 
    //   하지 않을 경우 constant 선언    
    function say() public constant returns (string) {
        return greeting;
    }
}

컴파일러 버전 선언

계약 선언

변수 선언

생성자

함수

return 함수

Solidity 자료형

  • 기본형
    • int
      • 부호 있는 정수
    • uint
      • 부호 없는 정수
    • bool
      • 참(true)/거짓(false)
    • string
      • 문자
  • 참조형
    • array
    • mapping
      • key-value hash
    • struct
      • 구조체

 

  • 특화형
    • address
      • 이더리움 주소
  • 지원안함
    • double

Solidity 자료형 - address

  • 계약에 사용되는 주소를 저장 
  • method 제공
    • balance
      • 주소에 해당되는 Ether를 wei 단위로 반환.
      • 반환값은 uint256
    • transfer(uint256 amount)
      • 주소에 Ether를 amount만큼 전송. wei 단위
      • 실폐 시 예외가 발생
    • send(uint256 amount) returns (bool)
      • transfer와 동일하지만 실패 시 false 반환
    • call.value(uint256 amount).gas(unit 256 val)() returns (bool)
      • 전송하는 것은 동일하지만 더 낮은 수준으로 평가한다.
      • gas 값을 지정하여 보낼 수 있고, 실패 시 false 반환

Solidity 자료형 - struct

  • 구조체 정의 
contract StructSample {
    struct User {
        address addr;
        string name;
    }

    User[] public userList;     // 구조체를 담는 배열 선언

    function addUser(string _name) returns (unit) {
        unit id = userList.push(User({
            addr: msg.sender,
            name: _name
        }));

        rerturn (id - 1);
    }
}

Solidity 자료형 - mapping

  • key - value  형태의 구조
contract MappingSample {
    struct User {
        address addr;
        string name;
    }

    mapping(address=>User) public userMap;    // key-value 유저 Map

    function setUser(string _name, uint _age) {
        // msg.sender를 키로 지정
        userMap[msg.sender].name = _name;
        userMap[msg.sender].age = _age;
    }

    function getUser() returns (string, uint) {
        User storage u = userMap[msg.sender];
        return (u.name, u.age);
    }
}

Solidity 자료형 - 시간 단위

contract TimeSample {

    uint public startTime; 설정 시간

    function setTime() {
        // now는 block.timestamp의 별칭임. 현재 시간의 의미가 아님
        startTime = now;    
    }
    // 시작 시간으로부터 지정한 '분'만큼 경과했는지 확인
    function minutesAfter(uint min) constant returns (bool) {
        if( startTime == 0 ) return false;
        return ((now - startTime) / 1 minutes >= min);
    }
}
  • 상수 값 뒤에 시간단위를 나타내는 문자열로 표현
       ex) 1 minutes, 3 seconds

Solidity 전역 속성 - block, msg 등

  • contract 내에 전역으로 접근 가능한 변수
전역 변수 데이터 형식 설명
block.blockhash bytes32 지정한 블록의 해시 값
block.coinbase address 해당 블록 채굴자의 주소
block.number uint 해당 블록의 번호
block.timestamp uint 해당 블록의 타임스탬프
msg.sender address 송금자 주소(현재 주소)
msg.value uint 송금액
now unit block.timestamp 별칭

Solidity 함수 - payable

  • 이더리움 전송에 필요한 method
  • 이 외의 function에서 이더리움을 전송한다면, 모두 reject 시킴
contract Transfer{

    address public owner;

    function() payable {
        // 계좌 잔고나 owner등을 체크하여 전송을 실행
    }
}

Solidity 함수 - modifier

  • 함수 실행전에 실행 조건에 대한 체크
  • 여러개의 modifier를 정의하여 사용할 수 있음
contract Modify{

    address public owner;
    // 실행하는 주소와 owner(계약 생성 주소)가 동일한지 체크
    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }
    // distribute function 실행 전에 onlyOwner 체크
    function distribute(address depositor) onlyOwner {
        balances[depositor] +=  100;
    }
}

Solidity 계약 시연

Solidity 코드 리뷰

pragma solidity ^0.4.0;

contract bankcontract {
    uint private balance;

    address public owner;

    function bankcontract() public {
        owner = msg.sender;
    }

    function deposit() public payable {
        balance += msg.value;
    }

    function withdraw(uint amount) public {
        if(balance >= amount){
        //if(msg.sender == owner && balance >= amount){
            balance -= amount;
            if(!msg.sender.send(amount)){
                  balance += amount;
            }
        }
    } 

    function getBalance() public constant returns(uint) {
        return balance;
    }
}

Tha

nks

Solidity 실습

By jungyoungtai

Solidity 실습

Solidity 실습 발표 자료

  • 1,303