Introduktion till fasthet: Skapa ett datakontrakt [Del 1]

Soliditet är ett javaskript som ett språk som används för att koda smarta kontrakt på Ethereum-plattformen. Den kompileras till ett bytecode-format som förstås av Ethereum Virtual machine (EVM). Det är ett starkt skrivet språk med förmågan att definiera anpassade datastrukturer. Introduktion till soliditet del 1 lär dig att använda en delmängd av soliditetsfunktionalitet för att skapa en mall för ett smart kontrakt som kan återanvändas för att formulera en komplett uppsättning kontrakt som innehåller data och grundläggande logik som fungerar för alla domäner. Detta kommer att vara en serie med flera delar eftersom den kommer att täcka grundläggande kontraktsdesign och några relaterade problem.

Introduktion till soliditet

Introduktion till fasthet: Skapa en miljö

För att utföra smarta kontrakt behöver vi ett system som kan kompilera, distribuera och anropa dess metoder. För alla de tre har vi en mycket enkel integrerad webbläsarbaserad app här.

Det är möjligt att använda detta verktyg för att ansluta till en levande eterumnod eller för att bilda en mock-miljö. Denna miljö kan också enkelt utföra vissa testfall på kontraktsmetoderna. Det behöver ingen installation och är helt webbläsarbaserat. Jag har använt det på krom över ubuntu, men jag är säker på att det fungerar lika bra på andra plattformar. Den vänstra rutan i appen är där kontraktskoden finns, och till höger finns distributions- och testalternativ. Appen kan arbeta med kontraktsfiler från egna system.

Källkoden för kontraktet vi kommer att diskutera är tillgänglig här. Vissa delar av avtalskoden kommer att diskuteras i de senare delarna av serien. Koden och laddas ner och laddas in i Remix för att se avsnitten som diskuteras nedan. Solidity senaste icke-släppta versionen är 4.10 varje natt och vi kommer att förlita oss på funktioner som stöds av den specifika versionen.

DataContract (grundläggande datastruktur):

Ett datakontrakt är inte standardterminologi. Det finns flera typer (mönster) av smarta kontrakt definierade i Monax (tidigare Eris industrier) dokumentation. Kontraktstypen “data” är ett enkelt koncept där data läggs till, uppdateras, tas bort och nås. Under processen att skapa datakontrakt kommer vi att kunna arbeta med ett ACL-kontrakt (Access Control List) som kan användas för att hantera rollbaserad säkerhet på alla typer av kontrakt, Eventing-mekanism för loggning och återlämnande av data och några andra funktioner i smarta kontrakt.

För att skapa ett enkelt datakontrakt antar du en användardefinierad datanivå på hög nivå för t.ex. Kunder

För att förenkla strukturerar vi en enkel kund som vi antar vara en individ:

strukturera kund {

uint id;

strängnamn;

uint dateOfBirth;

du är inte social;

uint status;

}

Datastatus

Vi implementerar strukturen med antagandet att varje datapost har status. Det är inte möjligt att ta bort och spela in och ordna om hela samlingen, så status är ett attribut som vi kommer att använda för att definiera ett tillstånd för posten. Kontrakt inom olika domäner kommer att ha en annan uppsättning status. Som ett enkelt antagande följer vi tre statuser (detta med tanken att en kund kan vänta på verifiering, aktiv eller kan raderas):

uint konstant aktiv = 1;

uint konstant väntar = 2;

uint konstant borttagen = 3;

En raderad post för alla referensdatatyper i en blockchain bör aldrig bli hårt raderad, så det är en lämplig designpraxis att tilldela en status till varje post.

Vårt mål är att möjliggöra en samling kundstrukturinstanser i blockchain och underlätta möjligheten att få tillgång till en specifik kund, listan över samtalskunder och uppdatera en specifik kundinstans. En övergripande oro för dessa mål är att möjliggöra loggning och implementering av en åtkomstkontrollstrategi.

För att skapa en samling använder vi kartläggningskonstruktionen.

mapping (uint => Kund) kunder;

mapping (uint => Kund) kunder;

