Solidity
실습
정영태
Agenda
- geth 예제 / 명령어 확인
- solidity 소개/문법
- solidity 시연/코드 리뷰
블럭 생성 및 Geth 구동 예제
- genesis.json 설정 파일 생성
- 최초 블럭 생성
- geth console 기동
- 계정 생성 / 확인
- 채굴 명령
- 송금
- 트랜잭션 확인
- geth rpc 접속 테스트
- geth 원격 활성화
블럭 생성 및 Geth 구동 예제 - genesis.json
{
"config": {},
"coinbase" : "0x0000000000000000000000000000000000000000",
"difficulty" : "0x1",
"extraData" : "0x00",
"gasLimit" : "0x47e7c5",
"nonce" : "0x0000000000000042",
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp" : "0x00",
"alloc" : { }
}- 프로젝트 디렉토리 생성
ex) c:\blockchain\test - 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
- 문자
- int
-
참조형
- array
- mapping
- key-value hash
- struct
- 구조체
- 특화형
- address
- 이더리움 주소
- 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 반환
- balance
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