วันอาทิตย์ที่ 17 พฤศจิกายน พ.ศ. 2562

Code Client Smart Contract auto transfer

ในครั้งนี้เราจะมาทำให้ Smart Contract ของเรา transfer auto กันครับ

โดยเริ่มจากส่วนของ Smart contract ของเราก่อน เราได้เพิ่มฟังก์ชั่น " transfer " ซึ่งฟังก์ชั่นนี้จะรับพารามิเตอร์ 2 ตัวคือ

  1.  uint _amount ที่จะรับค่า "จำนวนที่ต้องชำระ" ( เป็น unsigned integer )
  2.  address _to   จะรับ address ของผู้รับ ( เป็นตัวแปรประเภท address )

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
    function transfer(uint _amount, address _to) public {
        
        require (balanceOf[msg.sender] >= _amount, "You don't have enough amount.");
        
        balanceOf[_to] += _amount;
        balanceOf[msg.sender] -= _amount;
        if(_amount == 1000){
            check = 1;
        }else{
            check = 0;
        }
        
    }

ฟังก์ชั่นนี้เมื่อรับค่าพารามิเตอร์มาแล้ว จะตรวจสอบจำนวนเหรียญที่เรามีก่อนถ้าไม่พอจะส่งข้อความแจ้งว่า "You don't have enough amount." ถ้ามีจำนวนพอจะทำการ transfer เหรียญไปให้ผู้รับตาม address
โดยเราจะ deploy จากนั้น ให้เราไปเอา ABI เพราะเราได้แก้ contract ไป

ต่อมาเราจะไปแก้ Code ส่วนของ Client


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
function transfer(){

  var _amount = 1000;
  var _to = 'address receiver'
  SimpleContract.transfer(_amount, _to,function(error,result){
    if(error){
      addStatusLine(error);
      return;
    }
    // addStatusLine("");
    addStatusLine("calling transfer("+result+")");
  });
}

ฟังก์ชั่น ที่เราเพิ่มเข้าไปคือ "transfer" ฟังก์ชั่นนี้เราต้องใส่ค่า address ลงไป และจำนวนเหรียญที่ต้องชำระ โดยฟังก์ชั่นนี้จะเรียกตามเวลาที่เรากำหนดเอาไว้ จะทำการหักเงินตามที่เรากำหนดไว้


Pic: Code Client

Pic: Code Client การเรียกใช้ฟังก์ชั่น transfer

สุดท้ายเราจะมาทดสอบ DApp ของเรา


Pic: DApp transferเรียบร้อย

Pic: ตรวจสอบยอดเงิน และสถานะการล็อคห้องเป็น 1 หรือ "true"


วันอาทิตย์ที่ 3 พฤศจิกายน พ.ศ. 2562

Code Client Smart Contract

โดยผมจะแบ่งเป็น สามส่วนครับ



1. CSS



 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
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Digital Lock</title>
  <style>
  body {
    background-color:#F0F0F0;
    padding: 2em;
    font-family: 'Raleway','Source Sans Pro', 'Arial';
  }
  .container {
    width: 50%;
    margin: 0 auto;
  }
  label {
    display:block;
    margin-bottom:10px;
  }
  input {
    padding:10px;
    width: 50%;
    margin-bottom: 1em;
  }
  button {
    margin: 2em 0;
    padding: 1em 4em;
    display:block;
  }

  #balance {
    padding:1em;
    background-color:#fff;
    margin: 1em 0;
  }
  #status {
    font-weight:normal;
    font-family: monospace;
    padding:1em;
    background-color:#fff;
    margin: 1em 0;
  }
  </style>
</head>

ส่วนนี้จะเป็นการตกแต่งหน้าเว็บของเราเช่น ปุ่มกด, พื้นหลัง และ อื่นๆ


2. Body



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<body>
  <!-- Form -->
  <div class="container">
    <h1>Basic Digital Lock</h1>

    <h2 id="showStatus">Status Room = <span id="statusRoom"></span></h2>
    <h3 id="time"> Time:  <span id="timeCount"></span></h3>

    <hr/>
    <br/>
    <h4 id="balance">Current Balance = <span id="currentBalance"></span></h4>
    <button id="button" style="display: block" onclick="javascript:getBalance()">Get New Balance</button>
    <hr/>
    <br/>
    <label for="newBalance" class="col-lg-2 control-label"><strong>New Balance</strong></label>
    <input id="newBalance" type="number" value="300" style="display: inline-block">
    <button id="button" style="display: inline-block" onclick="javascript:setBalance()">Set New Balance</button>
    <br/>
    <label><strong>Status</strong></label>
    <h4 id="status"></h4>
  </div>
</body>

เป็นส่วนที่เราสร้าง ปุ่มกด หรือ หน้าต่างแสดงสถานะต่างๆของเว็บเรา ซึ่งปุ่มกดจะไปเรียกใช้งานฟังกชั่นต่างๆ ในส่วนของ <script> ตามที่เรากำหนดไว้