Denna kartläggning är mallen för en kartliknande struktur som skapar en karta över nyckelvärden där nyckeln är ett osignerat int och värdet är en förekomst av en kund. Den här kartläggningen har vissa begränsningar, det vill säga att det inte finns något sätt att gå igenom den för att hämta alla värden. Vi kan bara komma åt elementen genom en specifik get-logik:

kunder [nyckel];

På grund av detta måste vi behålla en skuggnyckel för att bibehålla ett antal element i kartläggningen och hämta den baserat på räkningen.

offentlig uträkning = 0;

Nu har vi vår datastruktur redo att vi kommer att användas för att hysa kunddata.

Datakontrakt (dataskapande):

För att skapa en kundinstans och stänga av den implementerar vi en metod som accepterar beståndsdata.

funktion skapa kund (uint id, strängnamn, uint dateOfBirth, uint socialt) {

kunder [count] = Kund (id, namn, dateFödsel, socialt, väntande);

räkna ++;

}

Ovanstående metod lägger till data i kartläggningen och ökar antalet skuggnycklar. Vad som ska noteras är att vi använder samma skuggnyckel för att avstänga data.

För att få tillgång till data slumpmässigt måste vi tillhandahålla en specifik nyckel som vi har avstängt data mot.

funktion getCustomer (uint index)

konstant avkastning (uint id, strängnamn, uint dateOfBirth, uint socialt, uint status)

{

id = kunder [index] .id;

namn = kunder [index] .namn;

dateOfBirth = kunder [index] .dateOfBirth;

social = kunder [index] .social;

status = kunder [index] .status;

}

Den här metoden är konstant eftersom den inte ändrar tillståndet för kontraktsdata (det är en skrivskyddad metod). Så för att kalla denna metod behöver vi ingen gas.

För att komma åt alla kunder måste vi använda räkenskuggnyckeln. Vi måste implementera looping-strukturen på klienten och återanvända det indexbaserade samtalet ovan. Detta kommer att förklaras kontraktskundens förklaring.

För att komma åt kunden baserat på ett specifikt attribut i en struktur måste vi implementera en loopbaserad brute-sökning. Det finns effektivare sätt att läsa den genom att analysera transaktionen som var ansvarig för att skapa dessa data.

funktion getCustomerById (uint id)

konstant avkastning (uint idRet, strängnamn, uint dateOfBirth, uint socialt, uint status)

{

för (var i = 0; i< räkna; i ++)

{

if (kunder [i] .id == id) {

idRet = kunder [i] .id;

namn = kunder [i] .namn;

dateOfBirth = kunder [i] .dateOfBirth;

social = kunder [i]. social;

status = kunder [i] .status;

lämna tillbaka;

}

}

}

Detta är ett mycket ineffektivt sätt att hämta kunden från ett attributvärde. Det finns också andra problem med denna metod förutom ineffektivitet. Det är inte möjligt att enkelt matcha strängar i soliditet, så det är inte möjligt att matcha strängattribut. Det returnerar också den första matchen, det är inte möjligt att returnera en lista med matchningar. Vi kommer att gå in på mer effektiva metoder för att komma åt dessa data i senare delar av denna serie.

Datakontrakt (datauppdatering):

Uppdateringsdatametoden är helt enkelt omvänd från åtkomstmetoden. Det enda du måste komma ihåg är att den här metoden resulterar i en förändring för blockchain-tillståndet så att ändringarna bara kommer att återspeglas när transaktionen har bekräftats. Vi kommer att diskutera hur vi kan säkerställa att transaktionen bekräftas innan vi försöker få åtkomst till data i senare delen av vår serie.

function updateCustomer (uint index, string name) {

kunder [index] .namn = namn;

}

Det är vettigt att göra några kontroller för indexvärdet (det måste vara mindre än antalet)

function updateCustomer (uint index, string name) {

om (index > räkna) kasta;

kunder [index] .namn = namn;

}

funktionsuppdateringCustomerStatus (uint index, uint status) {

om (index > räkna) kasta;

kunder [index] .status = status;

}

Den olika metoden bör implementeras för att uppdatera varje attribut, här uppdaterar vi namnet. Metoden updateCustomerStatus () ska behandlas som en speciell metod som kan aktivera eller inaktivera poster.

