การแยกโครงสร้างสัญญาอัจฉริยะ
ตอนที่ 1 คำนำ

ลองนึกภาพว่าคุณกำลังขับรถมัสแตงมัคปี 1969 อย่างรวดเร็วบนถนนทางตะวันตกของสหรัฐอเมริกา แสงแดดสาดส่องบนขอบล้อเคลือบทองอันงดงาม ถนนทั้งสายมีเพียงคุณและทะเลทราย และขอบฟ้าที่ไม่มีที่สิ้นสุดเป็นพยานถึงการไล่ตามคุณและ พระอาทิตย์อัสดง..... . .
ในขณะที่รู้สึกผ่อนคลายและมีความสุข จู่ๆ ก็มีเสียงดังขึ้น และม้าเร็ว 335 แรงม้าของคุณก็ถูกควันสีขาวกลืนหายไป และกลายเป็นหัวรถจักรไอน้ำทันที คุณจึงถูกบังคับให้หยุดอยู่ข้างถนน
คุณกำลังจะเห็นว่ามีอะไรผิดปกติ แต่เมื่อคุณยกฝากระโปรงออก คุณจะไม่สามารถอ่านได้ คุณไม่รู้ว่าเครื่องบ้าๆนั่นทำงานยังไง คุณจึงหยิบโทรศัพท์ขึ้นมาเพื่อโทรขอความช่วยเหลือ แต่กลับพบว่าไม่มีสัญญาณอยู่ใกล้ๆ...