3. script

     
        ในส่วนนี้จะสำคัญมาก เริ่มจาก JavaScript Loader กันก่อน โดยเราจะโหลดส่วนของ jquery และ web3 เข้ามาในไฟล์ Client ของเรา ซึ่งเราจะใช้ เพื่อติดต่อกับ smart contract ที่เรา deploy ไปเรียบร้อยแล้ว


1
2
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/ethereum/web3.js@1.0.0-beta.37/dist/"></script>

        ส่วนต่อมาจะเป็น ฟังก์ชั่นต่างๆ ใน Client ของเราโดยจะมีอยู่สามฟังก์ชั่นคือ


  • checkLock
       จะเป็นฟังก์ชั่นที่จะ นับเวลาเพื่อทำการโอนเหรียญอัตโนมัติ ตามเวลาที่เราระบุไว้ในสัญญา
  • getBalance
        เป็นฟังก์ชั่นที่มีไว้เช็ค Balance ในบัญชีของเราว่าเหลือเท่าไหร่
  • setBalance
       เป็นฟังก์ชั่นที่มีไว้ Set Balance ซึ่งฟังก์ชั่นนี้มีไว้เพื่อทดสอบเฉยๆว่า DApp ของเราสามารถโอนเหรียญและเช็ค Balance ได้จริงหรือไม่


 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
<script>
function addStatusLine(text) {
  document.getElementById("status").innerHTML = text + "<br/><br/>" + document.getElementById("status").innerHTML;
}
var countTime = setInterval(checkLock, 1000);
function checkLock() {
  var d = new Date();
  // TODO: Call checkLock Smart Contract
  //addStatusLine("calling checkLock");
  document.getElementById("timeCount").innerHTML = d.toLocaleTimeString();
  SimpleContract.checkLock(function(errorLock,resultLock){
    if (resultLock == 1) {
      document.getElementById("statusRoom").innerText = "OPEN";
   }else {
      document.getElementById("statusRoom").innerText = "LOCK";
   }

  })
}
function getBalance() {
  //var d = new Date();
  addStatusLine("");
  addStatusLine("calling getBalance()");
  // TODO: Call getBalance Smart Contract
  SimpleContract.getBalance(function(errorGet,resultGet){
    addStatusLine("Current balance =" + resultGet);
    document.getElementById('currentBalance').innerText=resultGet;
  })
}
function setBalance() {
  // TODO: Call setBalance Smart Contract
  //addStatusLine("called");
  newBalance =parseInt(document.getElementById('newBalance').value);
  //addStatusLine(newBalance);
  SimpleContract.setBalance(newBalance,function(error,result){
    if(error){
      addStatusLine(error);
      return;
    }
    // addStatusLine("");
    addStatusLine("calling setBalance("+newBalance+")");
    txHash = result;
    addStatusLine("TxHash = <a href='https://kovan.etherscan.io/tx/"+
    result + "' target='_blank'>" + result + "</a>");
  });
}

</script>

        ส่วนต่อมาเป็นส่วนที่เราจะตั้งค่าเกี่ยวกับ Smart Contract ที่เรา Deploy เอาไว้
  • ตั้งค่า Account ของเราให้ใช้ Metamask
  • ตั้งค่า Address และ ABI ของเรา 
ABI คือ ฟังก์ชั่นต่างๆใน Smart contract ของเรา ซึ่งถูกจักเก็บในรูปแบบของ JSON เราจะนำมาใส่ใน Client ของเรา เพื่อให้ Client ของเรารู้ว่า Smart contract มีฟังก์ชั่นอะไร มีข้อมูลอะไรส่งออกมา


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<script>
// Initializing
if (typeof web3 !== 'undefined') {
  web3 = new Web3(web3.currentProvider); // inject from Metamask plugin
}
// Get default address
web3.eth.defaultAccount = web3.eth.accounts[0];
window.ethereum.enable();
// TODO: Replace your SimpleContract contract address here
var contractAddress = 'ใส่ address ของเรา';
// TODO: Replace your SimpleContract abi here
var abi = ใส่ ABI ของเรา;
// Create an interface to SimpleContract on TomoChain
var SimpleContractContract = web3.eth.contract(abi);
var SimpleContract = SimpleContractContract.at(contractAddress);
// Get Balance on the first load
getBalance();
</script>

ก็จะจบในส่วนของการอธิบาย Code ครับ ด้านล่างนี้จะเป็น Code ตัวเต็มครับ ย้ำนิดนึงว่า
** ระวังส่วนของ JavaScript Loader ด้วยนะครับเพราะ Web3.js มีการ update บ่อยมาก **

Full Code


  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
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Digital Lock</title>
  <style>
  body {
    background-color:#F0F0F0;
    padding: 2em;
    font-family: 'Raleway','Source Sans Pro', 'Arial';
  }
  .container {
    width: 50%;
    margin: 0 auto;
  }
  label {
    display:block;
    margin-bottom:10px;
  }
  input {
    padding:10px;
    width: 50%;
    margin-bottom: 1em;
  }
  button {
    margin: 2em 0;
    padding: 1em 4em;
    display:block;
  }

  #balance {
    padding:1em;
    background-color:#fff;
    margin: 1em 0;
  }
  #status {
    font-weight:normal;
    font-family: monospace;
    padding:1em;
    background-color:#fff;
    margin: 1em 0;
  }
  </style>
