1. EVM or WASM?
ด้วยความนิยมของ Ethereum เมื่อเราพูดถึงสัญญาอัจฉริยะ เรามักจะใช้ภาษา Solidity เพื่อพัฒนาสัญญาอัจฉริยะตาม EVM เป็นค่าเริ่มต้น อย่างไรก็ตาม เนื่องจากข้อบกพร่องของเวลาบล็อกที่ช้าของ Ethereum และค่าธรรมเนียมการทำธุรกรรมที่สูง จึงมีการเปิดตัวเทคโนโลยีการเพิ่มประสิทธิภาพและเชนสาธารณะใหม่มากขึ้นเรื่อยๆ WASM เป็นหนึ่งในเทคโนโลยีตัวแทน ในฐานะไวยากรณ์ไบนารีใหม่ล่าสุด WASM มีข้อดีหลายประการ เช่น ขนาดคำสั่งขนาดเล็ก ความเร็วในการดำเนินการที่รวดเร็ว และความปลอดภัยของหน่วยความจำ ดังนั้นสัญญาอัจฉริยะที่ทำงานบน WASM สามารถลดทรัพยากรบล็อกเชนที่ถูกครอบครองได้อย่างมาก ปรับปรุงความเร็วและประสิทธิภาพของการสร้างบล็อกอย่างมีนัยสำคัญ และทำงานได้เสถียรมากขึ้น ทำให้ผู้ใช้ได้รับประสบการณ์ที่ดีขึ้น WASM รองรับภาษาการพัฒนาส่วนหน้าที่แตกต่างกันมากมาย รวมถึง Rust, C, C++, TypeScript, AssemblyScript เป็นต้น เมื่อพิจารณาถึงการปรับตัวและห่วงโซ่เครื่องมือและความปลอดภัยของภาษาเองแล้ว Rust เป็นหนึ่งในตัวเลือกที่ดีมาก
2. ทางเลือกของ BlockSec
ภารกิจของ BlockSec คือการทำให้ระบบนิเวศของ Defi ทั้งหมดมีความปลอดภัยมากขึ้น ดังนั้น นอกเหนือจากการให้บริการตรวจสอบแล้ว เรายังหวังว่าจะให้การสนับสนุนชุมชนมากขึ้นจากมุมมองของการพัฒนาความปลอดภัย จากข้อดีหลายประการของ Rust และ WASM เราจึงตัดสินใจนำเสนอชุดการแบ่งปันสำหรับกลุ่มเทคโนโลยีนี้โดยเฉพาะ และหวังว่าคุณจะสนใจเราต่อไป เราได้ตรวจสอบโครงการเครือข่ายสาธารณะที่ได้รับความนิยมมากขึ้นในปัจจุบัน และเครือข่ายสาธารณะ NEAR ก็ใช้เทคโนโลยีชุดเดียวกัน NEAR รองรับสัญญา WASM โดยกำเนิด และรองรับภาษา Rust และ AssemblyScript เพื่อพัฒนาสัญญาอัจฉริยะ ดังนั้น เราจะเริ่มการแบ่งปันและการสนทนาของเราตามห่วงโซ่สาธารณะ NEAR
3. พัฒนาสัญญาอัจฉริยะกับ Rust
ภาษา Rust พัฒนาโดย Mozilla หลังจากคอมไพล์โปรแกรมแล้วโปรแกรมจะทำงานด้วยความเร็วที่น่าทึ่งมีอัตราการใช้หน่วยความจำที่สูงมากและรองรับรูปแบบการเขียนโปรแกรมเชิงฟังก์ชันและเชิงวัตถุ บางทีนักเรียนหลายคนยังค่อนข้างใหม่สำหรับภาษา Rust แต่ไม่ต้องกังวล เริ่มจากบล็อกนี้ BlockSec จะทำงานร่วมกับคุณเพื่อขจัดหมอกของสนิม เพื่อให้ทุกคนสามารถใช้ Rust เพื่อพัฒนาสัญญาอัจฉริยะที่มีประสิทธิภาพและปลอดภัย
4. การกำหนดค่าสภาพแวดล้อม
4.1 การใช้งาน IDE
เมื่อเรากำลังเรียนรู้ที่จะใช้ภาษาใหม่เพื่อพัฒนา จำเป็นต้องเลือก IDE ที่ยอดเยี่ยม ที่นี่ BlockSec ขอแนะนำให้คุณใช้ Visual Studio Code กับปลั๊กอิน Rust (เช่น Rust-analyzer) ซึ่งเกือบจะตอบสนองความต้องการประจำวันของคุณได้ หากคุณมีเงื่อนไข คุณสามารถลองใช้ปลั๊กอิน Jetbrains Clion + Rust นักเรียนสามารถใช้งานได้ฟรี
4.2 ติดตั้ง Rust toolchain
เมื่อเรามี IDE ที่ยอดเยี่ยม เราก็จำเป็นต้องดาวน์โหลดและติดตั้ง Rust โดยธรรมชาติ Rust มีวิธีการติดตั้งที่ง่ายและสะดวกมาก ในระบบ Linux เราเพียงเรียกใช้โค้ดบรรทัดต่อไปนี้เพื่อดาวน์โหลดและติดตั้ง Rust โดยอัตโนมัติ
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
หลังจากการติดตั้งเสร็จสิ้น เราสามารถตรวจสอบว่าการติดตั้งสำเร็จหรือไม่โดยเรียกใช้ $rustup --version สนิมทำหน้าที่เป็นตัวจัดการสำหรับ Rust toolchains โดยจัดเตรียมวิธีการสำหรับการติดตั้ง การลบ การอัปเดต การเลือก และการจัดการ toolchains เหล่านี้และส่วนประกอบที่เกี่ยวข้อง จากนั้น เราจำเป็นต้องเพิ่มเป้าหมาย WASM (WebAssembly) ไปยัง toolchain โดยดำเนินการคำสั่งต่อไปนี้:
$ rustup target add wasm32-unknown-unknown
5. สัญญาสนิมแรก
ในที่สุดเราก็มาถึงจุด ที่นี่เราจะพาคุณไปทำความเข้าใจและเชี่ยวชาญวิธีใช้ Rust ในการเขียนสัญญาอัจฉริยะโดยการวิเคราะห์โครงการสัญญาอัจฉริยะแต่ละโครงการอย่างลึกซึ้ง หากคุณสนใจในภาษา Rust มีแบบฝึกหัดมากมายบนอินเทอร์เน็ต คุณสามารถดูได้
5.1 ผู้จัดการแพ็คเกจของ Rust
ด้วยการสนับสนุนจากชุมชนโอเพ่นซอร์สทั้งหมดสำหรับ Rust ไลบรารีของบุคคลที่สามจำนวนมากจึงปรากฏขึ้นในสตรีมที่ไม่มีที่สิ้นสุด เพื่อให้จัดการไลบรารีเหล่านี้ได้ดียิ่งขึ้น Cargo จึงถือกำเนิดขึ้น คำสั่งการติดตั้งข้างต้นจะช่วยให้คุณติดตั้ง Cargo ในเวลาเดียวกัน Cargo ช่วยนักพัฒนาในการทำงานต่างๆ เช่น การสร้างโครงการ Rust ใหม่ ดาวน์โหลดและคอมไพล์ไลบรารีที่โครงการ Rust พึ่งพา และสร้างโครงการทั้งหมดโดยสมบูรณ์
5.2 สร้างโครงการสัญญาสนิมแรก
เมื่อเราพร้อมสำหรับสภาพแวดล้อมการพัฒนา ก่อนอื่นให้ใช้ Cargo เพื่อสร้างโครงการสัญญาใหม่และตั้งชื่อว่า StatusMessage
$ cargo init --lib StatusMessage
โครงสร้างไดเร็กทอรีของโครงการมีดังนี้:
StatusMessage/
├── Cargo.toml
└── src
└── lib.rs
5.3 ประกาศสัญญา
สัญญาอัจฉริยะ (Smart Contract) มักจะต้องรักษาชุดข้อมูลสถานะสัญญา โค้ดต่อไปนี้เขียนใน src/lib.rs ประกาศสัญญาอย่างง่ายที่เรียกว่า StatusMessage
1 #[near_bindgen]
2 #[derive(BorshDeserialize, BorshSerialize)]
3 pub struct StatusMessage {
4 records: LookupMap
5 }
ต่อไป เราจะวิเคราะห์โค้ดห้าบรรทัดข้างต้นอย่างรอบคอบ บรรทัดที่ 1 และ 2 ขึ้นต้นด้วย # คล้ายกับความคิดเห็น อันที่จริง นี่คือรูปแบบหนึ่งของมาโครใน Rust จะรับบรรทัดที่ 3-5 เป็นอินพุต และตามคำจำกัดความของแมโคร จะสร้างเอาต์พุต ตัวอย่างเช่น #[nearbindgen] ในบรรทัดแรกถูกกำหนดโดยฟังก์ชัน Nearbindgen ในแพ็คเกจรุ่น Near-sdk-macro ซึ่งเป็นตำแหน่งที่ใช้มาโครเพื่อสร้างโค้ดการฉีดโดยอัตโนมัติ เป็น MAGIC )
ไม่เป็นไรถ้าคุณไม่เข้าใจ เราต้องรู้ฟังก์ชันของบรรทัดที่ 1 และ 2 เท่านั้น โดยเฉพาะอย่างยิ่ง โครงสร้างที่มีคำอธิบายประกอบด้วย #[nearbindgen] จะกลายเป็นสัญญาอัจฉริยะบน NEAR และโครงสร้างอื่น ๆ เป็นเพียงโครงสร้างธรรมดา ดังนั้น [nearbindgen] จึงเป็นแพ็คเกจที่พัฒนาโดย NEAR และให้บริการแก่นักพัฒนา #[derive(BorshDeserialize, BorshSerialize)] ในบรรทัดที่ 2 ใช้สำหรับการทำให้เป็นซีเรียลไลเซชันและดีซีเรียลไลเซชัน เพื่อให้สามารถส่งสถานะของสัญญาในรูปแบบไบนารีบนสายโซ่ บรรทัดที่ 3-5 เป็นโครงสร้างที่เรียกว่า StatusMessage ซึ่งรักษาสถานะของสัญญาอัจฉริยะ และเนื้อหาของสถานะอธิบายไว้ในบรรทัดที่ 4 โครงสร้างนี้มีตัวแปรสมาชิกเพียงตัวเดียวชื่อเรกคอร์ด ประเภทของมันคือ LookupMap ซึ่งถือได้ว่าเป็นประเภทพจนานุกรม ทั้งคีย์และค่าเป็นประเภทสตริงปกติ
5.4 การตั้งค่าเริ่มต้นของสัญญา
เมื่อเราประกาศสัญญา เรามักจะต้องกำหนดค่าเริ่มต้นของสัญญา รหัสต่อไปนี้ตั้งค่าเริ่มต้นของสัญญา StatusMessage
1 impl Default for StatusMessage {
2 fn default() -> Self {
3 Self {
4 records: LookupMap::new(b"r".to_vec()),
5 }
6 }
7 }
ในหมู่พวกเขา บรรทัดที่ 1 ประกาศว่านี่คือการใช้งานค่าเริ่มต้นสำหรับ StatusMessage บรรทัดที่ 2 ประกาศว่าชื่อเมธอดเป็นค่าเริ่มต้นและค่าส่งคืนคือ Self Self แสดงถึงขอบเขตโมดูลปัจจุบันใน Rust โดยเฉพาะ แสดงถึงอินสแตนซ์ StatusMessage บรรทัดที่ 3-5 คือคำจำกัดความของอินสแตนซ์ เนื่องจากอินสแตนซ์มีระเบียนตัวแปรประเภท LookupMap เท่านั้น โดยผ่านอาร์เรย์ไบนารีข"r".tovec(),สามารถเริ่มต้น LookupMap ได้ วิธีการใหม่ของ LookupMap ถูกกำหนดโดย NEAR เอง ข"r".tovec() ระบุคำนำหน้าของคีย์ที่จัดเก็บไว้ใน LookupMap นี้
5.5 กำหนดวิธีการทำสัญญา
หลังจากที่เราใช้โครงสร้างเพื่อกำหนดสถานะของสัญญาแล้ว เรายังจำเป็นต้องกำหนดชุดของเมธอด เพื่อให้สามารถเรียกเมธอดที่เปิดเผยเหล่านี้ผ่านธุรกรรมภายนอกได้ ต่อไปนี้เป็นวิธีการที่กำหนดไว้สองวิธี ซึ่งสามารถแก้ไขและรับค่าบันทึกในสัญญาปัจจุบันตามลำดับ โปรดทราบว่าเมื่อกำหนดวิธีการของสัญญา เราต้องเพิ่ม #[near_bindgen] ด้วย ดังที่แสดงในบรรทัดที่ 1:
1 #[near_bindgen]
2 impl StatusMessage {
3 pub fn set_status(&mut self, message: String) {
4 let account_id = env::signer_account_id();
5 self.records.insert(&account_id, &message);
6 }
7
8 pub fn get_status(&self, account_id: String) -> Option
9 return self.records.get(&account_id);
10 }
11 }
คำหลักโดยนัยในบรรทัดที่ 2 ระบุว่าเรากำลังนำ StatusMessage ไปใช้อย่างเป็นรูปธรรม
บรรทัดที่ 3-6 กำหนดเมธอด setstatus ฟังก์ชันนี้ใช้เพื่อกำหนดสถานะของสัญญาปัจจุบัน ส่วนที่สามเป็นการประกาศชื่อเมธอดและตัวแปร ฟังก์ชันนี้มีตัวแปรสองตัว ได้แก่ &ปิดเสียงตัวเองและข้อความ: สตริง &mut แสดงถึงการอ้างอิงถึงตนเอง และอาจแก้ไขเนื้อหาของตนเอง และข้อความ: สตริงระบุว่าประเภทของข้อความคือสตริง ในเวลาเดียวกันฟังก์ชันได้รับการตกแต่งด้วยคีย์เวิร์ด pub โปรดทราบว่าเฉพาะฟังก์ชันที่ตกแต่งด้วย pub fn เท่านั้นที่สามารถเรียกใช้โดยธุรกรรมภายนอกซึ่งแสดงว่าเป็นสาธารณะ
บรรทัดที่ 4 กำหนด accountid ของตัวแปรโลคัลซึ่งมีค่าที่ได้รับผ่าน env::signeraccountid() ซึ่งระบุ ID ผู้ใช้ที่เริ่มต้นลายเซ็นธุรกรรม
บรรทัดที่ 5 ใส่รหัสบัญชีเป็นคีย์และข้อความเป็นค่าในเรกคอร์ด โปรดทราบว่าข้อความเป็นตัวแปรประเภท String ซึ่งผู้ใช้ส่งผ่านเข้ามา และข้อความ & หมายถึงการอ้างอิงถึงข้อความ
บรรทัดที่ 8-10 ประกาศฟังก์ชันอื่นที่เรียกว่า getstatus แตกต่างจาก setstatus getstatus จะคืนค่าเป็น None หรือ String type ที่นี่เราใช้ Option เพื่อแสดงค่า
สรุปและแสดงตัวอย่างของปัญหานี้
สรุปและแสดงตัวอย่างของปัญหานี้
นี่คือบล็อกแรกของ BlockSec สำหรับสัญญา Rust ในฉบับนี้ เราจะอธิบายเบื้องหลังของสัญญา Rust และวิธีการสร้างสัญญาอย่างง่ายตามห่วงโซ่ NEAR ในฉบับหน้า เราจะอธิบายเพิ่มเติมเกี่ยวกับวิธีการใช้ Rust ในการเขียนกรณีการทดสอบหน่วยสำหรับสัญญาที่เราสร้างขึ้นเพื่อแก้ปัญหาสัญญาของเรา