Det är möjligt att lägga till samma kontroll på åtkomstmetoden som får åtkomst till indexnyckeln, men det är inte nödvändigt eftersom returen blir noll om det ogiltiga indexet tillhandahålls, så klienten ska kunna validera svaret och returnera lämpliga fel. Eftersom åtkomst skulle vara en vanligare metoduppsättning bör den göras så effektiv som möjligt.

Testa kontraktet:

För att testa kontraktet, gå till fliken miljö på höger panel (rutan ikonen).

Du kommer att se kontraktet listat till höger med alternativet att ange en adress (At Address) och ett alternativ att skapa. Välj alternativknappen VM för javascript (vald som standard och tryck på skapa). Detta skapar en lokal miljö i webbläsaren så att du kan utföra tester på ditt kontrakt och felsöka det.

Introduktion till fasthet: Skapa ett datakontrakt [Del 1]

Introduktion till fasthet: Skapa ett datakontrakt [Del 1]

Denna testmiljö ger dig möjlighet att ringa kontraktmetoder individuellt och se resultaten på data.

Till att börja med låt oss ringa metoden Create Contract för att lägga till lite data i blockchain (inte den riktiga än, men hån en).

Leta efter den röda markerade knappen med metoden call createCustomer och lägg till parametrar i textfältet bredvid den åtskilda av komma som om du ringer den här metoden via en javascriptklient. För t.ex. (För enkelhetens skull har vi valt dateOfBirth som enhetens tidsstämpel som kan passa in i en enhet)

För t.ex. (För enkelhetens skull har vi valt dateOfBirth som enhetens tidsstämpel som kan passa in i en enhet)

101, "Jack", 845078400, 1234567

Med den här parameteruppsättningen klickar du på skapa kund så visas följande utskrivna under samtalet:

Resultat: "0x"

Transaktionskostnad: 129390 gas.

Utförandekostnad: 106454 gas.

Detta kommer att indikera att metodanropet har lyckats, du kan bekräfta det genom att kontrollera antalet kunder genom att trycka på räkna-knappen (Metoden samtalsantal ()). Kom ihåg att soliditet exponerar sina offentliga medlemmar genom ett direkt samtal med signaturmedlemmen ().

Samtalet ska skriva ut ungefär som:

"0x00000000000000000000000000000000000000000000000000000000000000000002"

Transaktionskostnad: 21505 gas. (varning)

Utförandekostnad: 233 gas.

Avkodad:

uint256: 1

Denna uint256 har ett värde 1 som indikerar att du har en enda medlem i din inspelningsuppsättning.

Du kan köra ovanstående createCustomer-samtal flera gånger och verifiera resultatet. Observera att det inte finns någon kontroll av att lägga till dubbla poster. Detta måste kontrolleras av klienten.

Du kan hämta kunden med hjälp av den indexbaserade getCustomer (0) – kom ihåg att ditt index börjar med 0. Du bör se utdata så här:

Värde:

"0x000000000000000000000000000000000000000000000000000000000000006500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000325edf80000000000000000000000000000000000000000000000000000000000012d687000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000044a61636b00000000000000000000000000000000000000000000000000000000"

Transaktionskostnad: 23404 gas. (varning)

Utförandekostnad: 2004 gas.

Avkodad:

uint256 id: 101

strängnamn: Jack

uint256 dateOfBirth: 845078400

uint256 social: 1234567

uint256-status: 2

Värdet som returneras är den kodade data som returneras. Den avkodas och visas och parametervärdena i sekvens nedan.

Nu har du ett komplett arbetsavtal som har testats mot vissa testdata.

Det finns situationer när du kontrakt inte fungerar som förväntat, i vilket fall du måste felsöka kontraktet för att ta reda på tillståndet för kontraktsdata när metoden körs och identifiera problemet. Det finns för närvarande ingen soliditetsfelsökare. Det finns en soliditet IDE – Mix som har kapacitet, men den stöds för närvarande inte. Du kan testa det på egen risk.

Nu för att distribuera ditt kontrakt till en riktig ethereuminstans och ringa det med en enkel javascriptklient.

Implementering av kontraktet:

Du kan hänvisa till en tidigare artikel om hur man ställer in lokal ethereumnod med paritet. Vi kommer att använda den här möjligheten och anta att du har en lokal körande ethereum-instans som exponerar JSON_RPC-port 8545. Vi antar också att du har skapat ett konto och returneras på kontots [0] plats, även detta konto bör ha tillräckligt med etersaldo för att distribuera kontraktet och genomföra transaktionssamtal med gasavgifterna.