</head>
<body>
  <!-- Form -->
  <div class="container">
    <h1>Basic Digital Lock</h1>

    <h2 id="showStatus">Status Room = <span id="statusRoom"></span></h2>
    <h3 id="time"> Time:  <span id="timeCount"></span></h3>

    <hr/>
    <br/>
    <h4 id="balance">Current Balance = <span id="currentBalance"></span></h4>
    <button id="button" style="display: block" onclick="javascript:getBalance()">Get New Balance</button>
    <hr/>
    <br/>
    <label for="newBalance" class="col-lg-2 control-label"><strong>New Balance</strong></label>
    <input id="newBalance" type="number" value="300" style="display: inline-block">
    <button id="button" style="display: inline-block" onclick="javascript:setBalance()">Set New Balance</button>
    <br/>
    <label><strong>Status</strong></label>
    <h4 id="status"></h4>
  </div>
</body>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/ethereum/web3.js@1.0.0-beta.37/dist/"></script>
<script>
function addStatusLine(text) {
  document.getElementById("status").innerHTML = text + "<br/><br/>" + document.getElementById("status").innerHTML;
}
var countTime = setInterval(checkLock, 1000);
function checkLock() {
  var d = new Date();
  // TODO: Call checkLock Smart Contract
  //addStatusLine("calling checkLock");
  document.getElementById("timeCount").innerHTML = d.toLocaleTimeString();
  SimpleContract.checkLock(function(errorLock,resultLock){
    if (resultLock == 1) {
      document.getElementById("statusRoom").innerText = "OPEN";
   }else {
      document.getElementById("statusRoom").innerText = "LOCK";
   }

  })
}
function getBalance() {
  //var d = new Date();
  addStatusLine("");
  addStatusLine("calling getBalance()");
  // TODO: Call getBalance Smart Contract
  SimpleContract.getBalance(function(errorGet,resultGet){
    addStatusLine("Current balance =" + resultGet);
    document.getElementById('currentBalance').innerText=resultGet;
  })
}
function setBalance() {
  // TODO: Call setBalance Smart Contract
  //addStatusLine("called");
  newBalance =parseInt(document.getElementById('newBalance').value);
  //addStatusLine(newBalance);
  SimpleContract.setBalance(newBalance,function(error,result){
    if(error){
      addStatusLine(error);
      return;
    }
    // addStatusLine("");
    addStatusLine("calling setBalance("+newBalance+")");
    txHash = result;
    addStatusLine("TxHash = <a href='https://kovan.etherscan.io/tx/"+
    result + "' target='_blank'>" + result + "</a>");
  });
}
// Initializing
if (typeof web3 !== 'undefined') {
  web3 = new Web3(web3.currentProvider); // inject from Metamask plugin
}
// Get default address
web3.eth.defaultAccount = web3.eth.accounts[0];
window.ethereum.enable();
// TODO: Replace your SimpleContract contract address here
var contractAddress = 'ใส่ address ของเรา';
// TODO: Replace your SimpleContract abi here
var abi = ใส่ ABI ของเรา;
// Create an interface to SimpleContract on TomoChain
var SimpleContractContract = web3.eth.contract(abi);
var SimpleContract = SimpleContractContract.at(contractAddress);
// Get Balance on the first load
getBalance();
</script>
</html>

วันอังคารที่ 29 ตุลาคม พ.ศ. 2562

Smart Contract คืออะไร ???

          ในการทำ สัญญา อาจจะมีปัญญาเรื่องความปลอดภัย เช่น การปลอมแปลงเอกสารแบบกระดาษ  หรือขั้นตอนในการมานั่งตรวจสอบเอกสาร
Nick Szabo จึงมองเห็นว่า "ในเมื่อหนึ่งในแนวคิดของ Blockchain คือการให้ทุกคนถือเอกสารชุดเดียวกัน เมื่อมีการอัปเดตก็จะอัปเดตด้วยกัน โดยมั่นใจได้ว่าเอกสารเหล่านั้น เชื่อถือได้แน่นอนไม่มีการปลอมแปลง" Nick Szabo จึงคิดริเริ่มนำ Blockchain มาประยุกต์ในการทำ สัญญา การทำดังกล่าวจึงได้ชื่อเรียกว่า Smart contect เจ้าสิ่งนี้สามารถแก้ปัญญาเรื่องความปลอดภัยและการปลอมแปลงเอกสารแบบกระดาษ อีกทั้งยังไม่ต้องผ่านคนกลาง อีกทั้ง Smart contect ยังมีความสามารถ กำหนดขั้นตอนการทำธุรกรรมโดยอัตโนมัติไว้ล่วงหน้า เพราะ สัญญาเกิดจากการเขียนโค้ดคอมพิวเตอร์ จึงสามารถกำหนด ธุรกรรม ล่วงหน้าได้
โดย Smart Contract มีคุณสมบัติว่า

