Decentral applikationsarkitektur: Back End, sikkerhed og designmønstre

Decentrale applikationer eller ÐApps kræver et specielt systemdesign for at opnå høj sikkerhed og pålidelighed. I denne artikel vil jeg dække flere hovedprincipper for, hvordan man korrekt designer og implementerer backend- og smarte kontrakter til decentrale applikationer, idet jeg tager Ethereum som et primært eksempel, selvom meget af det vil gælde for EOS, Tron og andre decentrale dataplatforme.

Artikel Højdepunkter :

  • Sådan opbevares private nøgler på bagsiden uden sikkerhedsproblemer
  • Sådan designes smarte kontrakter korrekt, og hvad man skal "decentralisere"
  • Eksempler på decentraliseret og semicentral applikationsarkitektur
  • Sådan håndteres ting på lavt niveau som netværksbelastning og fejl

Det bliver stort, lad os gøre det!

Decentrale programmer og Blockchain

På trods af at blockchain står over for mange adoptions- og reguleringsproblemer i dag, er det en slags teknologi, der er kommet for at blive, uanset om det er blockchain, hashgraph, tempo eller enhver anden distribueret ledgerteknologi, der stadig kommer, uanset algoritmen.

Den vigtigste værdi, som blockchain og andre lignende teknologier bringer, kan generaliseres som følger: de giver folk mulighed for at skrive og køre programmer, der praktisk talt ikke kan ændres efter oprettelsen eller manipuleres med dem under udførelsen. Med andre ord kører disse programmer altid som designet, og ingen enkelt part kan påvirke deres adfærd.

Denne definition er gyldig for mange kryptokurver, der findes i dag, hvis vi betragter dem som programmer, der definerer, hvordan mønter kan overføres frem og tilbage. Dette forklarer også, hvorfor kryptokurver og mange slags tokens har reel værdi: de kan ikke genereres ud af luften ved hjælp af deres definerede "underliggende programmer".

Ethereum / EOS / Tron /… -platforme implementerer i modsætning til Bitcoin et mere komplekst programlag, som igen implementerer eksekveringsmiljøet, der gør det muligt for enhver at skrive deres egne decentrale programmer oven på platformen. Disse brugerdefinerede programmer kører altid som designet uden undtagelser, og deres sikkerhed garanteres af platformen.

Decentrale applikationer

Disse sikre og uforanderlige programmer, der kører på et decentraliseret netværk i kombination med traditionelle front-end og back-end-teknologier, er det, vi kalder decentrale applikationer (ÐApps) i dag. Gennem nogle af dem kan være semi-centraliserede, en stor del af aktiviteterne i den virkelig decentrale anvendelse skal ske uden for en central parts kontrol.

For at forestille dig, hvad vi kalder decentrale applikationer i dag, skal du tage enhver eksisterende centraliseret webressource som _YouTube_ eller _Instagram_ som et eksempel og forestille dig, at du i stedet for en adgangskodebeskyttet central konto har din " kryptoidentitet " bundet til web / mobilressourcen.

Det er hvad Wallet Software giver dig. Den private nøgle fra denne identitet (en hemmelighed, hvor du kan handle på vegne af denne identitet) er gemt på din lokale enhed og går aldrig online, hvilket gør ingen i stand til at kontrollere denne identitet undtagen dig. Med denne identitet kan du udføre forskellige handlinger i både centraliserede (webressourcer kontrolleret af en central myndighed) og decentraliserede (hvilket er et andet netværk end det traditionelle www, hvis mål er at eliminere den centrale myndigheds) netværk ved hjælp af hjemmesiden som et adgangspunkt og / eller som en grafisk brugergrænseflade. Hele pointen med denne "kryptoidentitet" er, at dine handlinger er kryptografisk sikret, og ingen er i stand til at ændre, hvad du har underskrevet eller din signatur.

