เข้าใจ Transaction หน่วยบันทึกข้อมูล บน Ethereum
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
จากรูปข้างบน ขอยกมาอีกรอบ
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 กดข้างบนได้เลย
หวังว่าทุกคนคงเข้าใจประเภทของ Transaction ใน Ethereum มากขึ้น ซึ่งผมยกตัวอย่าง การโอน Ethereum การสร้าง Smart Contract และ การสั่ง method ใน Smart Contract โดยแต่ละประเภทต่างกันที่ข้อมูลการส่ง
นอกจากนี้ Transaction นั้นเป็นหน่วยย่อยๆ ของ Block เท่านั้น และ Block เชื่อมต่อกับ Block ผ่าน field ที่ชื่อ parentHash
สุดท้าย Web3 เป็นทางออกสำหรับคนที่ต้องการเขียน Front-end เชื่อมกับ Ethereum Blockchain
ชอบใจก็ฝากกด like page dcen.io ด้วยครับ