1) ไม่สามารถเปลี่ยนแปลงได้
2) ทุกคนสามารถเข้าถึงและดูได้ว่าโค้ดเขียนไว้อย่างไร
3) สามารถสร้างลอจิคการทำงานได้ตามที่ต้องการ
4) สามารถบันทึกข้อมูลที่ต้องการลงใน Blockchain ได้
5) ข้อมูลที่ถูกบันทึกไว้จะอยู่ตลอดไป หากข้อมูลมีการเปลี่ยนแปลงก็สามารถตรวจสอบได้ เพราะข้อมูลไม่มีทางหายไป

            แต่ถึงแม้ว่า Smart Contract จะสามารถพัฒนาสัญญาแบบเก่าได้ แต่ก็ไม่มีอะไรที่ไม่มีข้อเสียเลย ในกรณีที่เขียนโค้ดผิดพลาดก็จะเกิดความเสียหายได้มหาศาล แม้กระทั่ง Vitalik Buterin ผู้สร้าง Ethereum Blockchain เองยังออกมาเตือนว่าไม่ควรทำ Smart Contract ที่มีมูลค่าสูงมาก ดังนั้นการศึกษาเรื่องกฎหมายที่เกี่ยวข้องกับ Blockchain จึงมีความจำเป็นมาก

ต่อไปนี้คือ บันทึกการทดลองทำ Smart Contract ของผมนะครับ


เขียน Smart Contract


การเขียน Ethereum Smart Contract จะใช้ภาษา Solidity ซึ่ง IDE ที่ช่วยเขียนในที่นี้เราจะใช้ Remix เนื่องจาก ง่ายต่อการใช้งาน ไม่ต้องติดตั้ง และมี env สำหรับการ Deploy Contract




Link: www.remix.ethereum.org

ซึ่ง Code จะเป็นการเก็บค่า balance และดึงค่า balance


pragma solidity >=0.4.22 <0.7.0;
contract SimpleContract {
    uint balance;
 
    constructor() public { // caleed since it deploy to blockchain
        balance = 1000;
    }
 
    function setBalance(uint newBalance) public {
        balance = newBalance;
    }
 
    function getBalance() public view returns (uint) {
        return balance;
    }
}
Pic: remix.ethereum

จากนั้นกด compile


Pic: remix.ethereum

จากนั้นเราจะมา deploy Smart Contract เราโดยเลือก Env = JavaScript VM แล้ว deploy


Pic: remix.ethereum

ทำการ Test Method โดยเรา Test Method getBalance จะได้ 1000 ตาม constructor ที่เรากำหนดไว้ตอนแรก

Pic: remix.ethereum


จากนั้นเราจะเขียน Solidity ทำ Contract "Smart Lock" กันครับ ว่าแต่ Smart Lock คืออะไร คือ Contract การเช่าห้อง หรือเช่าล็อกเกอร์ครับ โดยจะตัดเงินเราทุกๆวันที่ X ของทุกๆเดือน โดย Code Solidity ที่เราจะเขียนจะเป็นแบบนี้ครับ

Code
pragma solidity >=0.4.22 <0.7.0;
contract SimpleContract {    uint balance;        constructor() public { // caleed since it deploy to blockchain        balance = 1000;    }        function setBalance(uint newBalance) public {         balance = newBalance;    }        function getBalance() public view returns (uint) {        return balance;    }        function checkLock() public view returns (uint) {        if(balance < 1000){            return 0; //False: Lock         }else{         return 1; //True: Open      }                      }    }


Pic

Pic: remix.ethereum

        จะเห็นได้ว่าเราเพิ่ม method "checkLock" เจ้า method จัวนี้เมื่อเราเรียกใช้จะทำการเช็ค balance ว่ามีเท่าไหร่ถ้ามีไม่ถึงตามที่เรากำหนดไว้ (ในตัวอย่างนี้คือ 1000) จะ return 0 หรือ false แต่ถ้าถึงตามที่กำหนดจะ return 1 หรือ true ถึงตอนนี้ทุกคนคงสงสัยว่า แล้วแบบนี้จะเป็น Smart Lock ได้อย่างไรถ้าเราต้องมาเรียกใช้ method นี้ทุกๆเดือน ดังนั้นเราจึงต้องสร้าง DApp ครับ เพื่อให้เจ้า DApp มาติดต่อกับ Smart Contract ให้เราครับ 

        ขอนอกเรื่องนิดนึง DApp หรือ Decentralized Application เป็นการเอา Smart Contract เข้ามาใช้ร่วมด้วยกับ application ดังนั้นแอพของเราจะได้ประโยชน์จากความปลอดภัย ของ blockchain และแอพยังสามารถเรียกใช้ method ของ Smart Contract ได้ด้วย 

        ดังนั้นเราจะทำการ Deploy Contract ของเราเข้าไปใน Network ของ blockchain ซึ่งในบทความนี้จะใช้ blockchain ของ Kovan ครับ ซึ่ง kovan คือ Network ที่มีไว้ทดสอบ Deploy Smart Contract ของเราได้ แต่ก่อนที่เราจะ Deploy เราจะต้องมี EtherWallet ก่อน 

Metamask EtherWallet

โดยเราจะเลือกใช้ Metamask 

1) ติดตั้ง Browser Extension ชื่อว่า Metamask เป็น กระเป๋าตังค์ Ethereum 
2) ติดตั้งเสร็จจะได้ icon รูปหมาจิ้งจอก 