I dag er beregnings- og lagringsfunktionerne for fejltolerante decentrale netværk som Ethereum, EOS eller Tron begrænsede. Hvis de var skalerbare, kunne vi bruge decentrale netværk til at gemme hele den decentrale applikation, inklusive dens grafiske brugergrænseflade, data og forretningslogik. I dette tilfælde vil vi kalde disse applikationer virkelig decentrale / distribuerede.

Men fordi disse netværk ikke er skalerbare i dag, kombinerer vi forskellige tilgange for at opnå det maksimale decentraliseringsniveau for vores applikationer. Den “traditionelle” bagende, som vi ved, går ikke nogen steder. For eksempel:

  • Vi bruger back-end til at hoste frontend til en decentral applikation.
  • Vi bruger backend til integration med andre eksisterende teknologier og tjenester. Reelle applikationer i verdensklasse kan ikke leve i et isoleret miljø.
  • Vi bruger back-end til at gemme og behandle alt, der er stort nok til et decentraliseret netværk (især blockchain). Praktisk set er hele applikationen og dens forretningslogik gemt et eller andet sted i verden, undtagen kun blockchain-delen. For ikke at nævne, kan IPFS og lignende lagring ikke garantere tilgængeligheden af ​​filer, derfor kan vi heller ikke stole på dem uden at være vært for filerne selv. Med andre ord er der altid et behov for en dedikeret kørende server.

Der er ingen måde at opbygge en sikker og delvist decentraliseret applikation uden at bruge en solid bagende fra i dag, og hele pointen med denne artikel er at forklare, hvordan man gør dette rigtigt.

(De) centralisering og poletter

Det sker således, at næsten alle decentrale applikationer i dag er bygget op omkring såkaldte tokens - specialbyggede (eller bare klonede) kryptokurver, der driver en bestemt decentral applikation. Tokens er simpelthen en programmerbar valuta eller aktiver, det er det.

Normalt er et token en "smart kontrakt" (et brugerdefineret program) skrevet oven på den decentrale platform som Ethereum. Ved at eje nogle tokens er du dybest set i stand til at få forskellige tjenester på en webressource eller mobilapp og bytte dette token til noget andet. Nøglepunktet her er, at symbolet lever alene og ikke styres af en central myndighed.

Der er mange eksempler på applikationer, der er bygget op omkring tokens: fra adskillige samleobjekter som CryptoKitties (ERC721-tokens) til mere serviceorienterede apps som LOOM Network eller endda browsere som Brave og spilplatforme som DreamTeam (ERC20-kompatible tokens).

Udviklere bestemmer selv og beslutter, hvor meget kontrol de vil (eller ikke vil) have over deres applikationer. De kan bygge hele applikationens forretningslogik oven på smarte kontrakter (som CryptoKitties gjorde), eller de kan slet ikke bruge smarte kontrakter ved at centralisere alt på deres servere. Den bedste tilgang er dog et sted i midten.

Back End til decentrale netværk

Fra et teknisk synspunkt skal der være en bro, der forbinder tokens og andre smarte kontrakter med web- / mobilapplikationen.

I nutidens fuldt decentrale applikationer, hvor klienter interagerer med smarte kontrakter direkte, indsnævres denne bro til en JSON RPC API-kapacitet af offentlige API'er eller nodepuljer som Infura, som igen er tvunget til at eksistere på grund af det faktum, at ikke alle enheder kan køre og understøtte sin individuelle netværksnode. Imidlertid giver denne API et eneste grundlæggende og meget snævert sæt funktioner, som næppe tillader at lave enkle forespørgsler eller effektivt samle data. På grund af dette, til sidst, brugerdefinerede bagenden spark i, hvilket gør applikationen semi-centraliseret.

Hele interaktionen med det decentrale netværk kan indsnævres til kun et eller to punkter afhængigt af applikationsbehovet:

  1. Lytte til netværkshændelser (som tokenoverførsler)/ læser netværkstilstanden .
  2. Offentliggørelsestransaktioner (påberåbte statsændrende smarte kontraktfunktioner som tokenoverførsel).

