Contracte Ethereum Oracle: Configurare și orientare

Publicat: 2022-03-11

Contractele inteligente Ethereum sunt mai mult decât „noul lucru fierbinte”. Cred că ei (sau ceva înrudit) sunt gata să schimbe modul în care oamenii fac afaceri între ei în noua era viitoare a internetului. Timpul va spune dacă este cazul.

Acesta este primul articol din trei părți despre dezvoltarea contractelor inteligente Ethereum cu Solidity, cel mai specific explorând utilizarea contractelor cu așa-numitele „oracole” – care sunt în principiu contracte care pompează date în blockchain pentru a fi utilizate de alte contracte inteligente.

  • Partea 1: O introducere în dezvoltarea cu Truffle și configurarea proiectului pentru experimentare ulterioară
  • Partea 2: Aprofundarea codului pentru o examinare mai profundă
  • Partea 3: O discuție conceptuală despre oracole cu contracte inteligente

Scopul acestei părți, partea 1 a seriei, nu este de a intra prea mult în conceptul de contracte oracol, filozofia din spatele lor, sau chiar foarte profund în ceea ce sunt ele; Scopul acestei părți a tutorialului nostru de oracol Ethereum este pur și simplu:

  • Stabiliți-vă cu crearea de contracte inteligente cu Truffle.
  • Construiți un proiect de contract inteligent care ne va servi în părțile 2 și 3.
  • Introduceți câteva concepte legate de contractele inteligente Ethereum și codificarea contractelor inteligente.
  • Introduceți ciclul de compilare/rulare/depanare cu Truffle și contracte inteligente.

Definiție: Oracol. Un mijloc pentru contractele inteligente de a accesa date din lumea din afara blockchain-ului. Un tip de contract inteligent în sine, oracolele preiau date din lumea exterioară și le pun în blockchain pentru ca alte contracte inteligente să le consume.

Prima parte a acestui articol va consta în configurarea cu toate cerințele prealabile. Apoi, vom configura un singur contract Ethereum și îl vom testa cu Truffle. În cele din urmă, vom separa oracolul de client și le vom testa împreună.

Cerințe software

  • Orice sistem de operare major va funcționa, deși unele dintre instalări și configurare vor fi, desigur, diferite pe sisteme diferite. Am făcut toate acestea pe Ubuntu Linux (16.04). De asemenea, nu am avut probleme la configurarea mediului pe Windows. Nu am încercat Mac, deși sunt conștient că este obișnuit să fac acest lucru și pe Mac.
  • Nu este necesar să rulați un nod eth complet; vom folosi Truffle, care vine cu propriul testnet. Dacă știi puțin despre ceea ce faci, poți folosi orice alt testnet pe care îl alegi; Testnetul de dezvoltare local al Truffle este cel mai ușor și mai accesibil pentru scopurile acestui tutorial.

Cerințe de cunoștințe

  • Cunoștințe de bază despre cum funcționează blockchain
  • Înțelegerea a ceea ce este un contract inteligent bazat pe blockchain
  • O experiență de bază hello-worldish cu dezvoltarea unui contract inteligent va fi utilă, dar nu este necesară dacă ești inteligent și ambițios. (Și știu că ești!)

Această serie de articole poate servi ca o primă introducere în contractele inteligente, dar trece foarte repede la concepte mai avansate. Dacă este primul tău tutorial eth smart contract, fii pregătit să urci rapid la altitudine. Dacă te simți încrezător, grozav; dacă nu, simțiți-vă liber să obțineți mai întâi un tip de tutorial mai simplu „hello world” sau două sub centură. Consultați unul dintre articolele Ethereum sau anterioare și Cryptozombies, pentru început.

Avertisment: spațiul smart contract, fiind atât de nou, se schimbă rapid. Caracteristicile de sintaxă Solidity care erau noi când a fost scris acest articol pot fi depreciate sau depășite în momentul în care citiți acest articol. Este posibil ca versiunile Geth să fi venit și să plece. Solidity adaugă mereu noi funcții de limbaj și le depreciază pe cele vechi. Multe funcții noi sunt în prezent în lucru. Așadar, fiți pregătit dacă este necesar să adaptați informațiile din acest articol la noul peisaj al viitorului; dacă ești serios să înveți dezvoltarea unui contract inteligent, atunci am încredere în tine.

