BTC
ETH
HTX
SOL
BNB
ดูตลาด
简中
繁中
English
日本語
한국어
ภาษาไทย
Tiếng Việt

การแยกโครงสร้างสัญญาอัจฉริยะ

猎豹区块链安全
特邀专栏作者
2018-12-03 11:51
บทความนี้มีประมาณ 4852 คำ การอ่านทั้งหมดใช้เวลาประมาณ 7 นาที
ค้นพบความลึกลับของสัญญาอัจฉริยะกับผู้เขียน
สรุปโดย AI
ขยาย
ค้นพบความลึกลับของสัญญาอัจฉริยะกับผู้เขียน

ตอนที่ 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เรียนรู้เพิ่มเติม


ยินดีต้อนรับเข้าร่วมชุมชนทางการของ Odaily
กลุ่มสมาชิก
https://t.me/Odaily_News
กลุ่มสนทนา
https://t.me/Odaily_CryptoPunk
บัญชีทางการ
https://twitter.com/OdailyChina
กลุ่มสนทนา
https://t.me/Odaily_CryptoPunk
ค้นหา
สารบัญบทความ
空头猎人
คลังบทความของผู้เขียน
猎豹区块链安全
ดาวน์โหลดแอพ Odaily พลาเน็ตเดลี่
ให้คนบางกลุ่มเข้าใจ Web3.0 ก่อน
IOS
Android