Implementering af begge disse punkter er ret vanskelig, især hvis vi vil opbygge en sikker og pålidelig back-end-løsning. Her er de vigtigste punkter, som vi skal nedbryde nedenfor:

  • Først og fremmest i Ethereum er hentning af begivenheder ikke produktionsklar med det samme. På grund af flere årsager: netværksnoder kan mislykkes, mens der hentes et stort antal begivenheder, begivenheder kan forsvinde eller ændre sig på grund af netværksgafler osv. Vi er nødt til at opbygge et abstraktionslag for at synkronisere begivenheder fra netværket og garantere deres pålidelige levering.
  • Det samme for offentliggørelse af transaktioner er vi nødt til at abstrakte Ethereums ting på lavt niveau som nonce-tællere og gasestimater samt genudgivelse af transaktioner, hvilket giver en pålidelig og stabil grænseflade. Desuden indebærer transaktionsudgivelse brug af private nøgler, hvilket kræver avanceret back-end sikkerhed.
  • Sikkerhed. Vi vil tage det alvorligt og se, at det er umuligt at garantere, at private nøgler aldrig bliver kompromitteret på en back-end. Heldigvis er der en tilgang til at designe en decentral applikation uden engang behov for back-end-konti for at være meget sikret.

I vores praksis fik alt dette os til at skabe en robust back-end-løsning til Ethereum, som vi navngiver Ethereum Gateway . Det abstraherer andre mikrotjenester fra Ethereums sjov og giver en pålidelig API til at arbejde med det.

Som en hurtigt voksende opstart kan vi ikke afsløre den komplette løsning (lige endnu) af åbenlyse grunde, men jeg vil dele alt, hvad du har brug for at vide, for at få din decentrale applikation til at fungere fejlfrit. Men hvis du har specifikke spørgsmål eller spørgsmål, er du velkommen til at kontakte mig. Kommentarer til denne artikel er også meget værdsat!

Decentraliseret applikationsarkitektur

Denne del af artiklen afhænger meget af behovene for en bestemt decentral applikation, men vi vil forsøge at sortere nogle grundlæggende interaktionsmønstre, som disse applikationer er bygget på (ÐPlatform = Decentral platform = Ethereum / EOS / Tron / Whatever):

Klient ⬌ ÐPlatform : fuldt decentrale applikationer .

Klienten (browser eller mobilapplikation) taler direkte til den decentrale platform ved hjælp af Ethereum “tegnebog” -software som Metamask, Trust eller hardware-tegnebøger som Trezor eller Ledger. Eksempler på DApps opbygget på en sådan måde er CryptoKitties, Loom's Delegated Call, selve crypto-tegnebøger (Metamask, Trust, Tron Wallet, andre), decentraliserede crypto-udvekslinger som Etherdelta og så videre.

ÐPlatformKlientBack EndÐPlatform : centraliserede eller semicentraliserede applikationer .

Klientens interaktion med den decentrale platform og serveren har meget lidt til fælles. Det gode eksempel på dette er enhver ( central ) kryptobørs i dag, som BitFinex eller Poloniex: de valutaer, du handler på børser, registreres simpelthen i den traditionelle database. Du kan "fylde op" din databasesaldo ved at sende aktiver til en bestemt adresse (ÐPlatform ⬌ Client) og derefter trække aktiver ud efter nogle handlinger i appen (Back End ⬌ ÐPlatform), dog alt hvad du gør i form af en "ÐApp" sig selv (Client ⬌ Back End) betyder ikke din direkte interaktion med ÐPlatform.

Et andet eksempel er Etherscan.io, der bruger semi-centraliseret tilgang: du kan udføre alle nyttige decentrale handlinger der, men selve applikationen giver bare ikke mening uden deres omfattende back-end (Etherscan synkroniserer løbende transaktioner, analyserer data og gemmer det, i sidste ende leverer en omfattende API / UI).

Noget imellem: stadig, centraliserede eller semicentraliserede applikationer .

Ovenstående fremgangsmåder kombineret. For eksempel kan vi have en applikation, der leverer forskellige tjenester i bytte for krypto, så du kan logge ind og underskrive oplysninger med din kryptoidentitet.