Descrierea exemplului de aplicație

Caz de utilizare: utilizatorii pariază pe meciuri de box.

  • Utilizatorul poate trage o listă de meciuri de box care pot fi pariate.
  • Utilizatorul poate alege un meci și poate pune un pariu pe câștigător.
  • Utilizatorul poate paria orice sumă peste un minim specificat.
  • Dacă alegerea utilizatorului pierde, utilizatorul pierde întreaga sumă a pariului.
  • În cazul în care alegerea utilizatorului câștigă, utilizatorul primește o parte din pot în funcție de mărimea pariului său și de suma totală pariată pe pierderea meciului, după ce casa (proprietarul contractului) ia un mic procent din câștiguri. .

Ce este un oracol Ethereum?

Contractele inteligente sunt încă un lucru nou; încă nu au preluat curentul mainstream și atât de multe aspecte ale modului în care vor funcționa nu au fost încă stabilite și standardizate. Voi explica pe scurt impulsul din spatele ideii de „oracol” – și voi avea răbdare; vom intra în ea mai în profunzime în părțile ulterioare.

Proiectarea unui contract blockchain nu este ca programarea unei aplicații client-server. O diferență importantă este că datele cu care interacționează contractul trebuie să fie deja pe blockchain. Nu există apeluri din blockchain. Nu numai că nu este susținut de limbaj, dar nu este susținut de paradigma blockchain. Contractul poate accepta pariuri sub formă de monedă bazată pe Ethereum, le poate stoca în contract și le poate elibera la adresele corecte de portofel conform unei formule, atunci când este declarat câștigătorul unui meci. Dar de unde știe contractul câștigătorul? Nu poate interoga un API REST sau ceva de genul acesta. Poate folosi doar date care sunt deja în blockchain! Multe multe cazuri de utilizare ale contractelor inteligente se confruntă cu o problemă similară - sunt foarte limitate, cu excepția cazului în care pot interacționa cu lumea din afara blockchain-ului.

Dacă contractul poate interacționa doar cu datele din blockchain, o soluție evidentă este injectarea datelor necesare în blockchain. Și asta este un oracol. Un oracol este un alt contract, care injectează date în blockchain, permițând altor contracte să le consume. Deși asta poate ridica întrebări despre încredere și lipsă de încredere, acceptați doar pentru moment că asta este un oracol. În partea 3 a acestei serii, vom discuta aceste nuanțe. În cazul nostru de utilizare exemplu, oracolul va fi contractul care injectează date în blockchain, cu privire la (a) ce meciuri sunt disponibile și (b) cine a câștigat acele meciuri, odată decis.

Configurarea mediului de dezvoltare Ethereum

Pentru configurarea de bază, vom instala:

  • Geth (opțional pentru moment)
  • Trufe
  • Ganache CLI (opțional)
  • Un mediu de dezvoltare (opțional)

Acest articol nu are spațiul necesar pentru a fi un ghid complet pentru configurarea mediului, ci acționează doar ca un ghid brut. Este în regulă, totuși, pentru că există deja o mulțime de ghiduri de configurare mai complete pentru sistemul dvs. de operare, iar internetul nu are nevoie de unul nou. Așa că vă voi duce rapid pe cale și vă voi indica câteva resurse pentru a obține mai multe detalii, după cum este necesar. Fiți pregătit să instalați cerințele și cerințele prealabile, așa cum vă solicită sistemul și așa cum vă îndrumă Google.

Ilustrarea procesului de contracte Oracle

Instalați Geth (opțional)

Captură de ecran a instalării Geth Faceți clic pentru a vedea imaginea la dimensiune completă.

