Sådan redder du dine Ethereum DApp-brugere fra at betale gas for transaktioner

I stedet betaler du som DApp-ejer for det

Crosspost: Dette indlæg blev oprindeligt offentliggjort her. Og blev sendt med forfatteren, Mahesh Murthys tilladelse. [Lær mere på Zastrin.com. Bonus: Brug kode “BlockChannel” for at spare 50% på alle kurser.]

Et af friktionspunkterne for vedtagelse af Ethereum dapp er, at brugerne skal betale et gebyr for gas (transaktion (txn)) for at få deres transaktioner registreret på blockchain. For eksempel har jeg en simpel afstemning, der lader nogen stemme for kandidater, og stemmerne gemmes på blockchain. En bruger, der ønsker at optage sin stemme om blockchain, skal betale en transaktion / gasgebyr. Dette er ikke ideelt, fordi du som dappejer forventer, at dine applikationsbrugere skal have Ether til at betale for gas, når alt, hvad de vil gøre, er at udføre en simpel handling, der ikke har noget at gøre med at overføre penge. Men hvis transaktionen skal udføres på blockchain, er der ingen anden mulighed end at betale gebyret. Hvad hvis der var en måde for brugere at udføre transaktioner sikkert (stemme på en kandidat, som i vores eksempel) og lade en anden (potentielt kontraktsejeren) registrere transaktionen på blockchain og selv betale for den?

Takket være denne tweet fra John Backus, havde jeg lige nok information til at hjælpe mig med at implementere en sådan løsning til min afstemning dapp.

Jeg ønskede at dele detaljer om, hvordan jeg implementerede denne løsning til min enkle dapp, så flere mennesker kan anvende denne teknik i deres egne dapps og forhåbentlig kunne forbedre den. Dette indlæg dækker følgende:

  1. Et meget højt overblik over kryptografi af offentlig nøgle og digitale signaturer, der er nøglen til at forstå denne løsning.
  2. Løsningsdetaljerne og den nye applikationsstrøm.
  3. Implementeringsdetaljer (frontend js og soliditetskontraktkode).
  4. Diskuter potentielle problemer og forbedringer.

Digitale signaturer

For at denne løsning skal være fornuftig, har du brug for en grundlæggende forståelse af, hvordan digitale signaturer fungerer i kryptografi. Du er velkommen til at springe dette afsnit over, hvis du kender kryptografi med offentlig nøgle. Jeg vil forsøge at forklare begrebet offentlige / private nøgler og digitale underskrifter på et meget højt niveau, men jeg anbefaler stærkt at lære mere detaljeret - wikipedia er et godt sted at starte.

Offentlig nøglekryptografi er et kryptografisk system, hvor du har 2 nøgler - offentlig nøgle (Pu) og en privat nøgle (Pr). Du giver din offentlige nøgle til hele verden og holder den private nøgle til dig selv. Eks: Din Ethereum-adresse er en offentlig nøgle (Den er faktisk afledt af offentlig nøgle, men for denne øvelse, lad os bare tænke på den som offentlig nøgle), og din private nøgle gemmes enten i din browser eller på din telefon / computer. Som du ved, for at nogen skal sende dig Ether, skal de bare kende din offentlige (konto) adresse. Dog er det kun du, der har adgang til de midler, du ejer, fordi du er den eneste, der kender din private nøgle.

Kryptografi med offentlig nøgle har algoritmer, der lader dig kryptere, dekryptere, underskrive og verificere beskeder ved hjælp af dit nøglepar.

Lad os se, hvad signering og bekræftelse af en meddelelse betyder gennem et eksempel. Lad os sige, at bruger Kim har et par offentlige / private nøgler

Pu = “0x44ac12c1e3dfd8edaf83b6f65918229d5279a6f5”

Pr = “dbc226043e390cf39280e5edfd418d7ad61931c76509270867d300f110c46506”

For at underskrive en meddelelse udfører Kim et funktionstegn (“Stem på Alice”, Pr), der udsender en alfanumerisk streng

signatur = 0x9127112de0033555c7f6508d963d484965a953844dfcff092712102c236467a25af57edc53b63880ea39af8ce7334f6d77a8206e805305e7c6ad919d12bfae5c1b

Dette er den digitale signatur af meddelelsen “Stem på Alice” underskrevet af Kim ved hjælp af sin private nøgle Pr.

Nu kan enhver bekræfte, at meddelelsen "Stem på Alice" blev underskrevet af Kim ved at udføre verificeringsfunktionen, verificere ("Stem på Alice", signatur), der udsender "0x44ac12c1e3dfd8edaf83b6f65918229d5279a6f5". Hvis du bemærker, at output er Kims offentlige nøgle Pu (husk, alle ved, at det er Kims offentlige nøgle), hvilket betyder, at meddelelsen bestemt blev underskrevet af Kim. Hvis du manipulerer med signaturen eller beskeden (ved at ændre endda et tegn), udsender bekræftelsesalgoritmen en helt anden offentlig nøgle, og du vil vide, at beskeden blev manipuleret, fordi den offentlige nøgle er forskellig fra Pu.

Løsningsdetaljer