Forhåbentlig rejser interaktionsmønsteret for fuldt decentrale applikationer (Client ⬌ ÐPlatform) ingen spørgsmål. Ved at stole på sådanne fantastiske tjenester som Infura eller Trongrid kan man simpelthen bygge en applikation, der slet ikke kræver en server. Næsten alle klientsidesbiblioteker som Ethers.js for Ethereum eller Tron-Web for Tron kan oprette forbindelse til disse offentlige tjenester og kommunikere med netværket. For mere komplekse forespørgsler og opgaver skal du dog alligevel allokere din egen server.

Resten af ​​interaktionsmønstre, der involverer bagenden, gør tingene mere interessante og komplekse. For at sætte alle disse på et billede, lad os forestille os et tilfælde, hvor vores bagende reagerer på en begivenhed i netværket. For eksempel offentliggør brugeren en kvotetransaktion, som giver os tilladelse til at opkræve dem. For at foretage et gebyr skal vi offentliggøre gebyrtransaktionen som reaktion på den udsendte tillægshændelse:

Set bagfra er der hvad der sker:

  1. Vi lytter til en bestemt netværksbegivenhed ved løbende at afstemme netværket.
  2. Når vi først har fået en begivenhed, udfører vi en vis forretningslogik og beslutter derefter at offentliggøre en transaktion som svar.
  3. Før transaktionen offentliggøres, vil vi sikre, at den sandsynligvis vil blive udvundet (i Ethereum betyder den vellykkede transaktionsgasestimering, at der ikke er fejl i forhold til den aktuelle netværkstilstand ). Vi kan dog ikke garantere, at transaktionen bliver udvundet med succes .
  4. Ved hjælp af en privat nøgle underskriver og offentliggør vi transaktionen. I Ethereum skal vi også bestemme transaktionens gaspris og gasgrænse.
  5. Efter offentliggørelse af transaktionen afstemmer vi løbende netværket for dets status.
  6. Hvis det tager for lang tid, og vi ikke kan få transaktionens status, er vi nødt til at genudgive den eller udløse et "fail-scenario". Transaktioner kan gå tabt af forskellige årsager: overbelastning i netværket, faldende jævnaldrende, stigning i netværksbelastning osv. I Ethereum kan du også overveje at genunderskrive en transaktion med en anden (faktisk) gaspris.
  7. Når vi endelig får min transaktion udvundet, kan vi udføre mere forretningslogik, hvis det er nødvendigt. For eksempel kan vi give andre back-end-tjenester besked om, at transaktionen er afsluttet. Overvej også at vente på et par bekræftelser, inden du træffer endelige beslutninger vedrørende transaktionen: Netværket distribueres, og resultatet kan derfor ændre sig på få sekunder.

Som du kan se, sker der meget! Imidlertid kræver din ansøgning muligvis ikke nogle af disse trin, afhængigt af hvad du prøver at opnå. Men at opbygge en robust og stabil bagende kræver en løsning på alle ovennævnte problemer. Lad os nedbryde dette.

Decentrale applikationer Back End

Her vil jeg fremhæve nogle af de punkter, der opstår de fleste af spørgsmålene, nemlig:

  • Lytte til netværkshændelser og læse data fra netværket
  • Offentliggørelse af transaktioner og hvordan man gør det sikkert

Lytte til netværkshændelser

I Ethereum såvel som i andre decentrale netværk tillader et koncept med smarte kontraktbegivenheder (eller hændelseslogfiler eller bare logfiler) off-chain-applikationer at være opmærksomme på, hvad der sker i blockchain. Disse begivenheder kan oprettes af smarte kontraktudviklere når som helst i smartkontraktskoden.

For eksempel skal inden for den velkendte ERC20-tokenstandard hver tokenoverførsel logge overførselshændelsen og således lade off-chain-applikationer vide, at der er sket en tokenoverførsel. Ved at "lytte" til disse begivenheder kan vi udføre (gen) handlinger. For eksempel sender nogle mobile krypto-tegnebøger dig en push / e-mail-meddelelse, når tokens overføres til din adresse.