Geth este Go-ethereum, software-ul de bază Ethereum; deși nu este deloc necesar pentru acest exercițiu, ar fi cazul oricărui viitor dezvoltator Ethereum să-l aibă și să fie familiarizat cu el. Va fi necesar dacă veți implementa vreodată contractul inteligent în rețeaua Ethereum live.

  • http://www.talkcrypto.org/blog/2018/01/23/what-is-geth/
  • https://github.com/ethereum/go-ethereum/wiki/Installation-Instructions-for-Ubuntu
  • https://github.com/ethereum/go-ethereum/wiki/Installation-instructions-for-Windows

Instalați Truffle

Captură de ecran a instalării Truffle Faceți clic pentru a vedea imaginea la dimensiune completă.

Trufa este principalul lucru pe care îl vom folosi pentru dezvoltare și este absolut o cerință pentru acest ghid. Găsiți și urmați instrucțiunile specifice pentru sistemul de operare pentru a instala Truffle. Mai jos sunt câteva link-uri care sper să vă ajute.

  • https://truffleframework.com/docs/truffle/getting-started/installation
  • https://github.com/trufflesuite/truffle
  • https://truffleframework.com/tutorials/how-to-install-truffle-and-testrpc-on-windows-for-blockchain-development

Instalați Ganache CLI (opțional)

Captură de ecran a instalării Ganache CLI Faceți clic pentru a vedea imaginea la dimensiune completă.

Recomand să instalați Ganache CLI pentru a fi folosit ca un alt instrument de testare, deși nu îl vom folosi de fapt pentru tutorialul nostru. Este optional.

https://github.com/trufflesuite/ganache-cli

Mediul de dezvoltare Ethereum

Ar fi mai mult decât posibil să faci întreg acest tutorial cu orice editor de text simplu, cum ar fi Notepad++, gedit, vi sau orice editor de text sau IDE la alegere. Eu personal folosesc Visual Studio Code cu următoarele extensii:

  • Soliditate
  • Soliditatea extinsă
  • Tema pictogramei materiale

Notă: Extensiile nu sunt necesare - doar creează un mediu de codare mai bun.

Configurarea codului

Configurarea proiectului

Truffle este un instrument foarte convenabil pentru compilarea contractelor inteligente, migrarea lor către un blockchain și, de asemenea, oferă utilități de dezvoltare și depanare. Va fi necesară o anumită configurare a proiectului pentru a se integra cu Truffle. Acum vom configura shell-ul pentru proiectul nostru, atât în ​​Truffle, cât și în structura directoarelor. Stați pe spate, urmați pașii robot deocamdată și bucurați-vă.

Creați un director pentru a găzdui tot codul; numiți-o oracol-exemplu .

În directorul rădăcină, creați două subdirectoare, pentru că în cele din urmă, proiectul va consta din două sub-proiecte. Creați directoarele:

  • /oracol-example/client
  • /oracol-exemplu/oracol

Intrați în folderul client, pentru că acesta este primul proiect pe care îl vom dezvolta. Deschideți o fereastră de terminal (linie de comandă) în folderul /oracle-example/client .

Rulați comanda truffle init .

Rețineți că printre multe fișiere create se numără truffle-config.js și truffle.js . Nu avem nevoie de ambele, așa că ștergeți truffle-config.js (doar pentru a evita confuzia și dezordinea).

Trebuie să edităm truffle.js , pentru a îndrepta Truffle în direcția corectă pentru testare. Înlocuiți conținutul truffle.js cu următorul:

 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

Rețineți că Truffle init a creat un director numit migrations ( oracle-example/client/migrations ). În interiorul acelui folder ar trebui să fie un fișier numit 1_initial_migration.js .

Adăugați un alt fișier în directorul de migrare și denumiți-l 2_deploy_contracts.js , cu următorul conținut:

 var BoxingBets = artifacts.require("BoxingBets"); module.exports = function(deployer) { deployer.deploy(BoxingBets); };

https://github.com/jrkosinski/oracle-example/tree/part1-step1

Adăugarea Codului