Remix IDE ger dig möjlighet att distribuera detta kontrakt direkt från IDE till ethereum-instansen. För att göra det måste du först välja alternativet Web3-leverantör på fliken Miljö. Om miljön för närvarande plockas upp ser du inget fel under kontraktet.

Screen_3 (Contract deploy option)

Introduktion till fasthet: Skapa ett datakontrakt [Del 1]

IDE ger dig tre resultat från kontraktsuppställningsprocessen BTW kontraktet sammanställs automatiskt. Se till att du ser alternativen som visas i skärm _3. annars betyder det att kompileringen misslyckades och du bör se kompileringsfelet.

Bytecode är EVM-koden som skapas när din kod sammanställs. Detta är instruktionsuppsättningen på låg nivå som ethereum förstår. Den andra är Application Binary interface eller ABI för kontraktskoden. ABI är bara en lista över metodunderskrifter, returtyper, medlemmar etc i kontraktet i ett definierat JSON-format. Detta ABI behövs när du kommer att ringa ditt kontrakt från en riktig javascriptklient.

Det tredje alternativet som Web3 distribuerar är alternativet som låter dig trycka kontraktet direkt på nodinstansen. Välj bara det här alternativet så ser du din kontraktsadress i blockchain tillbaka till dig .. (Gilla sreen_2). Den här kontraktsadressen är viktig eftersom den behövs i javascript-klienten som du snart kommer att skapa. Om du inte kan distribuera kontraktet direkt i blockchain från ethereum-konsolen. Kopiera bara skriptet i textområdet mot web3-distributionsalternativet och klistra in på konsolen. Du bör se tonkonsol.log-utdata med “kontrakt bryts” följt av dess adress i kedjan.

Köra kontraktet från en riktig kund.

Att integrera kontraktet med din företagskod. För att göra det skapar du en enkel javascript / html-klient som kan köras i webbläsaren. Du kan också köra den här klienten som ett nodjs-program. Det här är något jag kommer att täcka i de senare delarna av serien.

För att kommunicera med ethereum blockchain exponerar ethereum en låg nivå JSON-RPC gränssnitt. Detta gränssnitt accepterar transaktioner till kontraktet. Det är ett gränssnitt på mycket låg nivå så det är svårt att arbeta med det direkt. Det finns ett javascript-ramverk web3.js som möjliggör abstraktioner på högre nivå av kontraktskod för att applikationer ska kunna integreras med kontraktssamtal.

För att aktivera web3 i en webbläsarstödad miljö måste en enda skriptsfil refereras till i sidkoden för att interagera med kontraktet.

Web3.js finns att ladda ner från länkarna i dokumentationen som nämns ovan. Web3 genererar ett handtag för kontraktsinstans på ethereum för att möjliggöra alla metodsamtal som vi implementerade i vår soliditetskälla. Dessa metodanrop kan kodas som om det finns en direkt javaskriptreferens till metodskriptet. Detta aktiveras av JSON-RPC-gränssnittet.

Det finns en mallad metod för att få ett kontraktshantering. Det första som behövs är att starta web3 och leverera kontraktet ABI till det.

var Web3 = kräver (‘web3’);

var web3 = ny Web3 ();