Pic: Metamask

        ให้กดเพื่อทำการตั้ง password ให้เรียบร้อย จากนั้นก็ Next ๆๆ Accept ๆๆ ให้เรียบร้อย (อย่าลืมจด Secret Backup Phrase 12 คำ ไว้ด้วยเอาไว้กู้ Account Wallet กลับมาและเอาไว้ confirm ในหน้าถัดไป)

3) เมื่อกดเข้าไปใน icon หมาจิ้งจอก ตั้งแต่นี้จะเรียก Metamask นะ จะได้หน้าต่างแบบนี้ครับ ให้เราเลือก กดปุ่มตามลูกศรสีแดงในรูปเพื่อไปเอา address wallet ครับ

Pic: Metamark

Pic: Metamark

4) ซึ่งในขั้นตอนนี้กดเปลี่ยนเป็น Kovan ด้วยนะ จึงทำการขอเหรียญ Ethereum ซึงขอฟรีได้วันละ 1 เหรียญ แต่เนื่องจากเหรียญฟรี จึงใช้ได้แค่ test นะครับใช้จริงไม่ได้นะ 




Pic: faucet.kovan

5) เราจะสามารถกดดูเหรียญของเราได้ที่ Metamark ครับ

Pic: Metamark

Deploy Contract

1) จากนั้นมา Deploy Smart Contract ไปที่ Injected Web3 แล้วกด Deploy


Pic: Remix

2) หน้าต่าง pop up Metamark จะเด้งขึ้นมา เป็นการเก็บค่าธรรมเนียมนิดหน่อยครับ

 
Pic: Metamark

3) เมื่อเรา Deploy เสร็จแล้วให้เข้ามาที่ Metamark ไปในส่วนของ history จะเจอส่วนของ Contract Deployment แล้วกดที่วงกลมสีแดงตามรูปเพื่อเข้าไปยังหน้าต่าง Kovan Network เพื่อเอา address 

Pic: Metamark

Pic: Kovan


4) จากนั้นไปเอา ABI จากหน้า remix ในส่วนของ complie 

Pic: Remix

5) สร้างไฟล์ index.html โดยมี code ดังนี้ โดยให้เอา address และ abi ของเราไปใส่ใน code ส่วนของ script 

*** ในส่วนของการอธิบาย Code ผมได้ทำเป็นบทความแยกไว้นะครับ ***
Link: https://selectedtopicenarudon.blogspot.com/2019/11/code-client-smart-contract_3.html

Code


  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
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Digital Lock</title>
  <style>
  body {
    background-color:#F0F0F0;
    padding: 2em;
    font-family: 'Raleway','Source Sans Pro', 'Arial';
  }
  .container {
    width: 50%;
    margin: 0 auto;
  }
  label {
    display:block;
    margin-bottom:10px;
  }
  input {
    padding:10px;
    width: 50%;
    margin-bottom: 1em;
  }
  button {
    margin: 2em 0;
    padding: 1em 4em;
    display:block;
  }

  #balance {
    padding:1em;
    background-color:#fff;
    margin: 1em 0;
  }
  #status {
    font-weight:normal;
    font-family: monospace;
    padding:1em;
    background-color:#fff;
    margin: 1em 0;
  }
  </style>
</head>
<body>
  <!-- Form -->
  <div class="container">
    <h1>Basic Digital Lock</h1>

    <h2 id="showStatus">Status Room = <span id="statusRoom"></span></h2>
    <h3 id="time"> Time:  <span id="timeCount"></span></h3>

    <hr/>
    <br/>
    <h4 id="balance">Current Balance = <span id="currentBalance"></span></h4>
    <button id="button" style="display: block" onclick="javascript:getBalance()">Get New Balance</button>
    <hr/>
    <br/>
    <label for="newBalance" class="col-lg-2 control-label"><strong>New Balance</strong></label>
    <input id="newBalance" type="number" value="300" style="display: inline-block">
    <button id="button" style="display: inline-block" onclick="javascript:setBalance()">Set New Balance</button>
    <br/>
    <label><strong>Status</strong></label>
    <h4 id="status"></h4>
  </div>