Acum, că configurarea simplă este îndepărtată, suntem pregătiți să începem codificarea. Amintiți-vă, această parte a articolului este încă introducere și configurare, așa că vom trece destul de repede prin cod. Vom intra în explicații mai aprofundate ale codului în partea 2 și discuții mai aprofundate despre arhitectură și concept în partea 3. Acestea fiind spuse, vom atinge rapid câteva concepte de bază evidente în cod. Urmați cu atenție pentru a ține pasul.

Codul complet pentru acest pas al procesului este disponibil pe GitHub: https://github.com/jrkosinski/oracle-example/tree/part1-step1

Contracte în Soliditate

Un „contract” în Solidity este aproximativ analog cu o clasă din alte limbaje orientate pe obiect. Limbajul în sine a fost comparat cu Golang și JavaScript, printre altele. Alte construcții de limbaj din Solidity - despre care vom avea exemple mai târziu - sunt modificatori, biblioteci și interfețe. Moștenirea (inclusiv moștenirea multiplă) este acceptată pentru contracte. Fișierele contractului de soliditate au extensia .sol.

Interfața Oracle

Adăugați acest fișier în proiectul dvs.: /oracle-example/client/contracts/OracleInterface.sol

https://github.com/jrkosinski/oracle-example/tree/part1-step1/client/contracts/OracleInterface.sol

Captură de ecran a interfeței Oracle Faceți clic pentru a vedea imaginea la dimensiune completă.

În mod normal, interfața Oracle ar fi doar asta: o interfață. Pentru această primă iterație, este doar o clasă simplă conținută în proiectul Solidity, doar ca substituent pentru moment. Îl vom muta în pasul următor, după ce vom compila și rula cu succes contractul pe Truffle. După ce convertim aceasta într-o interfață reală mai târziu, implementările funcției vor fi goale.

Contract client

Adăugați acest fișier în proiectul dvs.: /oracle-example/client/contracts/BoxingBets.sol

https://github.com/jrkosinski/oracle-example/tree/part1-step1/client/contracts/BoxingBets.sol

Acesta este contractul care consumă datele meciului de box, permite utilizatorilor să interogheze meciurile disponibile și să parieze pe ele. În iterațiile ulterioare, va calcula și va plăti câștigurile.

Compilarea și rularea

Acum vom vedea dacă am făcut totul bine de prima dată!

Compilați și migrați contractul

Deschideți un terminal în folderul /oracle-example/client/

Compilați codul cu această comandă:

 truffle compile 
Captură de ecran cu compilarea și migrarea contractului Faceți clic pentru a vedea imaginea la dimensiune completă.
A doua captură de ecran a compilării și migrării contractului Faceți clic pentru a vedea imaginea la dimensiune completă.

Alternativ: utilizați scriptul meu shell recompile.sh (https://github.com/jrkosinski/oracle-example/tree/part1-step1/client/recompile.sh).

Rețineți că veți vedea o mulțime de avertismente, deoarece codul nostru nu este încă în forma sa finală!

Deschideți consola de dezvoltare Truffle:

 truffle develop

Acum, în consola pentru dezvoltatori Truffle, migrați la rețeaua de testare:

 truffle(develop)> migrate

Rulați Contractul

La promptul consolei de dezvoltare, introduceți următoarea linie de cod:

 truffle(develop)> BoxingBets.deployed().then(inst => { instance = inst })

Acum, „instanță” este variabila care se referă la contractul BoxingBets și poate fi folosită pentru a apela metodele sale publice.

Testați-l folosind următoarea comandă:

 truffle(develop)> instance.test(3, 4)

Rețineți că am inclus o funcție publică de „test” în BoxingBets.sol . Adună toate cele două numere pe care le transmiteți, doar pentru a demonstra că contractul execută cod și că îl putem apela din consola de dezvoltare Truffle. Dacă primim un răspuns sănătos (vezi mai jos), atunci treaba noastră aici este gata (cel puțin deocamdată).

Separați Oracolul Ethereum

Dacă totul a reușit până acum, atunci am trecut peste cocoașă. Următorul lucru pe care îl vom face este să separăm contractul Oracle de contractul BoxingBets. În uz real, contractul oracolului va exista separat de contractul client pe blockchain, așa că va trebui să putem:

Diagrama proceselor contractului oracol Ethereum

  • Instanțiați-l prin adresa blockchain.
  • Schimbați în mod dinamic adresa oracolului pe care contractul client o folosește pentru a face referire la oracol.

Deci, pe scurt, ceea ce vom face acum este să separam oracolul și clientul în două entități contractuale blockchain separate și să îi facem să vorbească unul cu celălalt. Clientul va instanția oracolul după adresă și îl va apela.

Contract client

În primul rând, vom schimba contractul client (client) astfel încât să se refere la o interfață dinamică la un oracol mai degrabă decât la o clasă concretă. Apoi ne vom asigura că instanțiază oracolul dintr-un contract extern.

Accesați /oracle-example/client/contracts/OracleInterface.sol . După cum am menționat anterior, aceasta nu este în prezent o interfață, dar suntem pe cale să o facem. Înlocuiți ceea ce este acolo cu conținutul:

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 (eg 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; }

În BoxingBets.sol , vom înlocui această linie:

 OracleInterface internal boxingOracle = new OracleInterface();

Cu aceste două rânduri:

 address internal boxingOracleAddr = 0; OracleInterface internal boxingOracle = OracleInterface(boxingOracleAddr);

Acum, ceea ce dorim este o modalitate de a seta adresa oracolului, în mod dinamic, și o funcție pe care o putem apela pentru a afla adresa curentă a oracolului. Adăugați aceste două funcții la 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; }