Faktisk er der ingen pålidelig løsning til at lytte til netværkshændelser ud af kassen. Forskellige biblioteker giver dig mulighed for at spore / lytte til begivenheder, men der er mange tilfælde, hvor noget kan gå galt, hvilket resulterer i tabte eller ubehandlede begivenheder. For at undgå at miste begivenheder er vi nødt til at oprette en brugerdefineret back-end, der opretholder begivenhedssynkroniseringsprocessen.

Afhængigt af dine behov kan implementeringen variere. Men for at sætte dig i et billede her er en af ​​mulighederne for, hvordan du kan opbygge pålidelig levering af Ethereum-begivenheder med hensyn til mikroservicearkitektur:

Disse komponenter fungerer på følgende måde:

  1. Begivenhedssynkroniseringstjeneste afstemmer konstant netværket og forsøger at hente nye begivenheder. Når der er nogle nye begivenheder til rådighed, sender den disse begivenheder til meddelelsesbussen. Ved vellykket indsendelse af begivenhed til meddelelsesbussen, som for blockchain, kan vi gemme den sidste begivenheds blok for at anmode om nye begivenheder fra denne blok næste gang. Husk, at hentning af for mange begivenheder på én gang kan resultere i altid mislykkede anmodninger, så du er nødt til at begrænse antallet af begivenheder / blokke, du anmoder om fra netværket.
  2. Meddelelsesbussen (for eksempel Rabbit MQ) dirigerer begivenheden til hver kø, der blev opsat individuelt for hver backend-service. Før begivenhedsudgivelse specificerer begivenhedssynkroniseringstjeneste routingnøglen (for eksempel en smart kontraktadresse + begivenhedsemne), mens forbrugere (andre backendtjenester) opretter køer, der kun abonnerer på bestemte begivenheder.

Som et resultat får hver backend-tjeneste kun de begivenheder, den har brug for. Desuden garanterer meddelelsesbussen levering af alle begivenheder, når de er offentliggjort for den.

Selvfølgelig kan du bruge noget andet i stedet for meddelelsesbussen: HTTP-tilbagekald, sockets osv. I dette tilfælde skal du selv finde ud af, hvordan du garanterer levering af tilbagekald: administrer eksponentielle / brugerdefinerede tilbagekaldsforsøg, implementer brugerdefineret overvågning og snart.

Publiceringstransaktioner

Der er et par trin, vi skal udføre for at offentliggøre en transaktion til det decentrale netværk:

  1. Forbereder transaktionen. Sammen med transaktionsdata indebærer dette trin at anmode om netværketilstand for at finde ud af, om denne transaktion er gyldig og vil blive udvundet (gasestimering i Ethereum) og transaktionens løbenummer (nonce i Ethereum). Nogle af bibliotekerne prøver at gøre dette under emhætten, men disse trin er vigtige.
  2. Undertegner transaktionen. Dette trin indebærer brugen af ​​den private nøgle. Mest sandsynligt vil du her integrere den tilpassede løsning til samling af private nøgler (for eksempel).
  3. Offentliggørelse og genudgivelse af transaktionen. Et af nøglepunkterne her er, at din offentliggjorte transaktion altid har en chance for at gå tabt eller droppe fra det decentrale netværk. For eksempel i Ethereum kan den offentliggjorte transaktion droppes, hvis netværkets gaspris pludselig stiger. I dette tilfælde skal du genudgive transaktionen. Desuden vil du muligvis genudgive transaktionen med andre parametre (i det mindste med højere gaspris) for at få den udvundet så hurtigt som muligt. Således kan genudgivelse af transaktionen indebære genunderskrivelse af den, hvis udskiftningstransaktionen ikke blev underskrevet før (med forskellige parametre).