web3.setProvider (“<span lang ="zxx"><a href ="http: // localhost: 8545 /">http: // localhost: 8545a>spänna>”);

web3.eth.defaultAccount = web3.eth.accounts [0];

Leverantörens webbadress är ditt lokala JSON_RPC-gränssnitt. Standardkontoinställningen är ethereum-plånboken som kommer att användas som från kontot när vi kommer att genomföra transaktionerna på kontraktet. Vi måste se till att kontot är upplåst om vi använder geth-nodinstans, eftersom kontot som standard låses var 30: e sekund efter att det har låsts upp.

Nästa steg är att starta kontraktsplanen genom att leverera kontraktet ABI så web3.

var customerContract = web3.eth.contract ([ABI JSON]).

ABI JSON-matrisen är vanligtvis en lång JSON-sträng så vi omformulerar bara, men du borde kopiera hela ABI-matrisen från gränssnittstextområdet som visas på skärm3. När du har ritat kundkontraktet måste vi starta det genom att ange den riktiga adressen där kontraktet finns i blockchain.

var customerContractObject = customerContract.at (‘0x76bd9986c5c3e00111c82e16e01e282696d2b3fb’);

Den här adressen skulle vara vad du fick när du distribuerade kontraktet från web3-distributionen eller från ethereum-konsolen. När du har länkat kontrakthanteringen tillbaka till distributionsadressen kan du utföra kontraktsmetoder genom att skicka transaktioner till adressen. Låt oss till exempel säga att du vill lägga till kundposter efter att ditt html-formulär accepterar ingångar för formulärvärdena från användaren, då ser din html + web3-kod ungefär så ut:

<html>

<huvud>

<länk rel = ”stylesheet” typ = ”text / css” href = ”style.css”>

<skript typ = ”text / javascript” src = ”/ usr / local / lib / node_modules / web3 / dist / web3.js”><skript typ = ”text / javascript” src = ”jquery.js”>manus>

<skripttyp = ”text / javascript”>

var Web3 = kräver (‘web3’);

var web3 = ny Web3 ();

web3.setProvider (ny web3.providers.HttpProvider ()); // detta är för standard – localhost: 8545

web3.eth.defaultAccount = web3.eth.accounts [0];

var customerContract = web3.eth.contract ([ABI JSON]);

var customerContractObject = customerContract.at (‘0x76bd9986c5c3e00111c82e16e01e282696d2b3fb’);

funktionsregister () {

var txn = customerContractObject.createCustomer ($ (‘id’). val (), $ (‘name’). val (), $ (‘dob’). val (), $ (‘social’). val () , {gas: 144840});

console.log (txn);

}

manus>

huvud>

<kropp>

<inmatningstyp = ”nummer” namn = ”id” id = ”id” platshållare = ”Kund-id” />

<inmatningstyp = ”text” namn = ”namn” id = ”namn” platshållare = ”Kundnamn” />

<inmatningstyp = ”datum” namn = ”dob” id = ”dob” platshållare = ”Kund födelsedatum” />

<inmatningstyp = ”nummer” namn = ”socialt” id = ”socialt” platshållare = ”Kundens personnummer” />

<ingångstyp = ”knapp” värde = ”Registrera” onclick = ”registrera ();” />

kropp>

html>

Ovanstående kod fungerar ur rutan om du fixar sökvägen till web3.js och jquery. Precis som vi har kallat metoden på kontrakthandtaget:

var txn = customerContractObject.createCustomer ($ (‘id’). val (), $ (‘name’). val (), $ (‘dob’). val (), $ (‘social’). val () , {gas: 144840});

Det är möjligt att anropa alla andra metoder. Den beräknade gasen måste anges i testmetodsanropen, detta är 144840 i min konfiguration. Ovanstående samtal returnerar ett transaktions-ID för transaktionen som skapas i blockchain för att utföra denna metod. Denna transaktion är nu en del av blockchain och kan hänvisas till när vi vill granska när, hur och av vem skapades denna kund.

Det finns två typer av samtal, som vi har sett under kodningen av kontraktet. En som uppdaterar kontraktets tillstånd som createCustomer, updateCustomer etc. Och andra som är skrivskyddade och är markerade som konstanta. Den förstnämnda returnerar alltid en transaktion Id-hash, transaktion Id-hash är en 64 byte-identifiering av transaktionen som kan användas för att hänvisa till transaktionen. Om vi ​​kör kontraktet på ett synkront sätt som vi gör här. Den senare returnerar de faktiska värdena som söks i en kommaseparerad matris. Till exempel samtalet:

var kund = customerContractObject.getCustomer ($ (‘index’). val ());

console.log (kund)

Loggar en rad värden så här – 101, "Jack", 845078400, 1234567

I nästa del av serien kommer vi att se hur vissa icke-funktionella problem och aspekter är inbyggda i den kontraktsliknande åtkomstkontrollen, händelseloggar, borttagning av kontrakt. Vi kommer att diskutera delar av kontraktet som specifikt behandlar dessa frågor.

Mike Owergreen Administrator
Sorry! The Author has not filled his profile.
follow me