เข้าใจ Transaction หน่วยบันทึกข้อมูล บน Ethereum

Trust Tanapruk
Dcen.io
Published in
4 min readMay 6, 2018
Simplified Blockchain

Blockchain เป็นรูปแบบ database แบบหนึ่ง ที่เก็บข้อมูลหลายๆ transaction ไว้ใน block และนำ block มาวาง chain เรียงต่อกัน

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

Ethereum คือ Blockchain ที่รองรับ Smart Contract โดย smart contract คือหนังสือสัญญาที่มี programming logic

เราสามารถคุยกับ smart contract ผ่านคำสั่งที่ระบุในสัญญา

เช่น smart contract ที่ใช้แลก ethereum เป็น ICO ให้เราโอน ethereum พร้อมคำสั่ง exchangeEtherToICOToken() ไปที่ contract address ตัว contract จะส่ง ICO Token กลับให้เรา

Transaction

ในโลกของ Ethereum เราบันทึกข้อมูลผ่านการทำ Transaction เพียงทางเดียว

Transaction ในโลกความเป็นจริง จะเกิดขึ้นตอนเราทำธุรกรรม ผ่านธนาคาร อาทิ โอนเงิน ถอนเงิน หรือ ฝากเงิน

กลับมาที่ Ethereum เราเรียก สิ่งเหล่านี้ว่า Transaction หมด

  • การโอน Ethereum
  • การสร้าง Smart Contract
  • การสั่งซื้อเหรียญ ERC20 Token

Transaction หลังจากถูกยืนยัน (Verify) และบันทึกลงใน Block จะไม่สามารถแก้ไขได้แล้ว

Gas

ในโลก blockchain ที่ไม่มีธนาคารเป็นศูนย์กลาง คนยืนยัน Transaction ก็เป็นเหล่า miner ที่เปิดการ์ดจอทิ้งไว้

Miner ไม่ได้ใจดี เค้าต้องการค่าไฟที่เค้าเปิดการ์ดจอทิ้งไว้ด้วย เราต้องจ่ายค่าต๋งในรูปแบบของ gas

ค่า gas ก็ไม่ตายตัว แกว่งขึ้นลงตามปริมาณ Transaction ในตลาดตอนนั้นด้วย

Miner เหล่านี้ โลภ ไม่สนใจว่าเรามาก่อน หรือหลัง สนแค่ว่าเราจ่ายเยอะกว่าคนอื่นรึเปล่า ถ้าเงินหนา จ่าย gas แพงๆ Transaction ของเราก็ได้รับการยืนยัน และไปอยู่บน Ethereum Network

(ถึง Miner อยากจะใจดี ยืนยันให้คนมาก่อน ก็ทำไม่ได้ เพราะระบบถูกออกแบบมาแบบนี้)

ดังนั้น เมื่อเราทำ Transaction เราต้องระบุปริมาณ gas สูงสุดที่เรายอมจ่าย และราคา gas ในรูปแบบของ gasPrice

ใช้คำว่า gas สูงสุดที่ยอมจ่าย เพราะ miner อาจไม่ได้ใช้ gas เราจนหมดเสมอไป

เช่น

gas=10000

gasPrice=2gwei

แปลว่า เราเสียค่า gas ได้สูงสุด 20000 gwei (gwei เป็นหน่วยย่อยของ ether เหมือน สตางค์ ของบาท)

gas และ gasPrice ระดับไหนที่เหมาะสม ก็ขึ้นอยู่กับ traffic ในตอนนั้น เช็คได้จาก https://ethgasstation.info/

ประเภทของ Transaction

Transaction นั้นเป็นการโอนเงิน/การสร้าง smart contract ขึ้นอยู่กับรูปแบบการส่งค่าไป ดังนี้

Transaction โอน Ethereum

ระบุคนโอน, คนรับ, ปริมาณ พร้อมค่าโอนในรูปแบบ gas

from: eth address คนโอนเงิน
to: eth address คนรับเงิน
value: ปริมาณ eth ที่ส่งไป
gas: ปริมาณ gas สูงสุดที่ยอมจ่าย
gasPrice: ราคา gas ที่เราตั้งไว้ (หน่วยเป็น wei)
nonce: ค่า integer เอาไว้ refer ตอนยิงซ้ำกรณีรอยืนยัน transaction นาน

เช่น

{
from: "0x3f3783be816135bdc8210e998f9409559258295b",
to: "0x413e8682a1ff2f31da606cca7ca266c2fc71d959",
value: 10000,
gas: 90000,
gasPrice: 20000000000,
nonce: 1
}