</body>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/ethereum/web3.js@1.0.0-beta.37/dist/"></script>
<script>
function addStatusLine(text) {
  document.getElementById("status").innerHTML = text + "<br/><br/>" + document.getElementById("status").innerHTML;
}
var countTime = setInterval(checkLock, 1000);
function checkLock() {
  var d = new Date();
  // TODO: Call checkLock Smart Contract
  //addStatusLine("calling checkLock");
  document.getElementById("timeCount").innerHTML = d.toLocaleTimeString();
  SimpleContract.checkLock(function(errorLock,resultLock){
    if (resultLock == 1) {
      document.getElementById("statusRoom").innerText = "OPEN";
   }else {
      document.getElementById("statusRoom").innerText = "LOCK";
   }

  })
}
function getBalance() {
  //var d = new Date();
  addStatusLine("");
  addStatusLine("calling getBalance()");
  // TODO: Call getBalance Smart Contract
  SimpleContract.getBalance(function(errorGet,resultGet){
    addStatusLine("Current balance =" + resultGet);
    document.getElementById('currentBalance').innerText=resultGet;
  })
}
function setBalance() {
  // TODO: Call setBalance Smart Contract
  //addStatusLine("called");
  newBalance =parseInt(document.getElementById('newBalance').value);
  //addStatusLine(newBalance);
  SimpleContract.setBalance(newBalance,function(error,result){
    if(error){
      addStatusLine(error);
      return;
    }
    // addStatusLine("");
    addStatusLine("calling setBalance("+newBalance+")");
    txHash = result;
    addStatusLine("TxHash = <a href='https://kovan.etherscan.io/tx/"+
    result + "' target='_blank'>" + result + "</a>");
  });
}
// Initializing
if (typeof web3 !== 'undefined') {
  web3 = new Web3(web3.currentProvider); // inject from Metamask plugin
}
// Get default address
web3.eth.defaultAccount = web3.eth.accounts[0];
window.ethereum.enable();
// TODO: Replace your SimpleContract contract address here
var contractAddress = 'ใส่ address ของเรา';
// TODO: Replace your SimpleContract abi here
var abi = ใส่ ABI ของเรา;
// Create an interface to SimpleContract on TomoChain
var SimpleContractContract = web3.eth.contract(abi);
var SimpleContract = SimpleContractContract.at(contractAddress);
// Get Balance on the first load
getBalance();
</script>
</html>


Test

1) ทำการติดตั้ง Web Server for Chrome แล้วกด Launch app 

Pic: Web Server for Chrome

2) ทำการเลือก folder ที่เรา save index.html 

Pic: Web Server for Chrome

3) ทำการเปิด browser url http://127.0.0.1:8887 เราจะได้ web application ของเราซึ่งจะมีการนับเวลาเพื่อทำการเช็ค Balance ของเรา ซึ่งตอนนี้ Balance ของเรามีอยู่ 1200 ดังนั้น Status Room = OPEN 
แต่ถ้าเรา setBalance ใหม่ให้ต่ำกว่า 1000 เมื่อถึงเวลาที่เราตั้งไว้ ก็จะพบว่า Status Room = close 

Pic: Basic Digital Lock 

Pic: Basic Digital Lock 

ครั้งหน้าเราจะมาทำให้ DApp ของเราตัดเงินได้อัตโนมัตินะครับ
Update 1/11/2019

วันจันทร์ที่ 28 ตุลาคม พ.ศ. 2562

Blockchain คืออะไร



บทความนี้ เรียบเรียงจาก "สิ่งที่ผมเข้าใจ" ผิดพลาดประการใดขออภภัยด้วยนะครับ
โดย ตัวอย่างในบทความนี้จะเน้นไปที่ ธนาคาร, บัญชี เพื่อให้ผู้อ่านมองภาพได้ง่าย และนึกถึงความปลอดภัยเสมอ


ระบบรวมศูนย์ (Centralized) 




Credit Pic: Nuuneol

      คือระบบรวมศูนย์เนื่ยคือ ระบบที่ต้องมีคนกลางเป็น ศูนย์กลาง ดังนั้นไม่ว่าจะทำอะไรก็ตามจะต้องทำผ่านคนกลาง ที่นี่ผมเดาว่าผู้อ่านน่าจะเริ่มคุ้นๆกับระบบ ศูนย์รวม ที่มันคุ้นๆเพราะว่า ระบบ ศูนย์รวม ก็คือธนาคารนั้นเอง เช่นถ้าเราจะโอนเงิน, เช็คยอดเงิน หรือ ธุรกรรมใดๆ ก็ต้องทำผ่านธนาคาร 
ข้อดี 
1. โอกาสเกิดการผิดพลาดต่ำ 
2. ดูแลง่าย

ข้อเสีย
1. การวางระบบศูนย์กลางนี้มีค่าใช้จ่ายสูง 
2. ในแง่ความปลอดภัย ต้องเชื่อใจคนกลาง 
3. ถ้าคนกลาง หรือ ศูนย์รวม มีปัญหาก็ต้องรอให้กลับมาทำงานตามปกติอย่างเดียว


ระบบแบบกระจาย (Distributed)




Credit Pic: Nuuneol

      ระบบแบบกระจาย ถูกสร้างมาเพื่อแก้ปัญหา ระบบศูนย์รวม โดยตัวระบบจะไม่มีการใช้งานคนกลาง ให้แต่ละคนถือชุดข้อมูลของตัวเองไว้เองเลย ซึ่งมันมีปัญหาแน่นอน เพราะถ้าไม่มีคนกลาง แล้วใครจะเป็นคนตรวจสอบข้อมูลว่า ข้อมูลนั้นถูกต้อง ซึ่งถ้ายกตัวอย่างเป็นเรื่องของ บัญชีธนาคาร ซึ่งแต่ละคนจะถือสมุดบัญชีของตัวเองไว้ ตามรูปแบบของ ระบบแบบกระจาย เราจะเห็นปัญหาได้ง่ายมาก เช่น