Ved at bruge ovenstående tilgange kan du ende med at opbygge noget, der ligner det, der er præsenteret i sekvensdiagrammet nedenfor. På dette specifikke sekvensdiagram viser jeg (generelt!) Hvordan blockchain tilbagevendende fakturering fungerer (der er mere i en linket artikel):

  1. Brugeren udfører en funktion i en smart kontrakt, som i sidste ende gør det muligt for backenden at udføre en vellykket gebyrtransaktion.
  2. En backend-tjeneste, der er ansvarlig for en bestemt opgave, lytter til begivenhedens tillæg og offentliggør en gebyrtransaktion.
  3. Når afgiftstransaktionen er udvundet, modtager denne back-end-tjeneste, der er ansvarlig for en bestemt opgave, en begivenhed fra Ethereum-netværket og udfører en vis logik (inklusive indstilling af den næste opladningsdato).

Back End-sikkerhed og smarte kontrakter

Transaktionspublicering indebærer altid brug af en privat nøgle . Du undrer dig måske over, om det er muligt at holde private nøgler sikre. Nå ja og nej. Der er adskillige komplekse strategier og forskellige typer software, der gør det muligt at gemme private nøgler på bagsiden ganske sikkert. Nogle private nøgleopbevaringsløsninger bruger geodistribuerede databaser, mens andre endda foreslår brug af speciel hardware. Under alle omstændigheder er det mest sårbare punkt i en semicentral applikation, hvor den private nøgle samles og bruges til at underskrive en transaktion (eller i tilfælde af speciel hardware et punkt, der udløser en transaktionssigneringsprocedure). Derfor er der teoretisk ingen 100% pålidelig løsning, der muliggør kuglesikker beskyttelse mod at kompromittere lagrede private nøgler.

Tænk nu sådan. I mange tilfælde behøver du ikke engang at sikre private nøgler på bagsiden så ofte. I stedet kan du designe smarte kontrakter og hele applikationen på en sådan måde, at en privat nøglelækage ikke påvirker deres sædvanlige opførsel . Med denne tilgang betyder det ikke noget, hvordan autoriserede konti interagerer med den smarte kontrakt. De “udløser” bare en smart kontrakt til at udføre sit sædvanlige job, og den smarte kontrakt udfører selv den krævede validering. Jeg kalder det ”operationelle regnskabsmønstre”.

På denne måde i nødstilfælde:

  • Det eneste, angriberen kan stjæle, er en lille mængde ether (fra Ethereum) deponeret på de operationelle konti til transaktionsudgivelse
  • Angriberen kan ikke skade den smarte kontraktlogik eller nogen, der er involveret i processen
  • Kompromitterede operationelle konti kan hurtigt erstattes med andre, men dette kræver enten manuel udskiftning (generering af nye konti og godkendelse af konti i alle smarte kontrakter) eller udvikling af en ekstra løsning, der vil gøre alt det magiske med en enkelt transaktion fra en super -sikker (hardware eller multi-sig) masterkonto.

For eksempel, i vores tilbagevendende fakturering for Ethereum-løsningen, uanset hvad der sker i en back-end, er den tilbagevendende faktureringssmarte kontrakt designet på en sådan måde, at vi har en hel måneds tid til at erstatte de kompromitterede konti, hvis nogen af ​​dem er kompromitterede .

Men alligevel, hvis du ønsker at få din bageste private nøgleopbevaring så sikker som muligt, kan du prøve at bruge Vault med et godt plugin til Ethereum, der gemmer og administrerer Ethereum-konti (også holde øje med vores open source-moduler - vi er ved at frigive noget lignende snart). Jeg vil ikke dykke dybt ned i detaljerne her, selvom du selv kan besøge de sammenkædede projekter og lære derfra.

Dette er ikke engang alt, hvad jeg har at sige. Denne artikel viste sig imidlertid at være meget længere end forventet, så jeg er nødt til at stoppe. Abonner på mine Medium / andre netværk, hvis du er interesseret i software, krypto, rejsetips eller bare vil følge noget interessant. Håber, jeg har givet et stort værdifuldt stykke information, og du finder det nyttigt. Du er velkommen til at kommentere og sprede denne artikel!