Transaction สร้าง Smart Contract

ระบุคนโอน, input เป็น smart contract ที่ compile แล้ว พร้อมกับค่า gas

* ไม่ต้องระบุปลายทาง และมูลค่า Ether

from: eth address คนสร้าง
to: 0x0
value: 0x0
gas: ปริมาณ gas สูงสุดที่ยอมจ่าย
gasPrice: ราคา gas ที่เราตั้งไว้
input: compiled smart contract
nonce: ค่า integer เอาไว้ refer ตอนยิงซ้ำกรณีรอยืนยัน transaction นาน

เช่น

{
from: "0x3f3783be816135bdc8210e998f9409559258295b",
to: "0x0",
gas: 255620,
gasPrice: 1,
nonce: 2,
input: "0x608060405234801561001057600080fd5b506102fa806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806322faf03a146100515780633c1b81a5146100c4575b600080fd5b34801561005d57600080fd5b506100c2600480360381019080803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192908035906020019092919050505061015b565b005b3480156100d057600080fd5b506100d961017d565b6040518080602001838152602001828103825284818151815260200191508051906020019080838360005b8381101561011f578082015181840152602081019050610104565b50505050905090810190601f16801561014c5780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b8160009080519060200190610171929190610229565b50806001819055505050565b6060600080600154818054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561021a5780601f106101ef5761010080835404028352916020019161021a565b820191906000526020600020905b8154815290600101906020018083116101fd57829003601f168201915b50505050509150915091509091565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061026a57805160ff1916838001178555610298565b82800160010185558215610298579182015b8281111561029757825182559160200191906001019061027c565b5b5090506102a591906102a9565b5090565b6102cb91905b808211156102c75760008160009055506001016102af565b5090565b905600a165627a7a72305820ff9c194b6a633e1439e4a686e4ee48387b8c278e9aa4e3e1d59af986c8158dbe0029"
}

compile smart contract ทำได้หลายวิธี ทำได้ผ่าน remix IDE, solc ของ npm หรือ truffle framework

Transaction เรียกคำสั่งใน Smart Contract

เมื่อดูโค้ด smart contract ก่อน compile มันคือ class นึงเท่านั้น

pragma solidity ^0.4.18;contract Coursetro {  string fName;
uint age;
function setInstructor(string _fName, uint _age) public {
fName = _fName;
age = _age;
}
function getInstructor() public constant returns (string, uint) {
return (fName, age);
}
}
ข้อมูลจาก
https://coursetro.com/posts/code/99/Interacting-with-a-Smart-Contract-through-Web3.js-(Tutorial)
  • ระบุ คนโอน
  • ระบุปลายทางเป็น smart contract address
  • มูลค่า ขึ้นอยู่กับ method
  • gas เป็นค่าโอน
  • input อันนี้คือ method ที่เราจะเรียกใช้งาน
from: eth address คนสั่ง
to: eth address smart contract
value: มีค่าหรือไม่มีก็ได้ ขึ้นอยู่กับ method
gas: ปริมาณ gas สูงสุดที่ยอมจ่าย
gasPrice: ราคา gas ที่เราตั้งไว้
input: method ที่เรียกพร้อม parameter (ในรูปแบบ encoded)
nonce: ค่า integer เอาไว้ refer ตอนยิงซ้ำกรณีรอยืนยัน transaction นาน

เช่น

{
from: "0x3f3783be816135bdc8210e998f9409559258295b",
to: "0x08adca2c2d03aef61790f8db24bef0eee4a7f1fb",
gas: 90000,
gasPrice: 1,
nonce: 4,
input: "0x22faf03a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001900000000000000000000000000000000000000000000000000000000000000064e6578747a790000000000000000000000000000000000000000000000000000"
}

ส่วน input ที่ encode ไว้ คลายออกมาได้ดังนี้

{
name: "setInstructor",
params: [
{name: "_fName", value: "Nextzy", type: "string"},
{name: "_age", value: "25", type: "uint256"}
]
}

decode โดยใช้ library ตัวนี้ https://github.com/ConsenSys/abi-decoder

จะเห็นได้ว่า input ที่ decode ออกมา เป็น method จะตรงกับใน contract ของเราเลย

หาก Transaction ที่เราส่งไปยังไม่ได้รับการยืนยัน คงเป็นเพราะเราใส่ gas และ gasPrice น้อยไป เราสามารถส่งค่าเดิม ด้วย nonce เดิม เพิ่มเติมเป็น gas หรือ gasPrice ที่เพิ่มมากขึ้นได้ด้วย

