Download - Dapp튜토리얼 - 이더리움(Ethereum) 개발자 모임
이더리움 개발자 스터디 15.03.04 Ethereum Seoul 서울 비트코인 센터 심지홍 ([email protected])
Setting up your development environment
• Alethzero
• POC 8
• 컴파일러, 자바스크립트 콘솔 내장
• 블록체인 상태 조회 가능
• MIX
• javascript, html, contract 통합개발툴
• contract 작성시 step-by-step debugging 가능
• Mist
• end user 대상
• Dapp store 탑제
Your first Dapp
• mapping (address=>uint) balances;
• contract의 storage에 address, uint 타입으로 balances를 참조로 mapping
• balances[msg.sender] = 10000
• msg.sender : msg는 전역변수이고 transaction 발신자의 160bit public address를 의미
• sha-3 알고리즘으로 암호화
• key/value pair data type
contract metaCoin { mapping (address => uint) balances; function metaCoin() { balances[msg.sender] = 10000; }
function sendCoin(address receiver, uint amount) returns(bool sufficient) {
if (balances[msg.sender] < amount) return false;
balances[msg.sender] -= amount; balances[receiver] += amount; return true; }}
Your first Dapp
• function metaCoin(){}
• 모든 contract의 초기화 함수
• contract name과 같아야 함
• contract가 실행될 때 단 한번 실행되고 다시는 실행될 수 없음
• function sendCoin(address receiver, uint amount) returns(bool sufficient) {}
• 모든 함수는 ABI (Application Byte Interface)를 가짐
• 함수를 호출할 때 ABI, receiver, amount 가 필요
contract metaCoin { mapping (address => uint) balances; function metaCoin() { balances[msg.sender] = 10000; }
function sendCoin(address receiver, uint amount) returns(bool sufficient) {
if (balances[msg.sender] < amount) return false;
balances[msg.sender] -= amount; balances[receiver] += amount; return true; }}
Typing and Your Contracts Storage
• hash: 256-bit, 32-byte data chunk, indexable into bytes and operable with bitwise operations.
• uint: 256-bit unsigned integer, operable with bitwise and unsigned arithmetic operations.
• int: 256-bit signed integer, operable with bitwise and signed arithmetic operations.
• string32: zero-terminated ASCII string of maximum length 32-bytes (256-bit).
• address: account identifier, similar to a 160-bit hash type.
• bool: two-state value.
Typing and Your Contracts Storage - Structs
• Structs
• 정의된 structs는 스토리지에 아무것도 쓰지 않음
• 스토리지에 데이타를 쓰기 위해 structs를 선언하고 instance를 생성해야함
• key 는 0x0 부터 저장
contract Test{ struct coinWallet { uint redCoin; uint greenCoin; } coinWallet myWallet; function Test(){ myWallet.redCoin = 500; myWallet.greenCoin = 250; }}
Typing and Your Contracts Storage - Structs
• mapping + struct로 테이블 구조 구현 가능
• mapping(type => struct name) mappingName
• balances[msg.sender].redCoin = 10000
contract metaCoin {struct coinWallet {
uint redCoin; uint greenCoin;
} mapping (address => coinWallet) balances; function metaCoin() { balances[msg.sender].redCoin = 10000; balances[msg.sender].greenCoin = 5000; } function sendRed(address receiver, uint amount) returns(bool successful) { if (balances[msg.sender].redCoin < amount) return false; balances[msg.sender].redCoin -= amount; balances[receiver].redCoin += amount; return true; } function sendGreen(address receiver, uint amount) returns(bool successful) { if (balances[msg.sender].greenCoin < amount) return false; balances[msg.sender].greenCoin -= amount; balances[receiver].greenCoin += amount; return true; }}
sha3(address) redCoin(sha3(address))
greenCoin(sha3(address)+1)
blueCoin(sha3(address)+2)
0x0046.. 10000 10000 10000
0xd203.. 5000 9000 2000
0xc343. 3000 6000 10000
Typing and Your Contracts Storage - Structs
• mapping을 중첩 선언 함으로써 key 를 2개 갖는 structs 구현
• ex) data[4][9].b
• sha3(uint256(9) . sha3(uint256(4) . uint(256(1))) + 1.
contract c { struct S { uint a; uint b; } uint x; mapping(uint => mapping(uint => S)) data;}
Typing and Your Contracts Storage
contract rainbowCoin {mapping (address => mapping (uint => uint)) balances;function rainbowCoin() {
balances[msg.sender][0] = 10000; ///red coinbalances[msg.sender][1] = 10000; ///orange coinbalances[msg.sender][2] = 10000; ///yellow coinbalances[msg.sender][3] = 10000; ///green coinbalances[msg.sender][4] = 10000; ///blue coinbalances[msg.sender][5] = 10000; ///indigo coinbalances[msg.sender][6] = 10000; ///violet coin
}function sendCoin(address receiver, uint amount, uint coin) returns(bool successful) {
if (balances[msg.sender][coin] < amount) return false;balances[msg.sender][coin] -= amount;balances[receiver][coin] += amount;return true;
}}
Typing and Your Contracts Storage -Accessor Functions
• Accessor Functions : 접근자
• ex) mapping (address => mapping (uint => uint)) public balances;
• mapping name 앞에 public을 선언
• 외부에서 ABI를 통해 mapping에 접근해 스토리지를 제어 할 수 있음
JavaScript API 1
• web3.eth.watch : 블록체인 모니터링
• web3.eth.watch(‘chain’) , web3.eth.watch(‘pending’)
• web3.eth.watch(‘chain').changed(function(){})
• 블록체인의 상태가 변하면 실행하여 프론트랜드를 동적으로 컨트롤 가능
• web3.eth.coinbase
• 마이닝하거나 트렌젝션을 보낼 때 사용하는 본인의 어카운트
• web3.eth.storageAt(contractAddress)
• 컨트랙의 스토리지지의 모든 내용을 JSON 객체로 리턴
• var storageObject = web3.eth.storageAt(contractAddress);
JavaScript API 1
web3.eth.watch('chain').changed(function(){ var coinbase = web3.eth.coinbase; document.getElementById('coinbase').innerText = coinbase; var balance = web3.eth.balanceAt(coinbase); document.getElementById('balance').innerText = balance;});
web3.eth.watch('pending').changed(function(){ var coinbase = web3.eth.coinbase; document.getElementById('coinbase').innerText = coinbase; var balance = web3.eth.balanceAt(coinbase); document.getElementById('balance').innerText = web3.toDecimal(balance);});
///Insert your contract address var here: var contractAddress = "0x8026692b5e9c0e9a7ee3c3c13187a1d5efbc423c";
web3.eth.watch('pending').changed(function(){ var blockNumber = web3.eth.number; document.getElementById('latestBlock').innerText = blockNumber; var hash = web3.eth.block(blockNumber).hash; document.getElementById('latestBlockHash').innerText = hash; var timeStamp = web3.eth.block(blockNumber).timestamp; document.getElementById('latestBlockTimestamp').innerText = Date(timeStamp); var contractString = JSON.stringify(web3.eth.storageAt(contractAddress)) document.getElementById('contractString').innerText = contractString; var storageObject = web3.eth.storageAt(contractAddress); document.getElementById('fullName').innerText = web3.toAscii(storageObject['0x']) + ' ' + web3.toAscii(storageObject['0x01']);});