1) ถ้าเกิดในระบบมีคนเป็นโจรขึ้นมาแล้วแก้เลขในสมุดบัญชีตัวเอง
2) ในเมื่อต่างคนต่างถือสมุดบัญชี แล้วถ้าจะโอนเงินกัน คนโอนกับคนรับโอนต้องต่างคนต่างแก้เลขในสมุดบัญชีตัวเอง ถ้าเกิดแก้ผิดหรือถ้าจงใจเขียนผิด
3) เมื่อต่างคนต่างถือสมุดบัญชีของตัวเอง การโอนเงินก็เป็นปัญหาได้อีกเพราะคนรับโอนไม่รู้เลยว่าคนโอนมีเงินเท่าไหร่ ถ้าจะโอน 1,000 บาท แต่คนโอนดันมีอยู่ 100 บาท มันต้องโอนไม่ได้ แต่เนื่องจากคนรับโอนไม่รู้เลยว่าคนโอนมีเงินเท่าไหร่ มันก็เลยอาจจะเกิดกรณีที่เป็นปัญหาได้

นี่คือเหตุผลว่าทำไมที่ผ่านมาเราถึงเห็นว่า ธนาคารใช้ระบบศูนย์กลางกันทั้งหมด เพราะว่าปัญหามันน้อยกว่า แต่ Blockchain เป็นวิธีแรกในโลกที่แก้ปัญหานี้ในระบบแบบกระจายได้


Blockchain 

      คือ การให้ทุกคนถือเอกสารชุดเดียวกัน เมื่อมีการอัปเดตก็จะอัปเดตด้วยกัน โดยมั่นใจได้ว่าเอกสารเหล่านั้น เชื่อถือได้แน่นอนไม่มีการปลอมแปลง แล้ว Blockchain แก้ปัญหาของ ระบบการกระจายได้ไง เริ่มจาก 


1. สมุดบัญชีจะมีแค่ เลขบัญชี กับ Owner Key 



Credit Pic: Nuuneol

2. ไม่มีการเก็บจำนวนเงิน มีแต่ข้อมูลการเดินบัญชี หรือ Transaction เช่น

          - John ฝากเงิน 2,000 บาท
          - John โอนเงินให้ Alice 1,500 บาท (John เหลือ 500)
          - Paul โอนเงินให้ John 500 บาท (John เหลือ 1000)

      ดังนั้นถ้าเราเก็บรายการเดินบัญชีตั้งแต่บัญชี John ถูกสร้างขึ้นมาจนถึงปัจจุบัน พออยากรู้ว่าคน ๆ นี้มีเงินอยู่เท่าไหร่ ก็แค่เอารายการทั้งหมดมาบวกลบกัน นอกจากจะรู้ยอดที่ถูกต้องแล้ว เรายังสามารถตรวจสอบย้อนกลับไปที่มาของเงินได้
      ตามที่เคยบอกไปแล้วว่า "ทุกคนถือเอกสารชุดเดียวกัน เมื่อมีการอัปเดตก็จะอัปเดตด้วยกัน" ดังนั้นเอกสารที่ทุกคนถืออยู่จะเรียกว่า Public Ledger หรือ รายการเดินบัญชีสาธารณะ 



Credit Pic: Nuuneol

  แต่ก็ใช่ว่าระบบจะไม่มีปัญหา มันอาจมีปัญหาเกิดขึ้นได้สองอย่าง

1) รู้ได้ยังไงว่า Transaction นั้น ๆ ถูกต้อง?
      ถ้า Alice มีเช็คราคา 2,000 บาทอยู่ใบนึง แต่จะโอนให้ Johan 2,500 บาท

2) Double Spending
      ถ้า Alice มีเงินอยู่ 2,000 บาท แต่จะสั่งซื้อของราคา 2,000 บาททั้งหมด 2 ชิ้นในเวลาเดียวกัน



Credit Pic: Nuuneol


       เราจะเห็นได้ว่าทั้งสองปัญหานี้เกิดจาก Alice หรือ คนส่ง ซึ่งสามารถทำอะไรก็ได้เพราะ ไร้การตรวจสอบใดๆ ด้วยเหตุนี้ในระบบ Blockchain เราจึงต้องมี "ผู้ยืนยันความถูกต้องของ Transaction" 

      ในระบบรวมศูนย์กลางนั้นยังมีผู้ตรวจสอบ ก็คือ ธนาคาร แต่กับระบบแบบกระจายนี้ ผู้ตรวจสอบก็คือหนึ่งใน 6 คนที่ใช้บริการอยู่ ต้องมีอย่างน้อยหนึ่งเป็นผู้ตรวจสอบ และผู้ตรวจสอบเหล่านี้เราจะเรียกว่า Miner 
      ดังนั้น ลักษณะการประกาศ Transaction จะเปลี่ยนไป จากเดิมที่ประกาศแล้วให้ต่างคนต่างเขียนลงไปใน Ledger ของตัวเองเลย กลายเป็นว่าตอนประกาศ Transaction ไป Transaction นั้นๆจะอยู่ในสถานะ "ยังไม่ได้รับการยืนยัน (Unconfirmed) ก่อน และจะยังไม่ถูกบันทึกไว้ใน Ledger ของใครเพราะ Ledger จะมีไว้สำหรับเขียนสิ่งที่ "ได้รับการยืนยันแล้ว" เท่านั้น ซึ่งการตรวจสอบก็ไม่ยากแค่ ตรวจสอบว่า สิ่งที่ทำอยู่นั้น ตรงกับ Ledger ของ miner เช่น John โอนให้ Alice 2000 miner ก็จะตรวจสอบว่า John มียอดถึง 2000 ไหม 
     แต่ถ้าเราไม่มั่นใจว่า Miner ไว้ใจได้รึเปล่า ในกรณีนี้ การมี Miner เพียงคนเดียวนั้นจึงไม่ดีพอ ระบบเลยต้องมี Miner มากกว่า 1 คน และให้คนเหล่านั้น "แข่งกันยืนยัน Transaction"