Hvis du forstår digitale signaturer, er løsningen ekstremt triviel. Lad os se, hvordan det kan bruges i vores stemmeapplikation til at redde brugere fra at betale gasgebyr uden at gå på kompromis med deres stemme. Nedenfor kan du se alle brugere af dapp og de handlinger, de udfører.

  1. En vælger angiver deres intention om at stemme for en kandidat ved at underskrive en besked ved hjælp af deres private nøgle. De sender ikke deres transaktion til blockchain, så der betales ikke noget txn-gebyr. Meddelelseskøen i diagrammet ovenfor er bare en placering uden for kæden, hvor alle afstemningsoplysninger er gemt.
  2. Enhver, der er villig til at betale txn-gebyret (normalt kontraktsejeren), tager underskrift, kandidatnavn og vælgerens konto-adresse og sender dem til blockchain.
  3. Den smarte kontrakt bruger bekræftelsesfunktionen til at udlede den offentlige nøgle (Ethereum-kontoadresse) baseret på kandidatens navn og underskrift. Hvis den afledte offentlige nøgle svarer til adressen på den bruger, der har underskrevet meddelelsen, registrerer den afstemningen ellers mislykkes transaktionen.

Implementeringsdetaljer

Lad os nu se på den faktiske implementering, og hvordan alle brikkerne passer sammen.

Trin 1: Signer beskeden

Det første trin er at underskrive beskeden som vælger. Vi bruger eth_signTypedData-funktionen til at underskrive vores meddelelse. Denne funktion er implementeret i Metamask, hvilket gør det virkelig let at underskrive meddelelser. Du kan finde flere detaljer og diskussioner om dette forslag her: https://github.com/ethereum/EIPs/pull/712. Du kan finde koden til at underskrive beskeden nedenfor.

En virkelig vigtig ting at bemærke er, internt eth_signTypedData hascher meddelelsen, og den hashede meddelelse er, hvad der bliver underskrevet. Du kan henvise til typedSignatureHash-funktion her for at få flere oplysninger om hashing.

Trin 2: Indsend den underskrevne afstemning til blockchain

Da dette kun er en demo-applikation, gemmer vi ikke signaturen og andre detaljer overalt. Det vises direkte på siden, efter at meddelelsen er underskrevet. Alle kan tage disse detaljer og sende til blockchain. Her er koden, der sender afstemningen til blockchain:

Trin 3: Kontroller afstemningsoplysningerne i den smarte kontrakt

Vi verificerer nu i den smarte kontrakt, hvis de indsendte afstemningsinfo er gyldige, og vi registrerer derefter afstemningen.

Zeppelin har et praktisk bibliotek kaldet ECRecovery, som vi kan bruge til at bekræfte den underskrevne meddelelse. Funktionen voteForCandidate verificerer den underskrevne meddelelse (gendannelsesfunktion) og opdaterer afstemningen, hvis verifikationen lykkes.

Hvis du husker det, nævnte jeg tidligere, at eth_signTypedData hashes meddelelsen ("Stem på Alice"), før du underskrev den? Funktionen til gendannelse af soliditet har ikke nogen viden om hashfunktionen, der bruges i eth_signTypedData, og den kan derfor ikke bekræfte meddelelsen "Stem på Alice". Det skal generere hash for meddelelsen "Stem på Alice" og derefter bekræfte den. I stedet for at generere hash inde i kontrakten, forhåndsbestiller vi alle meddelelser på forhånd og videresender dem i konstruktøren, så det er let at slå op, når det verificeres. Koden til generering af hash er i migrationsfilen nedenfor

Det er al den kode, du har brug for for at få den nye applikation til at fungere!

Jeg oprettede en hurtig demo for at vise, hvordan denne applikation fungerer

Hele arbejdskoden er her: https://github.com/maheshmurthy/ethereum_voting_dapp/tree/master/chapter4

Demo-applikationen er her: https://www.zastrin.com/voting-dapp-without-paying-gas.html

Potentielle problemer, der skal løses

Der er et par spørgsmål, man skal overveje, når man bygger en rigtig dapp ved hjælp af denne teknik. Nogle af dem er anført nedenfor:

  1. Hvor gemmes de underskrevne meddelelser? Du kan bruge et slags køsystem til at gemme disse meddelelser.
  2. Hvad er garantien for, at den underskrevne besked til sidst sendes til blockchain?
  3. Det er ikke ideelt at gemme hash for alle meddelelser i blockchain, så hvad er den bedste løsning til det?

Hvis du har tanker om, hvordan du løser disse problemer, eller hvis du ser nogen fejl i denne løsning, skal du skrive en kommentar!

Bemærk: Eth_signTypedData API er tilsyneladende stadig ikke stabil og er kun implementeret af metamask. Vær opmærksom på dette, hvis du planlægger at bruge denne teknik i mainnet / produktion.

Yderligere læsning

https://en.wikipedia.org/wiki/Public-key_cryptography

https://en.wikipedia.org/wiki/Digital_signature

https://github.com/danfinlay/js-eth-personal-sign-examples/

https://danfinlay.github.io/js-eth-personal-sign-examples/

https://github.com/ethereum/EIPs/pull/712

Tak Chris Whinfrey og Febin John James for gennemgangen af ​​udkast til denne artikel.

Lær mere

Hvis du er interesseret i at lære at opbygge Ethereum decentraliserede applikationer, har jeg et par interessante kurser på www.zastrin.com