สถานการณ์ที่อธิบายไว้ข้างต้นคล้ายกับการพัฒนา DApp ที่คุณกำลังทำอยู่หรือไม่? ในกระบวนการพัฒนา Dapp ในการเปรียบเทียบ รถยนต์หรูหราคือสัญญาที่ชาญฉลาดของคุณ ส่วนขอบล้อและตำแหน่งที่ปรับเปลี่ยนคือรายละเอียดเล็กๆ น้อยๆ ที่ได้รับการคิดมาเป็นอย่างดี คุณต้องค้นหาคำตอบในสัญญาอัจฉริยะ EVM bytecode ในกรณีส่วนใหญ่คุณไม่รู้ว่าเกิดอะไรขึ้น
หากคุณเป็นนักพัฒนา Dapp และเคยพบกับสถานการณ์ที่น่าอับอายข้างต้น คุณก็ไม่ต้องกังวลอีกต่อไป!
เนื่องจาก จุดประสงค์ของบทความชุดนี้คือการแยกโครงสร้างสัญญา Solidity อย่างง่าย ดูที่รหัสไบต์ และแยกย่อยออกเป็นโครงสร้างที่จดจำได้ ลงไปจนถึงระดับต่ำสุด เราจะเปิดฝากระโปรงรถสปอร์ตของ Solidity ในตอนท้ายของซีรีส์นี้ คุณควรรู้สึกสบายใจในการดูหรือดีบัก EVM bytecode ซีรี่ส์นี้มุ่งเน้นไปที่การทำให้โค้ด EVM bytecode ที่สร้างขึ้นโดยคอมไพเลอร์ Solidity นั้นชัดเจนขึ้น ซึ่งง่ายกว่าที่เห็นมาก
ต่อไปนี้คือรหัสสัญญาอัจฉริยะที่เราจะใช้เมื่อแยกโครงสร้าง:
pragma solidity ^0.4.24;
contract BasicToken {
uint256 totalSupply_;
mapping(address => uint256) balances;
constructor(uint256 _initialSupply) public {
totalSupply_ = _initialSupply;
balances[msg.sender] = _initialSupply;
}
function totalSupply() public view returns (uint256) {
return totalSupply_;
}
function transfer(address _to, uint256 _value) public returns (bool) {
require(_to != address(0));
require(_value <= balances[msg.sender]);
balances[msg.sender] = balances[msg.sender] - _value;
balances[_to] = balances[_to] + _value;
return true;
}
function balanceOf(address _owner) public view returns (uint256) {
return balances[_owner];
}
}
ชื่อระดับแรก
รวบรวมสัญญา
ในการทำสัญญา เราจะใช้ Remix (ที่อยู่: https://remix.ethereum.org)
เมื่อคุณเปิดคอมไพเลอร์ Remix ให้คลิกปุ่ม + ที่มุมซ้ายบนเหนือพื้นที่เบราว์เซอร์ไฟล์เพื่อสร้างสัญญาอัจฉริยะใหม่ ตั้งชื่อไฟล์เป็น BasicToken.sol เมื่อสร้างแล้ว ให้วางโค้ดด้านบนลงในตัวแก้ไข
ทางด้านขวา ไปที่ตัวเลือกสำหรับ "การตั้งค่า" และตรวจสอบให้แน่ใจว่าได้เลือก "เปิดใช้งานโหมดส่วนตัว" โปรดทราบว่าเวอร์ชันคอมไพเลอร์ Solidity ที่เลือกคือ
“ version:0.4.24 +commit.e67f0147.Emscripten.clang ”。
รายละเอียดทั้งสองนี้มีความสำคัญมาก มิฉะนั้น คุณจะไม่สามารถดูรหัสไบต์ที่กล่าวถึงในบทความนี้ได้
ถัดไป คุณสามารถไปที่ตัวเลือกการคอมไพล์และคลิกปุ่มรายละเอียด จากนั้นคุณจะเห็นป๊อปอัปที่มีทุกอย่างที่สร้างโดยคอมไพเลอร์ Solidity ซึ่งหนึ่งในนั้นคือวัตถุ JSON ที่เรียกว่า BYTECODE ซึ่งมีคุณสมบัติ "วัตถุ" เป็นรหัสสัญญาที่รวบรวมและรหัสของมันมีดังนี้:
608060405234801561001057600080fd5b5060405160208061021783398101604090815290516000818155338152600160205291909120556101d1806100466000396000f3006080604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166318160ddd811461005b57806370a0823114610082578063a9059cbb146100b0575b600080fd5b34801561006757600080fd5b506100706100f5565b60408051918252519081900360200190f35b34801561008e57600080fd5b5061007073ffffffffffffffffffffffffffffffffffffffff600435166100fb565b3480156100bc57600080fd5b506100e173ffffffffffffffffffffffffffffffffffffffff60043516602435610123565b604080519115158252519081900360200190f35b60005490565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604090205490565b600073ffffffffffffffffffffffffffffffffffffffff8316151561014757600080fd5b3360009081526001602052604090205482111561016357600080fd5b503360009081526001602081905260408083208054859003905573ffffffffffffffffffffffffffffffffffffffff85168352909120805483019055929150505600a165627a7a72305820a5d999f4459642872a29be93a490575d345e40fc91a7cccb2cf29c88bcdaf3be0029
ชื่อระดับแรก
ปรับใช้สัญญา
จากนั้นไปที่ส่วน Run ใน Remix ก่อนอื่น ตรวจสอบให้แน่ใจว่าคุณใช้ Javascript VM นี่เป็นเครือข่าย Javascript EVM + ที่ฝังอยู่ซึ่งเป็นพื้นที่ฝึกอบรม Ethereum ในอุดมคติ ตรวจสอบให้แน่ใจว่าได้เลือก BasicToken ใน ComboBox และป้อนหมายเลข 10,000 ในช่องอินพุต Deploy จากนั้นคลิกปุ่ม "ปรับใช้" เพื่อปรับใช้ สิ่งนี้ปรับใช้อินสแตนซ์ของสัญญาอัจฉริยะ BasicToken ที่เราสร้างขึ้น โดยมีการจัดหาโทเค็นเริ่มต้น 10,000 รายการที่เป็นของบัญชีที่เลือกในปัจจุบันที่ด้านบนสุดของบัญชี ComboBox ซึ่งเก็บการจัดหาโทเค็นทั้งหมดที่เราตั้งไว้
ใน "สัญญาที่ปรับใช้" ของแท็บ "เรียกใช้" คุณจะเห็นสัญญาอัจฉริยะที่ปรับใช้ ซึ่งมีสามฟิลด์สำหรับโต้ตอบกับสัญญา: การโอนย้าย ยอดคงเหลือ และยอดรวมซัพพลาย ที่นี่เราสามารถโต้ตอบกับอินสแตนซ์สัญญาอัจฉริยะที่เราเพิ่งปรับใช้
แต่ก่อนหน้านั้น มาดูกันว่า "ปรับใช้" ของสัญญาหมายถึงอะไร:
ในพื้นที่คอนโซลที่ด้านล่างของหน้า คุณจะเห็นบันทึก "การสร้าง BasicToken ที่รอดำเนินการ ..." ตามด้วยรายการธุรกรรมที่มีฟิลด์ต่างๆ: จาก ถึง ค่า ข้อมูล บันทึก และแฮช คลิกที่รายการนี้เพื่อขยายข้อมูลธุรกรรม และคุณควรเห็นวันที่ของธุรกรรม ข้อมูลเข้า และรหัสไบต์ที่เรากล่าวถึงข้างต้น ดังนั้น สร้างตัวอย่างสัญญาอัจฉริยะ ซึ่งจะมีที่อยู่และรหัสของมันเอง
ชื่อระดับแรก
แยก bytecode
ตรงกลางคอนโซล ทางขวาของช่องธุรกรรม จะมีปุ่ม "debug" คลิกปุ่มนี้และคุณจะเปิดใช้งานตัวเลือก Debugger ในพื้นที่ด้านขวาของ Remix เราสามารถดูส่วนคำแนะนำด้วยกัน หากเลื่อนลง จะปรากฏสิ่งต่อไปนี้:
000 PUSH1 80
002 PUSH1 40
004 MSTORE
005 CALLVALUE
006 DUP1
007 ISZERO
008 PUSH2 0010
011 JUMPI
012 PUSH1 00
014 DUP1
015 REVERT
016 JUMPDEST
017 POP
018 PUSH1 40
020 MLOAD
021 PUSH1 20
023 DUP1
024 PUSH2 0217
027 DUP4
028 CODECOPY
029 DUP2
030 ADD
031 PUSH1 40
033 SWAP1
034 DUP2
035 MSTORE
036 SWAP1
037 MLOAD
038 PUSH1 00
040 DUP2
041 DUP2
042 SSTORE
043 CALLER
044 DUP2
045 MSTORE
046 PUSH1 01
048 PUSH1 20
050 MSTORE
051 SWAP2
...(ตัวย่อ)
เพื่อให้แน่ใจว่าคุณไม่ได้ผิดพลาด ให้เปรียบเทียบสิ่งที่คุณเห็นในคอมไพเลอร์ Remix ที่คุณกำลังใช้งานอยู่ข้างต้น
นี่คือรหัส bytecode ที่ถอดแยกชิ้นส่วนของสัญญา หากคุณสแกนรหัสไบต์ดิบแบบไบต์ต่อไบต์ (ครั้งละสองอักขระ) EVM จะจดจำรหัส opcode เฉพาะที่เกี่ยวข้องกับการดำเนินการเฉพาะ ตัวอย่างเช่น:
0x60 => PUSH
0x01 => ADD
0x02 => MUL
0x00 => STOP
...
ชื่อระดับแรก
Opcode
ก่อนที่จะเริ่มแยกโครงสร้างรหัสสัญญาอัจฉริยะ คุณจะต้องมีชุดเครื่องมือพื้นฐานเพื่อทำความเข้าใจ opcode เดียว เช่น opcode ของ PUSH, ADD, SWAP, DUP เป็นต้น ในตอนท้าย การดำเนินการแต่ละอย่างสามารถเข้าถึงได้จากสแต็กของ EVM เท่านั้น หน่วยความจำหรือเป็นของ ผลักรายการหรือใช้รายการจากที่จัดเก็บของสัญญา
หากต้องการดู opcodes ที่มีอยู่ทั้งหมดที่ EVM สามารถจัดการได้ คุณสามารถตรวจสอบ Pyethereum ซึ่งจะแสดงรายการของ opcodes เพื่อทำความเข้าใจวิธีการทำงานของ opcode เอกสารประกอบอย่างเป็นทางการของ Solidity ก็เป็นข้อมูลอ้างอิงที่ดีเช่นกัน แม้ว่าจะไม่ใช่การโต้ตอบแบบหนึ่งต่อหนึ่งกับ opcodes แบบดิบ แต่ก็ใกล้เคียงกัน (จริง ๆ แล้วมันคือ Yul ซึ่งเป็นภาษากลางระหว่าง Solidity และ EVM bytecode) หากคุณสามารถอ่านเอกสารทางเทคนิคได้ คุณก็สามารถอ่าน Ethereum Yellow Paper ได้ อันที่จริง เนื้อหาข้างต้นทั้งหมดจะเดือดดาล
แม้ว่าจะมีเอกสารมากมายที่แนะนำให้ทุกคน แต่ก็ไม่มีประโยชน์ที่จะอ่านแหล่งข้อมูลเหล่านี้ตั้งแต่หน้าหนึ่งไปอีกหน้าหนึ่ง ขอเพียงจำไว้ว่ามีเอกสารดังกล่าว และเราจะใช้เอกสารเหล่านั้นเมื่อจำเป็น
คำแนะนำ
แต่ละบรรทัดในการแยกชิ้นส่วนด้านบนคือคำสั่งการดำเนินการที่ดำเนินการโดย EVM และแต่ละคำสั่งจะมีรหัส opcode ตัวอย่างเช่น ให้เรานำหนึ่งในคำสั่งเหล่านี้ คำสั่ง 88 ซึ่งจะกดหมายเลข 4 ลงบนสแต็ก ตัวแยกส่วนนี้อธิบายสิ่งต่อไปนี้:
88 PUSH1 0x04
| | |
| | Hex value for push.
| Opcode
Instruction number
กลยุทธ์
กลยุทธ์
งานใดๆ ที่ดูเหมือนเป็นไปไม่ได้ในตอนเริ่มต้นสามารถแยกย่อยออกเป็นงานที่แก้ไขได้ผ่านการรื้ออย่างต่อเนื่อง และปัญหาที่เราพบก็ไม่มีข้อยกเว้น เมื่อเผชิญกับปัญหานี้ กลยุทธ์ที่ฉันนำมาใช้คือ "แบ่งและพิชิต"
เราสามารถพยายามหาจุดแยกย่อยของโค้ดที่ถอดประกอบแล้วค่อยๆ แตกออกจนแตกเป็นชิ้นเล็กๆ ซึ่งเราจะทำทีละขั้นตอนในดีบักเกอร์ของ Remix
ในภาพด้านล่าง เราจะเห็นการแยกส่วนแรกของโค้ดที่แยกส่วน (ซึ่งฉันจะวิเคราะห์อย่างละเอียดในโพสต์ถัดไป)

Cheetah blockchain security ใช้เทคโนโลยีของ Kingsoft Internet Security รวมกับปัญญาประดิษฐ์, nlp และเทคโนโลยีอื่นๆ เพื่อให้ผู้ใช้ blockchain ได้รับบริการด้านความปลอดภัยทางระบบนิเวศ เช่น การตรวจสอบสัญญาและการวิเคราะห์ความรู้สึก
*บทความนี้เผยแพร่ครั้งแรกบนสื่อโดย Alejandro Santander แปลและเรียบเรียงโดย Cheetah Blockchain*
Cheetah blockchain security ใช้เทคโนโลยีของ Kingsoft Internet Security รวมกับปัญญาประดิษฐ์, nlp และเทคโนโลยีอื่นๆ เพื่อให้ผู้ใช้ blockchain ได้รับบริการด้านความปลอดภัยทางระบบนิเวศ เช่น การตรวจสอบสัญญาและการวิเคราะห์ความรู้สึก
คุณสามารถเยี่ยมชมเว็บไซต์ทางการของ Ratingtokenเรียนรู้เพิ่มเติม