แข่งกันยืนยัน Transaction

      การแข่งยืนยัน Transaction นั้น เมื่อ Miner ทำการตรวจสอบ Transaction แล้วจะต้องแก้โจทย์ของระบบ Blockchain ซึ่ง ระบบ Blockchain จะตั้งโจทย์พิเศษขึ้นมาให้แก้หนึ่งตัว เป็นโจทย์ที่แก้ไขไม่ได้ด้วยสมการทางคณิตศาสตร์ วิธีเดียวที่จะทำได้คือ "ทำไปเรื่อยๆจนกว่าจะเจอคำตอบ"
(เช่น เอาข้อมูลไปผ่าน hash function แล้วให้ชุดตัวเลขที่ได้มีเลข 00 นำหน้า) 
จะเห็นว่าการยืนยัน Transaction นั้นใช้เวลานานพอสมควรเพราะ Proof of Work นั่นเอง โดยอาจจะใช้เวลาถึง 5-10 นาทีเลยทีเดียว

      ดังนั้นการจะมานั่งยืนยันทีละ Transaction จะเสียเวลา เลยจะใช้วิธียืนยันทีละหลายๆ Transaction พร้อมกันจากนั้นจะ รวม Transaction เข้ากล่อง ๆ เดียวแล้วยืนยันทุก Transaction นั้นพร้อมกัน และกล่องนี้เราเรียกมันว่า Block ต่อมา Miner จะส่ง Block (ใน block ประกอบไปด้วย Transaction หลายๆอัน และ คำตอบของโจทย์ที่เราแก้) ให้กับทุกคน ดังนั้นรายการเดินบัญชีที่เก็บไว้ในมือของแต่ละคนจะไม่ได้อยู่ในรูปแบบง่ายๆที่เรียง Transaction ต่อกันเรื่อยๆอีกต่อไป แต่จะเป็นการเอา Block มาเรียงต่อกันเรื่อยๆแทน  ซึ่งทุก Block ต้องอ้างอิง Block ก่อนหน้า เราจะเห็นได้ว่า จะไม่มีใครแอบเปลี่ยนข้อมลใน block ได้เพราะถ้าเปลี่ยนต้องเปลี่ยน block ก่อนหน้าด้วย



Credit Pic: Nuuneol

ถามว่า miner ได้อะไร 

      ในระบบทั่วไปเราจะให้รางวัล Miner เป็น Transaction fee ครับ ก็คือคนโอนจะต้องรับผิดชอบค่าธรรมเนียมการโอนเพิ่มเติม โดยแล้วแต่เลยว่าจะคิดค่าธรรมเนียมกันยังไง เช่น บังคับไปเลยว่าต้องจ่ายเท่าไหร่จนไปถึงคิดเป็น % จากยอดโอน แล้วเงินเหล่านี้จะถูกสร้างเป็นเช็คอีกใบนึงส่งให้กับ Miner ผู้ที่ยืนยันสำเร็จครับ



Bitcoin (บิทคอยน์) กับ Blockchain (บล็อกเชน) เกี่ยวข้องกันอย่างไร

  •  Blockchain : เทคโนโลยี ด้านความปลอดภัยของข้อมูล 
  •  Bitcoin: สกุลเงินบนโลกดิจิตอล

      จะเห็นได้ว่า Blockchain  ไม่ใช่ Bitcoin และ Bitcoin ก็ไม่ใช่ Blockchain  แต่ Bitcoin มีความต้องการนำ Blockchain มาใช้ เพื่อให้การซื้อขาย มีความปลอดภัย 

ก็ขอจบ post Blockchain คืออะไร เพียงเท่านี้นะครับ ต่อไปจะเป็นเรื่องของ Smart contact บน Blockchain นะครับ ขอบคุณครับ

Code Client Smart Contract auto transfer

ในครั้งนี้เราจะมาทำให้ Smart Contract ของเรา transfer auto กันครับ โดยเริ่มจากส่วนของ Smart contract ของเราก่อน เราได้เพิ่มฟังก์ชั่น ...