Și, în sfârșit, pentru testarea conexiunii dintre client și oracol, putem înlocui funcția de testare din BoxingBets cu o funcție de testare a conexiunii oracol:

 /// @notice for testing; tests that the boxing oracle is callable /// @return true if connection successful function testOracleConnection() public view returns (bool) { return boxingOracle.testConnection(); }

Proprietar

Observați că definiția pentru setOracleAddress are un modificator onlyOwner după ea. Asta împiedică apelarea acestei funcții de către altcineva decât proprietarul contractului, chiar dacă funcția este publică. Aceasta nu este o caracteristică de limbă. Acest lucru ne este oferit de contractul Ownable, care este scos din biblioteca OpenZeppelin de contracte de utilitate generală Solidity. Vom intra în detalii în partea 2, dar pentru a facilita utilizarea modificatorului onlyOwner , trebuie să facem câteva modificări:

Copiați Ownable.sol de pe https://github.com/jrkosinski/oracle-example/tree/part1-step2/client/contracts/Ownable.sol în /oracle-example/client/contracts/ .

Adăugați o referință la acesta în partea de sus a BoxingBets.sol , așa:

 import "./Ownable.sol";

(Puteți să-l adăugați chiar sub linia care importă OracleInterface.sol .)

Modificați declarația de contract a BoxingBets pentru a o moșteni de la Ownable, de aici:

 contract BoxingBets {

La acest:

 contract BoxingBets is Ownable {

Și ar trebui să fim gata. Codul complet este aici în cazul în care v-ați pierdut: https://github.com/jrkosinski/oracle-example/tree/part1-step2/client/contracts

Contracte Oracle

Înființat

Acum că contractul BoxingBets încearcă să se refere la un contract complet separat (adică oracolul) prin adresă, următoarea noastră sarcină este să creăm acel contract oracol. Așa că acum vom crea un proiect complet separat care va conține contractul Oracle. Este, în esență, aceeași configurație pe care am făcut-o deja pentru proiectul contractului client; adică configurarea Truffle pentru compilare și dezvoltare.

Ar trebui să aveți deja un folder numit /oracle-example/oracle/ pe care l-am creat într-un pas anterior (sau dacă nu, mergeți mai departe și creați acel director gol acum). Deschideți un terminal în acel director.

  • Rulați comanda truffle init .
  • Ștergeți /oracle-example/oracle/truffle-config.js .
  • Editați /oracle-example/oracle/truffle.js astfel:
 module.exports = { networks: { development: { host: "localhost", port: 8545, network_id: "*" // Match any network id } } };

Vezi exemplul aici: https://github.com/jrkosinski/oracle-example/tree/part1-step2/oracle/truffle.js

În /oracle-example/oracle/migrations/ , creați un fișier numit 2_deploy_contracts.js , cu următorul conținut:

 var BoxingOracle = artifacts.require("BoxingOracle"); module.exports = function(deployer) { deployer.deploy(BoxingOracle); };

Vezi exemplul aici: https://github.com/jrkosinski/oracle-example/tree/part1-step2/oracle/migrations/2_deploy_contracts.js

Codul Oracle

Pentru acest pas, pur și simplu copiați următoarele trei fișiere din https://github.com/jrkosinski/oracle-example/tree/part1-step2/oracle/contracts/ în folderul dumneavoastră /oracle-example/oracle/contracts/ :

  • BoxingOracle.sol: Contractul principal al oracolului.
  • Ownable.sol: Pentru funcțiile exclusiv de proprietar, așa cum am folosit deja în contractul clientului.
  • DateLib.sol: O bibliotecă de date. O vom analiza mai în profunzime în partea a 2-a a acestei serii.

Testarea Oracolului

Acum, în iterația actuală a proiectului, trebuie să testăm temeinic oracolul nostru smart contract, deoarece aceasta va fi baza noastră pe care vom construi restul proiectului. Deci, acum că am configurat proiectul Oracle și am copiat codul, vom dori să:

  • Compilați oracolul.
  • Asigurați-vă că oracolul rulează.
  • Rulați câteva funcții în consola Truffle pentru a vă asigura că oracolul funcționează conform așteptărilor.

Compilați și migrați Oracle

Încă într-un terminal deschis către /oracle-example/oracle/ , rulați următoarele comenzi. Din nou, acești pași sunt identici cu ceea ce am făcut deja pentru a compila și a migra contractul client.

 truffle compile

Alternativ: Folosiți scriptul meu shell recompile.sh (https://github.com/jrkosinski/oracle-example/tree/part1-step2/oracle/recompile.sh).

Deschideți consola de dezvoltare Truffle:

 truffle develop

Migrați la rețeaua de testare:

 truffle(develop)> migrate

Rulați și testați Oracolul

Încă în consola de dezvoltare Truffle, introduceți aceasta pentru a captura un pointer utilizabil către contractul oracol:

 truffle(develop)> BoxingOracle.deployed().then(inst => { instance = inst })

Acum putem (și ar trebui) să rulăm o suită de teste pe contractul nostru Oracle pentru a-l testa. Încercați să rulați următoarele comenzi, fiecare pe rând și examinați rezultatele.

 truffle(develop)> instance.testConnection() ... truffle(develop)> instance.getAllMatches() ... truffle(develop)> instance.addTestData() ... truffle(develop)> instance.getAllMatches() ...

Sunteți încurajat în acest moment să aruncați o privire prin codul Oracle, să vedeți ce metode publice sunt disponibile, să citiți comentariile din cod și să veniți cu unele dintre propriile dvs. teste de rulat (și să le rulați aici în consolă, ca prezentat mai sus).

Testare și depanare

Acum suntem pregătiți pentru testul final: să testăm că contractul client poate apela contractul oracle care se află deja pe blockchain și poate extrage și utiliza datele acestuia. Dacă toate acestea funcționează, atunci avem o pereche client-oracol pe care o putem folosi pentru experimente ulterioare. Pașii noștri pentru a rula testul end-to-end:

  • Compilați și rulați contractul Oracle
  • Întocmește și rulează contractul clientului
  • Obțineți adresa contractului oracol
  • Setați adresa oracolului în contractul clientului
  • Adăugați date de testare la contractul Oracle
  • Testați că putem prelua acele date din contractul clientului

Deschideți două ferestre de terminal:

  • Unul în /oracle-example/client/
  • Și celălalt în /oracle-example/oracle/

Vă sugerez să păstrați unul deschis pe /oracle-example/client/ în stânga și pe /oracle-example/oracle/ unul deschis în dreapta și să urmați îndeaproape pentru a evita confuzia.

Compilați și rulați contractul Oracle

Executați următoarele comenzi în terminalul /oracle-example/oracle/ :

 bash recompile.sh truffle develop truffle(develop)> migrate truffle(develop)> BoxingOracle.deployed().then(inst => { instance = inst })

Compilați și rulați contractul client

Executați următoarele comenzi în terminalul /oracle-example/client/ :

 bash recompile.sh truffle develop truffle(develop)> migrate truffle(develop)> BoxingBets.deployed().then(inst => { instance = inst })

Obțineți adresa contractului Oracle

Executați următoarea comandă către Truffle în terminalul /oracle-example/oracle/ :

 truffle(develop)> instance.getAddress()

Copiați adresa care este rezultatul acestui apel; și folosește-l în pasul următor.

Setați adresa Oracle în contractul client

Executați următoarea comandă pentru truffle în terminalul /oracle-example/client/ :

 truffle(develop)> instance.setOracleAddress('<insert address here, single quotes included>')

Și testați-l:

 truffle(develop)> instance.testOracleConnection()

Dacă rezultatul este true , atunci suntem gata.

Testați că putem prelua acele date din contractul clientului

Executați următoarea comandă pentru truffle în terminalul /oracle-example/client/ :

 truffle(develop)> instance.getBettableMatches()

Ar trebui să returneze o matrice goală, deoarece nu au fost încă adăugate date de testare la partea oracolului.

Executați următoarea comandă pentru truffle în terminalul /oracle-example/oracle/ pentru a adăuga date de testare:

 truffle(develop)> instance.addTestData()

Executați următoarea comandă pentru truffle în terminalul /oracle-example/client/ , pentru a vedea dacă putem prelua datele de testare nou adăugate de la client:

 truffle(develop)> instance.getBettableMatches()

Acum, dacă luați adrese individuale din matricea returnată de getBettableMatches() și conectați-le la getMatch() .

Sunteți încurajat în acest moment să aruncați o privire prin codul client, să vedeți ce metode publice sunt disponibile, să citiți comentariile din cod și să veniți cu unele dintre propriile dvs. teste de rulat (și să le rulați aici în consolă, ca de mai sus).

Concluzia primei părți

Rezultatele noastre din acest exercițiu sunt limitate, dar la fel și obiectivele noastre, pentru a păstra un ritm realist. Clientul nostru nu are încă capacitatea de a lua pariuri, de a gestiona fonduri, de a împărți câștigurile etc. Ceea ce avem, în afară de cunoștințele și experiența dobândită, este:

  • Un oracol de contract inteligent în mare parte funcțional
  • Un client care se poate conecta și interacționa cu oracolul
  • Un cadru pentru dezvoltare și învățare ulterioară

Și asta nu e prea rău pentru un articol scurt.

În partea a doua a acestei serii , vom aprofunda codul și vom analiza unele dintre caracteristicile care sunt unice pentru dezvoltarea de contracte inteligente, precum și unele dintre caracteristicile limbajului care sunt specifice Solidity. Multe dintre lucrurile care tocmai au fost ocolite în această parte vor fi explicate în următoarea.

În partea a treia a acestei serii , vom discuta puțin despre filosofia și designul contractelor inteligente, în special în legătură cu utilizarea lor cu oracole.

Alți pași opționali

Experimentarea individuală este o modalitate bună de a învăța. Iată câteva sugestii simple dacă vă gândiți la modalități de a extinde acest tutorial pentru mai multe cunoștințe (niciuna dintre următoarele nu va fi acoperită în părțile 2 și 3):

  • Implementați contractele în Ganache (fost testrpc) și rulați aceleași teste pentru a verifica funcția.
  • Implementați contractele pentru rețelele de testare ropsten sau rinkeby și rulați aceleași teste pentru a verifica funcționarea.
  • Construiți un front end web3js fie pentru oracol, fie pentru client (sau ambele).

Succes și vă rugăm să nu ezitați să mă contactați pentru orice întrebări. Nu pot garanta neapărat un răspuns rapid, dar voi face tot posibilul.