Ethereum Smart Contracts เป็นมากกว่า“ สิ่งใหม่ที่กำลังมาแรง” ฉันเชื่อว่าพวกเขา (หรือบางสิ่งที่เกี่ยวข้อง) พร้อมที่จะเปลี่ยนวิธีที่มนุษย์ทำธุรกิจร่วมกันในยุคใหม่ของอินเทอร์เน็ตที่กำลังจะมาถึง เวลาจะบอกได้ว่าเป็นเช่นนั้นหรือไม่
นี่เป็นบทความแรกของบทความสามตอนใน การพัฒนาสัญญาอัจฉริยะ Ethereum ด้วย Solidity โดยเฉพาะอย่างยิ่งการสำรวจการใช้สัญญากับสิ่งที่เรียกว่า“ oracles” ซึ่งโดยพื้นฐานแล้วเป็นสัญญาที่ปั๊มข้อมูลลงในบล็อกเชนเพื่อใช้โดยสัญญาอัจฉริยะอื่น ๆ
เป้าหมายของเรื่องนี้ในตอนที่ 1 ของซีรีส์นี้ไม่ได้มุ่งเน้นไปที่แนวคิดของสัญญาพยากรณ์ปรัชญาเบื้องหลังพวกเขาหรือแม้แต่ลงลึกในสิ่งที่พวกเขาเป็น เป้าหมายของการสอน Ethereum oracle ในส่วนนี้คือ:
คำจำกัดความ: Oracle วิธีการสำหรับสัญญาอัจฉริยะในการเข้าถึงข้อมูลจากโลกภายนอกบล็อกเชน ประเภทของสัญญาอัจฉริยะนั้นเอง oracles นำข้อมูลจากโลกภายนอกมาใส่ไว้ในบล็อกเชนเพื่อให้สัญญาอัจฉริยะอื่น ๆ ใช้
ส่วนแรกของบทความนี้จะประกอบด้วยการตั้งค่าสิ่งที่จำเป็นต้องมีทั้งหมด จากนั้นเราจะสร้างสัญญา Ethereum ฉบับเดียวและทดสอบกับ Truffle สุดท้ายนี้เราจะแยก oracle ออกจากไคลเอนต์และทดสอบร่วมกัน
ชุดบทความนี้ สามารถ เป็นการแนะนำสัญญาอัจฉริยะเป็นครั้งแรก แต่จะเพิ่มขึ้นอย่างรวดเร็วในแนวคิดขั้นสูงมากขึ้น หากนี่เป็นบทช่วยสอนเกี่ยวกับสัญญาอัจฉริยะครั้งแรกของคุณจงเตรียมพร้อมที่จะไต่ระดับความสูงอย่างรวดเร็ว ถ้าคุณรู้สึกมั่นใจก็ยิ่งดี หากไม่เป็นเช่นนั้นอย่าลังเลที่จะรับบทช่วยสอนประเภท 'สวัสดีชาวโลก' ที่ง่ายกว่านี้หรือสองแบบก่อน เช็คเอาท์ บทความ Ethereum อย่างใดอย่างหนึ่งหรือก่อนหน้านี้ และ Cryptozombies สำหรับผู้เริ่มต้น
ข้อแม้: พื้นที่สัญญาอัจฉริยะเป็นสิ่งใหม่เปลี่ยนแปลงอย่างรวดเร็ว คุณลักษณะไวยากรณ์ Solidity ที่เป็นของใหม่เมื่อเขียนบทความนี้อาจเลิกใช้งานหรือล้าสมัยเมื่อคุณอ่านบทความนี้ เวอร์ชัน Geth อาจมีมาเรื่อย ๆ Solidity มักจะเพิ่มคุณสมบัติภาษาใหม่ ๆ และเลิกใช้ภาษาเก่า ฟีเจอร์ใหม่มากมายกำลังอยู่ในระหว่างการทำงาน ดังนั้นโปรดเตรียมความพร้อมหากจำเป็นในการปรับข้อมูลในบทความนี้ให้เข้ากับภูมิทัศน์ใหม่ในอนาคต ถ้าคุณจริงจังกับการเรียนรู้การพัฒนาสัญญาอัจฉริยะฉันก็เชื่อมั่นในตัวคุณ
กรณีใช้งาน: ผู้ใช้เดิมพันการแข่งขันชกมวย
สัญญาอัจฉริยะยังคงเป็นสิ่งใหม่ พวกเขายังไม่ได้ยึดหลักและหลาย ๆ แง่มุมของวิธีการทำงานยังไม่ได้รับการตีพิมพ์ออกมาและเป็นมาตรฐาน ฉันจะอธิบายสั้น ๆ เกี่ยวกับแรงผลักดันที่อยู่เบื้องหลังความคิดเรื่อง“ oracle” - และจงอดทน เราจะลงลึกมากขึ้นในส่วนต่อไป
วิศวกรรมสัญญา blockchain ไม่เหมือนกับการเขียนโปรแกรมแอปไคลเอนต์เซิร์ฟเวอร์ ข้อแตกต่างที่สำคัญอย่างหนึ่งคือข้อมูลที่สัญญาโต้ตอบต้องอยู่ในบล็อกเชนอยู่แล้ว ไม่มีการโทร ออก ของ blockchain ไม่เพียง แต่ไม่รองรับภาษาเท่านั้น แต่ยังไม่รองรับกระบวนทัศน์บล็อกเชนอีกด้วย สัญญาสามารถเดิมพันในรูปแบบของสกุลเงินที่ใช้ Ethereum เก็บไว้ในสัญญาและปล่อยไปยังที่อยู่กระเป๋าเงินที่ถูกต้องตามสูตรเมื่อมีการประกาศผู้ชนะการแข่งขัน แต่สัญญาจะรู้ได้อย่างไรว่าผู้ชนะ? ไม่สามารถสืบค้น REST API หรืออะไรทำนองนั้นได้ สามารถใช้ได้เฉพาะข้อมูลที่มีอยู่แล้วในบล็อกเชนเท่านั้น! หลายกรณีการใช้งานของสัญญาอัจฉริยะประสบปัญหาที่คล้ายกัน - มีข้อ จำกัด อย่างจริงจังเว้นแต่ว่าจะสามารถโต้ตอบกับโลกภายนอกบล็อกเชนได้
หากสัญญาสามารถโต้ตอบกับข้อมูลบนบล็อกเชนได้เท่านั้นทางออกที่ชัดเจนคือการฉีดข้อมูลที่จำเป็นลงในบล็อกเชน และนั่นคือสิ่งที่ออราเคิลคือ Oracle เป็นอีกสัญญาหนึ่งที่อัดข้อมูลเข้าไปในบล็อกเชนเพื่อให้สัญญาอื่น ๆ ใช้งานได้ แม้ว่าจะทำให้เกิดคำถามเกี่ยวกับความไว้วางใจและความไม่ไว้วางใจ แต่ตอนนี้ยอมรับว่านั่นคือสิ่งที่ออราเคิลคืออะไร ในส่วนที่ 3 ของซีรี่ส์นี้เราจะพูดถึงความแตกต่างเหล่านั้น ในกรณีการใช้งานตัวอย่างของเรา oracle จะเป็นสัญญาที่ฉีดข้อมูลลงใน blockchain เกี่ยวกับ (ก) สิ่งที่ตรงกันที่มีอยู่และ (b) ผู้ที่ชนะการแข่งขันเหล่านั้นเมื่อตัดสินใจแล้ว
สำหรับการตั้งค่าพื้นฐานเราจะติดตั้ง:
บทความนี้ไม่มีพื้นที่สำหรับเป็นแนวทางในการตั้งค่าสภาพแวดล้อมโดยสมบูรณ์ แต่เป็นเพียงคำแนะนำคร่าวๆ ไม่เป็นไรเนื่องจากมีคู่มือการตั้งค่าที่สมบูรณ์มากขึ้นสำหรับระบบปฏิบัติการเฉพาะของคุณอยู่แล้วและอินเทอร์เน็ตไม่จำเป็นต้องมีคู่มือใหม่ ดังนั้นฉันจะพาคุณไปตามเส้นทางอย่างรวดเร็วและชี้ให้คุณไปยังแหล่งข้อมูลเพื่อรับรายละเอียดเพิ่มเติมตามต้องการ เตรียมพร้อมที่จะติดตั้งข้อกำหนดและข้อกำหนดเบื้องต้นตามที่ระบบของคุณต้องการและตามที่ Google สั่งคุณ
Geth คือ Go-ethereum ซึ่งเป็นซอฟต์แวร์หลักของ Ethereum แม้ว่าจะไม่จำเป็นสำหรับแบบฝึกหัดนี้ แต่อย่างใด แต่ผู้พัฒนา Ethereum ก็จะต้องมีและคุ้นเคยกับมัน จำเป็นหากคุณจะติดตั้งสัญญาอัจฉริยะกับเครือข่าย Ethereum ที่ใช้งานอยู่
Truffle เป็นสิ่งสำคัญที่เราจะใช้ในการพัฒนาและเป็นข้อกำหนดสำหรับคู่มือนี้ ค้นหาและปฏิบัติตามคำแนะนำเฉพาะสำหรับระบบปฏิบัติการของคุณเพื่อติดตั้ง Truffle ด้านล่างนี้คือลิงค์บางส่วนที่หวังว่าจะช่วยคุณได้
ขอแนะนำให้ติดตั้ง Ganache CLI เพื่อใช้เป็นเครื่องมือทดสอบอื่นแม้ว่าเราจะไม่ได้ใช้มันสำหรับบทช่วยสอนของเราก็ตาม เป็นทางเลือก
เป็นไปได้มากกว่าที่จะทำแบบฝึกหัดทั้งหมดนี้ด้วยโปรแกรมแก้ไขข้อความธรรมดา ๆ เช่น Notepad ++, gedit, vi หรือโปรแกรมแก้ไขข้อความใด ๆ หรือ IDE ที่คุณเลือก โดยส่วนตัวฉันใช้ Visual Studio Code กับส่วนขยายต่อไปนี้:
หมายเหตุ: ไม่จำเป็นต้องใช้ส่วนขยายเพียง แต่สร้างขึ้นเพื่อสภาพแวดล้อมการเข้ารหัสที่ดีขึ้น
Truffle เป็นเครื่องมือที่สะดวกมากในการรวบรวมสัญญาอัจฉริยะย้ายข้อมูลไปยังบล็อกเชนและยังมีการพัฒนาและแก้ไขข้อบกพร่องยูทิลิตี้ การตั้งค่าโปรเจ็กต์บางอย่างจำเป็นเพื่อที่จะรวมเข้ากับ Truffle ตอนนี้เราจะตั้งค่าเชลล์สำหรับโครงการของเราทั้งใน Truffle และในโครงสร้างไดเรกทอรี เพียงแค่นั่งลงทำตามขั้นตอนทางหุ่นยนต์ในตอนนี้และสนุกไปกับมัน
วิธีคอมไพล์โค้ด c++
สร้างไดเรกทอรีเพื่อเก็บรหัสทั้งหมด โทร oracle- ตัวอย่าง .
ภายในไดเร็กทอรีรูทให้สร้างไดเร็กทอรีย่อยสองไดเร็กทอรีเพราะในที่สุดโปรเจ็กต์จะประกอบด้วยโปรเจ็กต์ย่อยสองโปรเจ็กต์ สร้างไดเรกทอรี:
เข้าไปในโฟลเดอร์ไคลเอ็นต์เนื่องจากเป็นโครงการแรกที่เรากำลังจะพัฒนา เปิดหน้าต่างเทอร์มินัล (บรรทัดคำสั่ง) ในไฟล์ / oracle-example / client โฟลเดอร์
เรียกใช้คำสั่ง truffle init
.
โปรดทราบว่าในบรรดาไฟล์จำนวนมากที่สร้างขึ้นคือไฟล์ truffle-config.js และ truffle.js . เราไม่ต้องการทั้งสองอย่างดังนั้นลบ truffle-config.js (เพื่อหลีกเลี่ยงความสับสนและความยุ่งเหยิง)
เราจำเป็นต้องแก้ไข truffle.js เพื่อชี้ให้ Truffle ไปในทิศทางที่ถูกต้องสำหรับการทดสอบ แทนที่เนื้อหาของ truffle.js ดังต่อไปนี้:
module.exports = { networks: { development: { host: 'localhost', port: 8545, network_id: '*' // Match any network id } } };
https://github.com/jrkosinski/oracle-example/tree/part1-step1/client/truffle.js
สังเกตว่า Truffle init สร้างไดเร็กทอรีที่เรียกว่า การโยกย้าย ( oracle-example / client / migrations ). ภายในโฟลเดอร์นั้นควรมีไฟล์ชื่อ 1_initial_migration.js .
เพิ่มไฟล์อื่นในไดเร็กทอรีการโอนย้ายและตั้งชื่อ 2_deploy_contracts.js โดยมีเนื้อหาดังต่อไปนี้:
var BoxingBets = artifacts.require('BoxingBets'); module.exports = function(deployer) { deployer.deploy(BoxingBets); };
https://github.com/jrkosinski/oracle-example/tree/part1-step1/client/migrations/2deploycontracts.js
ตอนนี้การตั้งค่าง่ายๆไม่สามารถใช้งานได้แล้วเราก็พร้อมที่จะเริ่มเขียนโค้ด โปรดจำไว้ว่าส่วนนี้ของบทความยังคงเป็นบทแนะนำและการตั้งค่าดังนั้นเราจะดำเนินการอย่างรวดเร็วผ่านโค้ด เราจะอธิบายรายละเอียดเชิงลึกเกี่ยวกับโค้ดในส่วนที่ 2 และการอภิปรายเชิงลึกเกี่ยวกับสถาปัตยกรรมและแนวคิดในส่วนที่ 3 ซึ่งกล่าวได้ว่าเราจะพูดถึงแนวคิดหลักบางประการที่ปรากฏในโค้ดอย่างรวดเร็ว ติดตามอย่างระมัดระวังเพื่อให้ทัน
รหัสเต็มสำหรับขั้นตอนนี้ในกระบวนการมีอยู่ใน GitHub: https://github.com/jrkosinski/oracle-example/tree/part1-step1
“ สัญญา” ใน Solidity นั้นคล้ายคลึงกับคลาสในภาษาเชิงวัตถุอื่น ๆ ภาษานั้นได้รับการเปรียบเทียบกับ Golang และ JavaScript และอื่น ๆ โครงสร้างภาษาอื่น ๆ ใน Solidity ซึ่งเราจะมีตัวอย่างในภายหลัง ได้แก่ ตัวดัดแปลงไลบรารีและอินเทอร์เฟซ การรับมรดก (รวมถึงการสืบทอดหลายรายการ) ได้รับการสนับสนุนสำหรับสัญญา ไฟล์สัญญา Solidity มีนามสกุล. sol
เพิ่มไฟล์นี้ในโครงการของคุณ: /oracle-example/client/contracts/OracleInterface.sol
ภาษาโปรแกรม c คืออะไร
https://github.com/jrkosinski/oracle-example/tree/part1-step1/client/contracts/OracleInterface.sol
โดยปกติแล้วอินเทอร์เฟซ oracle จะเป็นเพียงอินเทอร์เฟซ สำหรับการทำซ้ำครั้งแรกนี้เป็นเพียงคลาสธรรมดาที่มีอยู่ในโปรเจ็กต์ Solidity เช่นเดียวกับตัวยึดสำหรับตอนนี้ เราจะย้ายออกไปในขั้นตอนถัดไปหลังจากรวบรวมและเรียกใช้สัญญากับ Truffle สำเร็จแล้ว หลังจากที่เราแปลงสิ่งนี้เป็นอินเทอร์เฟซจริงในภายหลังการใช้งานฟังก์ชันจะว่างเปล่า
เพิ่มไฟล์นี้ในโครงการของคุณ: /oracle-example/client/contracts/BoxingBets.sol
https://github.com/jrkosinski/oracle-example/tree/part1-step1/client/contracts/BoxingBets.sol
นี่คือสัญญาที่ใช้ข้อมูลการแข่งขันชกมวยอนุญาตให้ผู้ใช้สอบถามการแข่งขันที่มีอยู่และวางเดิมพัน ในการทำซ้ำในภายหลังจะคำนวณและจ่ายเงินรางวัล
ตอนนี้เป็นตอนที่เราจะดูว่าเราทำทุกอย่างถูกต้องในครั้งแรกหรือไม่!
เปิดเทอร์มินัลในไฟล์ / oracle- ตัวอย่าง / ไคลเอนต์ / โฟลเดอร์
คอมไพล์โค้ดด้วยคำสั่งนี้:
truffle compile
ทางเลือก: ใช้เชลล์สคริปต์ recompile.sh ของฉัน ( https://github.com/jrkosinski/oracle-example/tree/part1-step1/client/recompile.sh ).
โปรดทราบว่าคุณจะเห็นคำเตือนมากมายเนื่องจากโค้ดของเรายังไม่อยู่ในรูปแบบสุดท้าย!
เปิดคอนโซลการพัฒนา Truffle:
truffle develop
ตอนนี้ในคอนโซลนักพัฒนา Truffle ให้ย้ายไปที่เครือข่ายทดสอบ:
truffle(develop)> migrate
ที่พรอมต์คอนโซลการพัฒนาให้ป้อนโค้ดบรรทัดต่อไปนี้:
truffle(develop)> BoxingBets.deployed().then(inst => { instance = inst })
ตอนนี้“ อินสแตนซ์” เป็นตัวแปรที่อ้างถึงสัญญา BoxingBets และสามารถใช้เพื่อเรียกวิธีการสาธารณะได้
ทดสอบโดยใช้คำสั่งต่อไปนี้:
truffle(develop)> instance.test(3, 4)
โปรดทราบว่าเราได้รวมฟังก์ชัน 'ทดสอบ' สาธารณะไว้ใน BoxingBets.sol . มันจะรวมตัวเลขสองตัวที่คุณส่งผ่านไปเพียงเพื่อแสดงให้เห็นว่าสัญญากำลังเรียกใช้โค้ดและเราสามารถเรียกมันได้จากคอนโซลการพัฒนา Truffle หากเราได้รับคำตอบที่ดูดี (ดูด้านล่าง) งานของเราที่นี่ก็เสร็จแล้ว (อย่างน้อยตอนนี้)
หากตอนนี้ทุกอย่างประสบความสำเร็จแสดงว่าเราประสบความสำเร็จแล้ว สิ่งต่อไปที่เราจะทำคือแยกสัญญา Oracle ออกจากสัญญา BoxingBets ในการใช้งานจริงสัญญาของ oracle จะแยกออกจากสัญญาของลูกค้าบน blockchain ดังนั้นเราจึงต้องสามารถ:
ดังนั้นในระยะสั้นสิ่งที่เรากำลังจะทำในตอนนี้คือการแยก Oracle และลูกค้าออกเป็นสองหน่วยงานสัญญาบล็อกเชนที่แยกจากกันและทำให้พวกเขาพูดคุยกัน ไคลเอนต์จะสร้างอินสแตนซ์ oracle ตามที่อยู่และโทรหา
วงการความงามในตัวเรามีค่าแค่ไหน
ขั้นแรกเราจะเปลี่ยนสัญญาลูกค้า (ไคลเอนต์) เพื่อให้อ้างถึงอินเทอร์เฟซแบบไดนามิกไปยังออราเคิลแทนที่จะเป็นคลาสที่เป็นรูปธรรม จากนั้นเราจะตรวจสอบให้แน่ใจว่ามันสร้างอินสแตนซ์ oracle จากสัญญาภายนอก
เข้าไปใน /oracle-example/client/contracts/OracleInterface.sol . ดังที่เราได้ระบุไว้ก่อนหน้านี้ตอนนี้ไม่ใช่อินเทอร์เฟซ แต่เรากำลังจะทำให้เป็นหนึ่งเดียว แทนที่สิ่งที่อยู่ในนั้นด้วยเนื้อหาของ:
https://github.com/jrkosinski/oracle-example/tree/part1-step2/client/contracts/OracleInterface.sol
pragma solidity ^0.4.17; contract OracleInterface { enum MatchOutcome { Pending, //match has not been fought to decision Underway, //match has started & is underway Draw, //anything other than a clear winner (e.g. cancelled) Decided //index of participant who is the winner } function getPendingMatches() public view returns (bytes32[]); function getAllMatches() public view returns (bytes32[]); function matchExists(bytes32 _matchId) public view returns (bool); function getMatch(bytes32 _matchId) public view returns ( bytes32 id, string name, string participants, uint8 participantCount, uint date, MatchOutcome outcome, int8 winner); function getMostRecentMatch(bool _pending) public view returns ( bytes32 id, string name, string participants, uint participantCount, uint date, MatchOutcome outcome, int8 winner); function testConnection() public pure returns (bool); function addTestData() public; }
ใน BoxingBets.sol เราจะแทนที่บรรทัดนี้:
OracleInterface internal boxingOracle = new OracleInterface();
ด้วยสองบรรทัดนี้:
address internal boxingOracleAddr = 0; OracleInterface internal boxingOracle = OracleInterface(boxingOracleAddr);
ตอนนี้สิ่งที่เราต้องการคือวิธีตั้งค่าที่อยู่ของ oracle แบบไดนามิกและฟังก์ชั่นที่เราสามารถเรียกเพื่อค้นหาที่อยู่ oracle ปัจจุบัน เพิ่มฟังก์ชันทั้งสองนี้ลงใน BoxingBets.sol :
/// @notice sets the address of the boxing oracle contract to use /// @dev setting a wrong address may result in false return value, or error /// @param _oracleAddress the address of the boxing oracle /// @return true if connection to the new oracle address was successful function setOracleAddress(address _oracleAddress) external onlyOwner returns (bool) { boxingOracleAddr = _oracleAddress; boxingOracle = OracleInterface(boxingOracleAddr); return boxingOracle.testConnection(); } /// @notice gets the address of the boxing oracle being used /// @return the address of the currently set oracle function getOracleAddress() external view returns (address) { return boxingOracleAddr; }
และสุดท้ายสำหรับการทดสอบการเชื่อมต่อระหว่างไคลเอนต์และ oracle เราสามารถแทนที่ไฟล์ ทดสอบ ฟังก์ชันใน BoxingBets พร้อมฟังก์ชั่นทดสอบการเชื่อมต่อ oracle:
/// @notice for testing; tests that the boxing oracle is callable /// @return true if connection successful function testOracleConnection() public view returns (bool) { return boxingOracle.testConnection(); }
สังเกตว่าคำจำกัดความของ setOracleAddress
มี onlyOwner
ตัวปรับแต่งตามนั้น ซึ่งจะ จำกัด ไม่ให้ผู้อื่นเรียกฟังก์ชันนี้นอกเหนือจากเจ้าของสัญญาแม้ว่าฟังก์ชันนี้จะเป็นแบบสาธารณะก็ตาม นั่นไม่ใช่คุณสมบัติของภาษา ที่มอบให้กับเราโดยสัญญา Ownable ซึ่งยกออกจากไลบรารีสัญญา Solidity ทั่วไปของ OpenZeppelin เราจะเข้าไปดูรายละเอียดในส่วนที่ 2 แต่เพื่อความสะดวกในการใช้งานนั้น onlyOwner
ตัวแก้ไขเราจำเป็นต้องทำการเปลี่ยนแปลงเล็กน้อย:
สำเนา Ownable.sol จาก https://github.com/jrkosinski/oracle-example/tree/part1-step2/client/contracts/Ownable.sol เป็น / oracle- ตัวอย่าง / ลูกค้า / สัญญา / .
เพิ่มการอ้างอิงที่ด้านบนของ BoxingBets.sol เช่น:
import './Ownable.sol';
(คุณสามารถเพิ่มได้ใต้บรรทัดที่นำเข้า OracleInterface.sol .)
แก้ไขคำประกาศสัญญาของ BoxingBets เพื่อให้ได้รับมรดกจาก Ownable จากสิ่งนี้:
contract BoxingBets {
สำหรับสิ่งนี้:
contract BoxingBets is Ownable {
และเราควรจะพร้อม รหัสเต็มอยู่ที่นี่ในกรณีที่คุณทำหาย: https://github.com/jrkosinski/oracle-example/tree/part1-step2/client/contracts
วิธีเข้ารหัสสกุลเงินดิจิทัล
ตอนนี้สัญญาของ BoxingBets พยายามอ้างถึงสัญญาที่แยกจากกันโดยสิ้นเชิง (นั่นคือ oracle) ตามที่อยู่งานต่อไปของเราคือการสร้างสัญญา Oracle ตอนนี้เรากำลังจะสร้างโปรเจ็กต์แยกกันทั้งหมดซึ่งจะมีสัญญา oracle โดยพื้นฐานแล้วเป็นการตั้งค่าเดียวกับที่เราได้ทำไปแล้วสำหรับโครงการสัญญาของลูกค้า นั่นคือการตั้งค่า Truffle สำหรับการรวบรวมและพัฒนา
คุณควรมีโฟลเดอร์ที่เรียกว่า / oracle- ตัวอย่าง / oracle / ซึ่งเราได้สร้างไว้ในขั้นตอนก่อนหน้านี้ (หรือหากไม่เป็นเช่นนั้นให้สร้างไดเร็กทอรีว่างทันที) เปิดเทอร์มินัลในไดเร็กทอรีนั้น
truffle init
. module.exports = { networks: { development: { host: 'localhost', port: 8545, network_id: '*' // Match any network id } } };
ดูตัวอย่างที่นี่: https://github.com/jrkosinski/oracle-example/tree/part1-step2/oracle/truffle.js
ข้างใน / oracle-example / oracle / migrations / สร้างไฟล์ชื่อ 2_deploy_contracts.js โดยมีเนื้อหาดังต่อไปนี้:
var BoxingOracle = artifacts.require('BoxingOracle'); module.exports = function(deployer) { deployer.deploy(BoxingOracle); };
ดูตัวอย่างที่นี่: https://github.com/jrkosinski/oracle-example/tree/part1-step2/oracle/migrations/2_deploy_contracts.js
สำหรับขั้นตอนนี้ให้คัดลอกไฟล์สามไฟล์ต่อไปนี้จาก https://github.com/jrkosinski/oracle-example/tree/part1-step2/oracle/contracts/ ลงใน /oracle-example/oracle/contracts/
ของคุณ โฟลเดอร์:
ตอนนี้ในการทำซ้ำปัจจุบันของโครงการเราจำเป็นต้องทดสอบคำพยากรณ์สัญญาอัจฉริยะของเราอย่างละเอียดเนื่องจากนั่นจะเป็นฐานที่เราจะสร้างส่วนที่เหลือของโครงการ ตอนนี้เราได้ตั้งค่าโครงการ oracle และคัดลอกโค้ดแล้วเราจะต้องการ:
ยังคงอยู่ในเทอร์มินัลที่เปิดให้ /oracle-example/oracle/
เรียกใช้คำสั่งต่อไปนี้ อีกครั้งขั้นตอนเหล่านี้เหมือนกับสิ่งที่เราได้ทำไปแล้วในการรวบรวมและย้ายสัญญาลูกค้า
truffle compile
ทางเลือก: ใช้เชลล์สคริปต์ recompile.sh ของฉัน ( https://github.com/jrkosinski/oracle-example/tree/part1-step2/oracle/recompile.sh ).
เปิดคอนโซลการพัฒนา Truffle:
truffle develop
ย้ายไปยังเครือข่ายทดสอบ:
truffle(develop)> migrate
ยังคงอยู่ในคอนโซลการพัฒนา Truffle ให้ป้อนสิ่งนี้เพื่อจับตัวชี้ที่ใช้งานได้ไปยังสัญญา oracle:
truffle(develop)> BoxingOracle.deployed().then(inst => { instance = inst })
ตอนนี้เราสามารถ (และควร) เรียกใช้ชุดการทดสอบในสัญญา Oracle ของเราเพื่อทดสอบ ลองรันคำสั่งต่อไปนี้ทีละคำและตรวจสอบผลลัพธ์
truffle(develop)> instance.testConnection() ... truffle(develop)> instance.getAllMatches() ... truffle(develop)> instance.addTestData() ... truffle(develop)> instance.getAllMatches() ...
เมื่อถึงจุดนี้คุณควรตรวจสอบโค้ด oracle ดูว่ามีวิธีการสาธารณะใดบ้างอ่านความคิดเห็นในโค้ดและสร้างการทดสอบของคุณเองเพื่อเรียกใช้ (และเรียกใช้ที่นี่ในคอนโซลในฐานะ แสดงไว้ด้านบน)
ตอนนี้เราพร้อมแล้วสำหรับการทดสอบขั้นสุดท้าย: เพื่อทดสอบว่าสัญญาลูกค้าสามารถเรียกสัญญา oracle ที่มีอยู่แล้วใน blockchain และดึงข้อมูลมาใช้ หากทุกอย่างได้ผลเราจะมีคู่ไคลเอนต์ - ออราเคิลที่เราสามารถใช้สำหรับการทดลองต่อไป ขั้นตอนของเราในการเรียกใช้การทดสอบ end-to-end:
เปิดสองหน้าต่างเทอร์มินัล:
ฉันขอแนะนำให้คุณเก็บไฟล์ / oracle- ตัวอย่าง / ไคลเอนต์ / หนึ่งเปิดทางด้านซ้ายและ / oracle- ตัวอย่าง / oracle / เปิดทางด้านขวาและปฏิบัติตามอย่างใกล้ชิดเพื่อหลีกเลี่ยงความสับสน
ดำเนินการคำสั่งต่อไปนี้ในไฟล์ / oracle- ตัวอย่าง / oracle / ขั้ว:
bash recompile.sh truffle develop truffle(develop)> migrate truffle(develop)> BoxingOracle.deployed().then(inst => { instance = inst })
ดำเนินการคำสั่งต่อไปนี้ในไฟล์ / oracle- ตัวอย่าง / ไคลเอนต์ / ขั้ว:
bash recompile.sh truffle develop truffle(develop)> migrate truffle(develop)> BoxingBets.deployed().then(inst => { instance = inst })
ดำเนินการคำสั่งต่อไปนี้เพื่อ Truffle ในไฟล์ / oracle- ตัวอย่าง / oracle / ขั้ว:
truffle(develop)> instance.getAddress()
คัดลอกที่อยู่ซึ่งเป็นผลลัพธ์จากการโทรนี้ และใช้ในขั้นตอนต่อไป
ดำเนินการคำสั่งต่อไปนี้เพื่อ truffle ในไฟล์ / oracle- ตัวอย่าง / ไคลเอนต์ / ขั้ว:
truffle(develop)> instance.setOracleAddress('')
และทดสอบ:
truffle(develop)> instance.testOracleConnection()
หากผลลัพธ์เป็น true
แสดงว่าเราไปได้ดี
ดำเนินการคำสั่งต่อไปนี้เพื่อ truffle ในไฟล์ / oracle- ตัวอย่าง / ไคลเอนต์ / ขั้ว:
truffle(develop)> instance.getBettableMatches()
ควรส่งคืนอาร์เรย์ว่างเนื่องจากยังไม่มีการเพิ่มข้อมูลการทดสอบไปยังด้าน oracle
ดำเนินการคำสั่งต่อไปนี้เพื่อ truffle ในไฟล์ / oracle- ตัวอย่าง / oracle / เทอร์มินัลเพื่อเพิ่มข้อมูลการทดสอบ:
truffle(develop)> instance.addTestData()
ดำเนินการคำสั่งต่อไปนี้เพื่อ truffle ในไฟล์ / oracle- ตัวอย่าง / ไคลเอนต์ / เทอร์มินัลเพื่อดูว่าเราสามารถรับข้อมูลทดสอบที่เพิ่มใหม่จากไคลเอนต์ได้หรือไม่:
truffle(develop)> instance.getBettableMatches()
ตอนนี้ถ้าคุณรับที่อยู่แต่ละรายการจากอาร์เรย์ที่ส่งคืนโดย getBettableMatches()
และเสียบเข้ากับ getMatch()
ในตอนนี้คุณควรตรวจสอบโค้ดไคลเอนต์ดูว่ามีวิธีการสาธารณะใดบ้างอ่านความคิดเห็นในโค้ดและสร้างการทดสอบของคุณเองเพื่อเรียกใช้ (และเรียกใช้ที่นี่ในคอนโซลตามที่ ข้างบน).
ผลลัพธ์ของเราจากแบบฝึกหัดนี้มี จำกัด แต่เป้าหมายของเราก็เป็นเช่นนั้นเพื่อที่จะก้าวไปอย่างเป็นจริง ลูกค้าของเรายังไม่มีความสามารถในการเดิมพันจัดการเงินทุนแบ่งเงินรางวัล ฯลฯ สิ่งที่เรามีนอกเหนือจากความรู้และประสบการณ์ที่ได้รับคือ:
และนั่นก็ไม่เลวร้ายเกินไปสำหรับบทความสั้น ๆ
ใน ส่วนที่สองของซีรีส์นี้ เราจะเจาะลึกมากขึ้นในโค้ดและดูคุณสมบัติบางอย่างที่เป็นเอกลักษณ์เฉพาะของการพัฒนาสัญญาอัจฉริยะรวมถึงคุณลักษณะภาษาบางอย่างที่เฉพาะเจาะจงสำหรับ Solidity หลายสิ่งที่ถูกปัดสวะในส่วนนี้จะได้รับการอธิบายในครั้งต่อไป
ใน ส่วนที่สามของซีรีส์นี้ เราจะพูดถึงปรัชญาและการออกแบบสัญญาอัจฉริยะโดยเฉพาะที่เกี่ยวข้องกับการใช้งานกับ oracles
การทดลองเดี่ยวเป็นวิธีที่ดีในการเรียนรู้ คำแนะนำง่ายๆสองสามข้อต่อไปนี้หากคุณกำลังคิดหาวิธีขยายบทช่วยสอนนี้เพื่อความรู้ที่มากขึ้น (ส่วนที่ 2 และ 3 จะไม่กล่าวถึงต่อไปนี้):
ขอให้โชคดีโปรดอย่าลังเลที่จะติดต่อฉันหากมีคำถามใด ๆ ฉันไม่สามารถรับประกันได้ว่าจะตอบกลับอย่างรวดเร็วเสมอไป แต่ฉันจะทำให้ดีที่สุด
ขนาดหน้าจอทั่วไปสำหรับการออกแบบที่ตอบสนอง
ภาษาโปรแกรมที่ใช้ในการพัฒนา Ethereum คือ Solidity เป็นภาษาการเขียนโปรแกรมเชิงสัญญาที่ได้รับแรงบันดาลใจจาก JavaScript, Python และ C ++
สิ่งที่เรียกว่า * blockchain oracle * เป็นแหล่งข้อมูลที่เชื่อถือได้ซึ่งให้ข้อมูลเกี่ยวกับสถานะและเหตุการณ์ต่างๆที่ใช้โดยสัญญาอัจฉริยะ
คำทำนายสัญญาอัจฉริยะใช้เพื่อเชื่อมโยงระหว่างเหตุการณ์ในโลกแห่งความจริงและสัญญาดิจิทัล ข้อมูลภายนอกที่จัดทำโดย oracles อาจ (หรืออาจไม่) ทำให้เกิดการดำเนินการตามสัญญาอัจฉริยะ