ข้อสังเกต

Transaction แต่ละอัน มี from และ toเสมอ ข้อมูลที่บันทึก ต้องเป็นการปฏิสัมพันธ์จากสองฝ่าย อันนี้เป็นจุดต่างระหว่าง blockchain และ database ประเภทอื่น ที่ไม่ถูกจำกัดแค่การปฏิสัมพันธ์ระหว่าง 2 ฝ่าย

Smart Contract ก็เป็นแค่ field input ใน Transaction ที่ใส่ค่า to และ valueเป็น 0x0 เท่านั้น

ยิ่ง Smart Contract ซับซ้อน input จะมีปริมาณตัวหนังสือเยอะ แน่นอนว่าส่งผลต่อค่า gas ด้วย

เราไม่สามารถเปลี่ยนแปลง Smart Contract ที่ถูกยืนยันไปแล้วได้ ทำได้เพียงส่ง Smart Contract ใหม่ (Transaction ใหม่) ขึ้นไป และเราต้องบอก user ของเราให้อิงใช้ Smart Contract ตัวใหม่แทน

1 Block มีได้หลาย Transactions

Simplified Blockchain

จากรูปข้างบน ขอยกมาอีกรอบ

Transaction ที่มีหลายรูปแบบ นั้นจะถูกแพครวมโดย miner ใส่ใน Block และไปถักเชื่อมกับ Block ก่อนหน้า ตัวอย่างข้อมูลของ block มีดังนี้


{
"number": 1,
"hash": "0xcf470f494d508d09be84cb5ddcfec935eecc46095d67b34693cbecfa9ded7b66",
"parentHash": "0x116eb9eb1f9c54ace9977d5d0b725f3e08185578134614fe2b5a3630c6d1e116",
"mixHash": "0x1010101010101010101010101010101010101010101010101010101010101010",
"nonce": "0x0000000000000000",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot": "0x470c50d5ac03f67d58da846f3c607f4082e6e06a5b05f694c684364009296cd8",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"miner": "0x0000000000000000000000000000000000000000",
"difficulty": "0",
"totalDifficulty": "0",
"extraData": "0x00",
"size": 1000,
"gasLimit": 6721975,
"gasUsed": 255620,
"timestamp": 1525595171,
"transactions": [
"0xdbef03bc672111b7261a3cc9fa42ba7df3045f61b5e8a6e5f4c2042fb3f1e23c"
],
"uncles": []
}

มันเยอะมาก ผมแค่อยากให้ดู

  • transactions: [] มันเป็น array แปลว่ามันมีได้หลาย transactions
  • parentHash อันนี้คือ hash ของ Block ก่อนหน้าที่ chain ต่อมา
  • hash อันนี้คือ hash ตัวมันเอง เอาไว้ให้ Block ถัดไป refer ถึง

Web3 เครื่องมือสำหรับ Developer

ข้อมูลที่บันทึกบน ethereum network ไม่ได้อยู่ในรูป JSON สวยงามแบบนี้ มันผ่านการ hash การ encode หรือ encrypt ให้อ่านยาก หากจะไล่ decode และ decrypt และ filter หาข้อมูลที่ต้องการ หรือ encode/encrypt ข้อมูลก่อนส่งไปบน ethereum network คงเหนื่อยแย่ แนะนำให้ใช้ Web3 ครอบเรียกใช้งาน เราจะได้ JSON Object มาติดต่อคุยกับ Front-end ได้อย่างสบายแฮ

ตัวอย่าง เรียกใช้ web3 จาก Chrome Developer Tools

ลิ้งค์ Web3 กดข้างบนได้เลย

หวังว่าทุกคนคงเข้าใจประเภทของ Transaction ใน Ethereum มากขึ้น ซึ่งผมยกตัวอย่าง การโอน Ethereum การสร้าง Smart Contract และ การสั่ง method ใน Smart Contract โดยแต่ละประเภทต่างกันที่ข้อมูลการส่ง

นอกจากนี้ Transaction นั้นเป็นหน่วยย่อยๆ ของ Block เท่านั้น และ Block เชื่อมต่อกับ Block ผ่าน field ที่ชื่อ parentHash

สุดท้าย Web3 เป็นทางออกสำหรับคนที่ต้องการเขียน Front-end เชื่อมกับ Ethereum Blockchain

ชอบใจก็ฝากกด like page dcen.io ด้วยครับ

--

--