Slimme showdown: Hyperledger Fabric versus MultiChain versus Ethereum versus Corda

Bronknooppunt: 1585333

Er is meer dan één manier om code op een blockchain te zetten

In de meeste discussies over blockchains duurt het niet lang voordat het idee van 'slimme contracten' naar voren komt. In de populaire verbeelding automatiseren slimme contracten de uitvoering van interparty-interacties, zonder dat een vertrouwde tussenpersoon nodig is. Door juridische relaties in code uit te drukken in plaats van in woorden, beloven ze dat transacties direct en foutloos kunnen plaatsvinden, al dan niet opzettelijk.

Vanuit technisch oogpunt is een slim contract iets specifiekers: computercode die op een blockchain leeft en de regels voor de transacties van die keten definieert. Deze beschrijving klinkt eenvoudig genoeg, maar daarachter schuilt een grote mate van variatie in de manier waarop deze regels worden uitgedrukt, uitgevoerd en gevalideerd. Bij het kiezen van een blockchain-platform voor een nieuwe applicatie rijst de vraag “Ondersteunt dit platform slimme contracten?” is niet de juiste vraag. In plaats daarvan moeten we ons afvragen: “Welk type slimme contracten ondersteunt dit platform?”

In dit artikel is mijn doel om enkele van de belangrijkste verschillen tussen slimme contractbenaderingen en de afwegingen die ze vertegenwoordigen te onderzoeken. Ik zal dit doen door te kijken naar vier populaire blockchain-platforms voor bedrijven die een vorm van aangepaste on-chain-code ondersteunen. Ten eerste van IBM Hyperledger Fabric, die zijn contracten 'kettingcode' noemt. Ten tweede, ons MultiChain-platform, dat introduceert slimme filters in versie 2.0. Derde, Ethereum (en het is toegestaan quorum en Hol spin-offs), die de naam "smart contract" populair maakte. En tenslotte, R3 Corda, die verwijst naar "contracten" in haar transacties. Ondanks alle verschillende terminologie, verwijzen ze uiteindelijk allemaal naar hetzelfde: toepassingsspecifieke code die de regels van een ketting definieert.

Voordat ik verder ga, moet ik de lezer waarschuwen dat veel van de volgende inhoud van technische aard is en enige vertrouwdheid veronderstelt met algemene programmeer- en databaseconcepten. Voor goed of slecht, dit kan niet worden vermeden - zonder in details te treden, is het onmogelijk om een ​​weloverwogen beslissing te nemen over het al dan niet gebruiken van een blockchain voor een bepaald project en (zo ja) het juiste type blockchain om te gebruiken.

Basisprincipes van blockchain

Laten we beginnen met wat context. Stel je een applicatie voor die wordt gedeeld door meerdere organisaties, die is gebaseerd op een onderliggende database. In een traditionele gecentraliseerde architectuur wordt deze database gehost en beheerd door een enkele partij die alle deelnemers vertrouwen, zelfs als ze elkaar niet vertrouwen. Transacties die de database wijzigen, worden alleen geïnitieerd door applicaties op de systemen van deze centrale partij, vaak als reactie op berichten van de deelnemers. De database doet gewoon wat hem wordt verteld, omdat de applicatie impliciet wordt vertrouwd om alleen transacties te verzenden die logisch zijn.

Blockchains bieden een alternatieve manier om een ​​gedeelde database te beheren, zonder een vertrouwde tussenpersoon. In een blockchain voert elke deelnemer een "knooppunt" uit dat een kopie van de database bevat en zelfstandig de transacties verwerkt die deze wijzigen. Deelnemers worden geïdentificeerd met openbare sleutels of "adressen", die elk een bijbehorende privésleutel hebben die alleen bekend is bij de identiteitseigenaar. Hoewel transacties door elk knooppunt kunnen worden aangemaakt, worden ze "digitaal ondertekend" door de privésleutel van hun initiator om hun oorsprong te bewijzen.

Knooppunten maken op een peer-to-peer-manier verbinding met elkaar, waardoor transacties en de 'blokken' waarin ze een tijdstempel krijgen en worden bevestigd in het netwerk snel worden gepropageerd. De blockchain zelf is letterlijk een ketting van deze blokken, die een geordend logboek vormt van elke historische transactie. Een "consensusalgoritme" wordt gebruikt om ervoor te zorgen dat alle knooppunten overeenstemming bereiken over de inhoud van de blockchain, zonder gecentraliseerde controle. (Merk op dat een deel van deze beschrijving niet van toepassing is op Corda, waarbij elk knooppunt slechts een gedeeltelijke kopie van de database heeft en er geen wereldwijde blockchain is. Daar zullen we later meer over vertellen.)

In principe kan elke gedeelde database-applicatie worden ontworpen door in de kern een blockchain te gebruiken. Maar hierdoor ontstaan ​​een aantal technische uitdagingen die niet bestaan ​​in een gecentraliseerd scenario:

  • Transactieregels. Als een deelnemer de database rechtstreeks kan wijzigen, hoe zorgen we ervoor dat ze de regels van de applicatie volgen? Wat weerhoudt een gebruiker ervan om de inhoud van de database op een zelfbedieningsmanier te corrumperen?
  • Determinisme. Zodra deze regels zijn gedefinieerd, worden ze meerdere keren door meerdere knooppunten toegepast bij het verwerken van transacties voor hun eigen kopie van de database. Hoe zorgen we ervoor dat elk knooppunt exact hetzelfde resultaat behaalt?
  • Conflictpreventie. Hoe gaan we zonder centrale coördinatie om met twee transacties die elk de regels van de toepassing volgen, maar toch met elkaar in strijd zijn? Conflicten kunnen het gevolg zijn van een opzettelijke poging om het systeem te bespelen, of kunnen het onschuldige gevolg zijn van pech en timing.

Dus waar komen slimme contracten, slimme filters en kettingcode binnen? Hun kerndoel is om te werken met de onderliggende infrastructuur van een blockchain om deze uitdagingen op te lossen. Slimme contracten zijn het gedecentraliseerde equivalent van applicatiecode - in plaats van op één centrale plaats te draaien, draaien ze op meerdere knooppunten in de blockchain, waardoor transacties worden gecreëerd of gevalideerd die de inhoud van die database wijzigen.

Laten we beginnen met transactieregels, de eerste van deze uitdagingen, en kijken hoe ze worden uitgedrukt in respectievelijk Fabric, MultiChain, Ethereum en Corda.

Transactieregels

Transactieregels vervullen een specifieke functie in blockchain-aangedreven databases - en beperken de transformaties die kan worden uitgevoerd op de status van die database. Dit is nodig omdat de transacties van een blockchain door elk van zijn deelnemers kunnen worden geïnitieerd en deze deelnemers elkaar niet voldoende vertrouwen om hen in staat te stellen de database naar believen te wijzigen.

Laten we twee voorbeelden bekijken van waarom transactieregels nodig zijn. Stel je eerst een blockchain voor die is ontworpen om PDF-documenten die door de deelnemers zijn gepubliceerd, te aggregeren en tijdstempelen. In dit geval mag niemand het recht hebben om documenten te verwijderen of te wijzigen, omdat dit de volledige bedoeling van het systeem - documentpersistentie - zou ondermijnen. Ten tweede, overweeg een blockchain die een gedeeld financieel grootboek vertegenwoordigt, dat de saldi van zijn gebruikers bijhoudt. We kunnen niet toestaan ​​dat een deelnemer zijn eigen saldo willekeurig opblaast of het geld van anderen afneemt.

Ingangen en uitgangen

Onze blockchain-platforms vertrouwen op twee brede benaderingen voor het uitdrukken van transactieregels. De eerste, die ik het "input-output model" noem, wordt gebruikt in MultiChain en Corda. Hier vermelden transacties expliciet de database-rijen of "staten" die ze verwijderen en creëren, en vormen respectievelijk een set van "inputs" en "outputs". Het wijzigen van een rij wordt uitgedrukt als de equivalente bewerking van het verwijderen van die rij en het creëren van een nieuwe rij op zijn plaats.

Aangezien database-rijen alleen worden verwijderd bij invoer en alleen worden gemaakt bij uitvoer, moet elke invoer de uitvoer van een eerdere transactie 'besteden'. De huidige status van de database wordt gedefinieerd als de set van "niet-uitgegeven transactie-outputs" of "UTXO's", dwz outputs van eerdere transacties die nog niet zijn gebruikt. Transacties kunnen ook aanvullende informatie bevatten, genaamd "metadata", "commando's" of "bijlagen", die geen onderdeel worden van de database, maar helpen om hun betekenis of doel te definiëren.

Gezien deze drie sets inputs, outputs en metadata, wordt de geldigheid van een transactie in MultiChain of Corda bepaald door een code die willekeurige berekeningen op die sets kan uitvoeren. Deze code kan de transactie valideren of anders een fout retourneren met een bijbehorende uitleg. U kunt het input-outputmodel zien als een geautomatiseerde 'inspecteur' met een checklist die ervoor zorgt dat transacties elke regel volgen. Als de transactie een van die controles niet doorstaat, wordt deze automatisch afgewezen door alle knooppunten in het netwerk.

Opgemerkt moet worden dat, ondanks het delen van het input-outputmodel, MultiChain en Corda het heel anders implementeren. In MultiChain kunnen output activa en / of data bevatten in JSON, tekst of binair formaat. De regels zijn gedefinieerd in "transactiefilters" of "streamfilters", die kunnen worden ingesteld om alle transacties te controleren, of alleen die welke betrekking hebben op bepaalde activa of groepen gegevens. Daarentegen wordt een Corda-output "state" weergegeven door een object in de programmeertaal Java of Kotlin, met gedefinieerde gegevensvelden. De regels van Corda worden gedefinieerd in "contracten" die aan specifieke staten zijn verbonden, en het contract van een staat wordt alleen toegepast op transacties die die staat in zijn inputs of outputs bevatten. Dit heeft betrekking op Corda's ongebruikelijk zichtmodel, waarin transacties alleen kunnen worden gezien door hun tegenpartijen of degenen wier latere transacties ze beïnvloeden.

Contracten en berichten

De tweede benadering, die ik het 'contract-berichtmodel' noem, wordt gebruikt in Hyperledger Fabric en Ethereum. Hier kunnen meerdere 'slimme contracten' of 'kettingcodes' worden gemaakt op de blockchain, en elk heeft zijn eigen database en bijbehorende code. De database van een contract kan alleen worden gewijzigd door de code ervan, in plaats van rechtstreeks door blockchain-transacties. Dit ontwerppatroon is vergelijkbaar met de 'inkapseling' van code en gegevens in objectgeoriënteerde programmering.

Met dit model begint een blockchain-transactie als een bericht dat naar een contract wordt verzonden, met enkele optionele parameters of gegevens. De code van het contract wordt uitgevoerd als reactie op het bericht en de parameters en het is gratis om zijn eigen database te lezen en te schrijven als onderdeel van die reactie. Contracten kunnen ook berichten naar andere contracten sturen, maar hebben geen directe toegang tot elkaars databases. In de taal van relationele databases fungeren contracten als afgedwongen "Opgeslagen procedures", waarbij alle toegang tot de database verloopt via een vooraf gedefinieerde code.

Zowel Fabric als Quorum, een variatie op Ethereum, maken dit plaatje ingewikkelder doordat een netwerk meerdere "kanalen" of "privé-staten" kan definiëren. Het doel is om het probleem van de vertrouwelijkheid van blockchain te verminderen door afzonderlijke omgevingen te creëren, die elk alleen zichtbaar zijn voor een bepaalde subgroep van deelnemers. Hoewel dit in theorie veelbelovend klinkt, zijn de contracten en gegevens in elk kanaal of privéstaat in werkelijkheid geïsoleerd van die in de andere. Als gevolg hiervan staan ​​deze omgevingen qua slimme contracten gelijk aan afzonderlijke blockchains.

Voorbeeldregels

Laten we eens kijken hoe we de transactieregels voor een financieel grootboek met één activum kunnen implementeren met deze twee modellen. Elke rij in de database van ons grootboek heeft twee kolommen, met het adres van de eigenaar en de hoeveelheid van het bezit. In het input-outputmodel moeten transacties aan twee voorwaarden voldoen:

  1. De totale hoeveelheid activa in de output van een transactie moet overeenkomen met het totaal in de input. Dit voorkomt dat gebruikers willekeurig geld kunnen creëren of verwijderen.
  2. Elke transactie moet worden ondertekend door de eigenaar van elk van zijn inputs. Dit voorkomt dat gebruikers elkaars geld zonder toestemming kunnen uitgeven.

Alles bij elkaar zijn deze twee voorwaarden alles wat nodig is om een ​​eenvoudig maar levensvatbaar financieel systeem te creëren.

In het contract-berichtmodel ondersteunt het contract van het activum een ​​"betaling verzenden" -bericht, dat drie parameters heeft: het adres van de afzender, het adres van de ontvanger en de te verzenden hoeveelheid. Als reactie voert het contract de volgende vier stappen uit:

  1. Controleer of de transactie is ondertekend door de afzender.
  2. Controleer of de afzender voldoende saldo heeft.
  3. Trek de gevraagde hoeveelheid af van de rij van de afzender.
  4. Voeg die hoeveelheid toe aan de rij van de ontvanger.

Als een van de controles in de eerste twee stappen mislukt, wordt het contract afgebroken en wordt er geen betaling gedaan.

Dus zowel de input-output als de contractberichtmodellen zijn effectieve manieren om transactieregels te definiëren en een gedeelde database veilig te houden. Op theoretisch niveau kunnen al deze modellen worden gebruikt om de andere te simuleren. In de praktijk zal het meest geschikte model echter afhangen van de applicatie die wordt gebouwd. Heeft elke transactie invloed op enkele of veel stukjes informatie? Moeten we transactie-onafhankelijkheid kunnen garanderen? Heeft elk stuk gegevens een duidelijke eigenaar of is er een wereldwijde status die moet worden gedeeld?

Het valt buiten ons bestek om te onderzoeken hoe de antwoorden een keuze tussen deze twee modellen zouden moeten beïnvloeden. Maar als algemene richtlijn is het bij het ontwikkelen van een nieuwe blockchain-applicatie de moeite waard om de transactieregels in beide vormen uit te drukken en te kijken welke natuurlijker past. Het verschil zal zich uiten in termen van: (a) programmeergemak, (b) opslagvereisten en doorvoer, en (c) snelheid van conflictdetectie. We zullen later meer over dit laatste nummer praten.

Ingebouwde regels

Als het gaat om transactieregels, is er één manier waarop MultiChain specifiek verschilt van Fabric, Ethereum en Corda. In tegenstelling tot deze andere platforms heeft MultiChain verschillende ingebouwde abstracties die enkele basisbouwstenen bieden voor blockchain-gestuurde applicaties, zonder vereisen ontwikkelaars om hun eigen code te schrijven. Deze abstracties hebben betrekking op drie gebieden die gewoonlijk nodig zijn: (a) dynamische rechten, (b) overdraagbare activa en (c) gegevensopslag.

MultiChain beheert bijvoorbeeld machtigingen om verbinding te maken met het netwerk, transacties te verzenden en te ontvangen, activa of streams te creëren of de machtigingen van andere gebruikers te beheren. Meerdere fungibele activa kunnen veilig en atomair worden uitgegeven, overgedragen, met pensioen gaan of worden uitgewisseld. Er kan een onbeperkt aantal 'streams' in een keten worden gemaakt, voor het publiceren, indexeren en ophalen van on-chain of off-chain data in JSON, tekst of binaire formaten. Alle transactieregels voor deze abstracties zijn out-of-the-box beschikbaar.

Bij het ontwikkelen van een applicatie op MultiChain is het mogelijk om deze ingebouwde functionaliteit te negeren en transactieregels uit te drukken met alleen slimme filters. Slimme filters zijn echter ontworpen om samen te werken met de ingebouwde abstracties, door hun standaardgedrag mogelijk te maken begrensd op maat gemaakte manieren. De toestemming voor bepaalde activiteiten kan bijvoorbeeld worden beheerd door specifieke beheerders, in plaats van het standaardgedrag dat elke beheerder zal doen. De overdracht van bepaalde activa kan in de tijd beperkt zijn of vereist extra goedkeuring boven een bepaald bedrag. De gegevens in een bepaalde stream kunnen worden gevalideerd om ervoor te zorgen dat ze alleen uit JSON-structuren met vereiste velden en waarden bestaan.

In al deze gevallen creëren slimme filters aanvullende vereisten voor transacties die moeten worden gevalideerd, maar niet verwijderen de eenvoudige regels die zijn ingebouwd. Dit kan helpen bij het aanpakken van een van de belangrijkste uitdagingen in blockchain-toepassingen: het feit dat een bug in een aantal on-chain-code rampzalige gevolgen kan hebben. We hebben eindeloze voorbeelden van dit probleem gezien in de openbare Ethereum-blockchain, het meest bekend in de Ondergang van de DAO en Pariteit bugs met meerdere handtekeningen. Bredere onderzoeken hebben een groot aantal veelvoorkomende kwetsbaarheden gevonden in slimme contracten van Ethereum waarmee aanvallers het geld van andere mensen kunnen stelen of bevriezen.

Natuurlijk kunnen MultiChain slimme filters ook bugs bevatten, maar de gevolgen zijn beperkter van omvang. Zo voorkomen de ingebouwde activaregels dat een gebruiker het geld van een ander uitgeeft of per ongeluk zijn eigen geld laat verdwijnen, ongeacht welke andere logica een slim filter bevat. Als een bug wordt gevonden in een slimme filter, kan deze worden gedeactiveerd en vervangen door een gecorrigeerde versie, terwijl de basisintegriteit van het grootboek wordt beschermd. Filosofisch gezien staat MultiChain dichter bij traditionele database-architecturen, waar het databaseplatform een ​​aantal ingebouwde abstracties biedt, zoals kolommen, tabellen, indexen en beperkingen. Krachtigere functies zoals triggers en opgeslagen procedures kunnen optioneel worden gecodeerd door applicatieontwikkelaars, in gevallen waarin ze echt nodig zijn.

Transactieregels Stof MultiChain Ethereum Corda
Model Contractbericht Invoer uitvoer Contractbericht Invoer uitvoer
Ingebouwde ins Geen Toestemmingen +
activa + streams
Geen Geen

Determinisme

Laten we doorgaan naar het volgende deel van onze confrontatie. Welke benadering we ook kiezen, de aangepaste transactieregels van een blockchain-applicatie worden uitgedrukt als computercode geschreven door applicatieontwikkelaars. En in tegenstelling tot gecentraliseerde applicaties, zal deze code voor elke transactie meer dan één keer en op meer dan één plaats worden uitgevoerd. Dit komt omdat meerdere blockchain-knooppunten van verschillende deelnemers elk die transactie voor zichzelf moeten verifiëren en / of uitvoeren.

Deze herhaalde en redundante code-uitvoering introduceert een nieuwe vereiste die zelden wordt aangetroffen in gecentraliseerde toepassingen: determinisme. In de context van berekening betekent determinisme dat een stuk code altijd hetzelfde antwoord geeft voor dezelfde parameters, ongeacht waar en wanneer het wordt uitgevoerd. Dit is absoluut cruciaal voor code die interageert met een blockchain omdat, zonder determinisme, de consensus tussen de knooppunten in die keten catastrofaal kan worden afgebroken.

Laten we eens kijken hoe dit er in de praktijk uitziet, eerst in het input-outputmodel. Als twee knooppunten een verschillende mening hebben over de vraag of een transactie geldig is, accepteert de ene een blok met die transactie en de andere niet. Aangezien elk blok expliciet terug linkt naar een vorig blok, zal dit een permanente 'vork' in het netwerk creëren, waarbij een of meer knooppunten vanaf dat moment de meerderheid van de mening over de volledige blockchain-inhoud niet accepteren. De knooppunten in de minderheid worden afgesneden van de evoluerende status van de database en zullen de applicatie niet langer effectief kunnen gebruiken.

Laten we nu eens kijken wat er gebeurt als de consensus uitvalt in het contract-berichtmodel. Als twee knooppunten een verschillende mening hebben over hoe een contract moet reageren op een bepaald bericht, kan dit leiden tot een verschil in de inhoud van hun databases. Dit kan op zijn beurt de reactie van het contract op toekomstige berichten beïnvloeden, inclusief berichten die het naar andere contracten stuurt. Het eindresultaat is een toenemende divergentie tussen de verschillende knooppunten die de status van de database bekijken. (Het 'state root'-veld in Ethereum-blokken zorgt ervoor dat elk verschil in contractreacties onmiddellijk leidt tot een volledig catastrofale blockchain-vork, in plaats van het risico te lopen verborgen te blijven voor een bepaalde periode.)

Bronnen van niet-determinisme

Dus niet-determinisme in blockchain-code is duidelijk een probleem. Maar als de basisbouwstenen van berekeningen, zoals rekenen, deterministisch zijn, waar moeten we ons dan zorgen over maken? Nou, het blijkt dat er nogal wat dingen zijn:

  • Het meest voor de hand liggende generatoren voor willekeurige getallen, aangezien deze per definitie zijn ontworpen om elke keer een ander resultaat te produceren.
  • Het controleren van de huidige tijd, aangezien knooppunten transacties niet precies op hetzelfde moment zullen verwerken en in ieder geval hun klokken mogelijk niet synchroon lopen. (Het is nog steeds mogelijk om tijdsafhankelijke regels te implementeren door te verwijzen naar tijdstempels binnen de blockchain zelf.)
  • Externe bronnen raadplegen, zoals internet, schijfbestanden of andere programma's die op een computer worden uitgevoerd. Er kan niet worden gegarandeerd dat deze bronnen altijd hetzelfde antwoord geven en mogelijk niet meer beschikbaar zijn.
  • Het uitvoeren van meerdere stukjes code in parallelle "threads", aangezien dit leidt tot een "race-conditie" waarbij de volgorde waarin deze processen eindigen niet kan worden voorspeld.
  • Berekeningen met drijvende komma uitvoeren die zelfs zeer kleine verschillende antwoorden kunnen geven op verschillende computerprocessorarchitecturen.

Onze vier blockchain-platforms gebruiken verschillende benaderingen om deze valkuilen te vermijden.

Deterministische uitvoering

Laten we beginnen met Ethereum, omdat de aanpak het meest 'puur' is. Ethereum-contracten worden uitgedrukt in een speciaal formaat genaamd "Ethereum bytecode", dat wordt uitgevoerd door de Ethereum Virtual Machine ("EVM"). Programmeurs schrijven bytecode niet rechtstreeks, maar genereren of 'compileren' het vanuit een JavaScript-achtige programmeertaal genaamd Solidity. (Andere talen waren vroeger beschikbaar, maar zijn sindsdien verouderd.) Het determinisme wordt gegarandeerd door het feit dat de bytecode Solidity en Ethereum geen niet-deterministische bewerkingen kunnen coderen - zo eenvoudig is het.

MultiChain-filters en Corda-contracten kiezen voor een andere aanpak door bestaande programmeertalen en runtime-omgevingen aan te passen. MultiChain gebruikt JavaScript dat in Google wordt uitgevoerd V8 engine, die ook de kern vormt van de Chrome-browser en het Node.js-platform, maar met bronnen van niet-determinisme uitgeschakeld. Evenzo gebruikt Corda Java of Kotlin, die beide zijn gecompileerd naar "Java bytecode" die wordt uitgevoerd binnen een Java Virtual Machine ("JVM"). Voorlopig gebruikt Corda de standaard niet-deterministische JVM van Oracle, maar er wordt gewerkt aan de integratie van een deterministische versie. In de tussentijd moeten contractontwikkelaars van Corda ervoor zorgen dat niet-determinisme in hun code wordt toegestaan.

Hoe verhoudt het purisme van Ethereum zich tot de evolutionaire benadering van MultiChain en Corda? Het belangrijkste voordeel van Ethereum is het minimaliseren van risico's - het is minder waarschijnlijk dat een ingebouwde virtuele machine een onopzettelijke bron van niet-determinisme bevat. Hoewel een dergelijk toezicht kan worden verholpen door een software-update, zou het storend zijn voor elke keten die pech had om het tegen te komen. Het probleem van Ethereum is echter dat Solidity en de EVM een klein en ontluikend ecosysteem vormen in de bredere context van programmeertalen en runtime-omgevingen. Ter vergelijking: JavaScript en Java zijn de top twee talen op Github, draaien op miljarden digitale apparaten en hebben looptijden die in de afgelopen decennia zijn geoptimaliseerd. Dit is waarschijnlijk de reden waarom de openbare Ethereum-blockchain een overgang naar overweegt Ewas, een deterministische vork van de opkomende WebAssembly-standaard.

Determinisme door goedkeuring

Als het op determinisme aankomt, hanteert Hyperledger Fabric een heel andere benadering. In Fabric, wanneer een "client" -knooppunt een bericht naar een kettingcode wil sturen, stuurt het dat bericht eerst naar een aantal "endorser" -knooppunten. Elk van deze knooppunten voert de kettingcode onafhankelijk uit en vormt een mening over de berichten effect in de database van die kettingcode. Deze meningen worden samen met een digitale handtekening naar de klant teruggestuurd, wat een formele "goedkeuring" vormt. Als de klant voldoende aantekeningen van het beoogde resultaat ontvangt, creëert hij een transactie met die aantekeningen en zendt deze uit voor opname in de keten.

Om determinisme te garanderen, heeft elk stuk kettingcode een 'goedkeuringsbeleid' dat precies aangeeft welk goedkeuringsniveau vereist is om zijn transacties geldig te maken. In het beleid van één kettingcode kan bijvoorbeeld worden vermeld dat goedkeuring vereist is van ten minste de helft van de knooppunten van de blockchain. Een andere kan een goedkeuring van een van de drie vertrouwde partijen vereisen. Hoe dan ook, elk knooppunt kan onafhankelijk controleren of de nodige aantekeningen zijn ontvangen.

Om het verschil te verduidelijken, is het determinisme in de meeste blockchain-platforms gebaseerd op de vraag: "Wat is het resultaat van het uitvoeren van deze code op deze gegevens?" - en we moeten er absoluut zeker van zijn dat elk knooppunt deze vraag identiek zal beantwoorden. Het determinisme in Fabric daarentegen is gebaseerd op een andere vraag: "Zijn genoeg endossers het eens over het resultaat van het uitvoeren van deze code op deze gegevens?" Dat is een vrij simpele kwestie van tellen, en er is geen ruimte voor non-determinisme om in te kruipen.

Het determinisme van goedkeuring door Fabric heeft een aantal interessante gevolgen. Ten eerste kan chaincode in veel verschillende programmeertalen worden geschreven, omdat deze niet hoeven te worden aangepast voor determinisme (Go, Java en JavaScript worden momenteel ondersteund). Ten tweede kan chaincode voor sommige deelnemers van een blockchain worden verborgen, omdat deze alleen hoeft te worden uitgevoerd door klanten en goedkeurders (de database zelf is wereldwijd zichtbaar). Ten slotte en met name kan Fabric-kettingcode dingen doen die verboden zijn in andere blockchain-omgevingen, zoals het controleren van het weer met behulp van een online web-API. In het ergste geval, waar elke endossant een ander antwoord krijgt van deze API, zal de klant onvoldoende endossementen krijgen voor een bepaald resultaat en zal er geen transactie plaatsvinden. (Opgemerkt moet worden dat Fabric-teamleden nog steeds adviseren gebruikmakend van deterministische logica binnen chaincode, om verrassingen te vermijden.)

Welke prijs betaalt Fabric voor deze flexibiliteit? Als het doel van een blockchain is om tussenpersonen te verwijderen uit een gedeelde database-gestuurde applicatie, neemt Fabrics afhankelijkheid van goedkeurders een grote stap weg van dat doel. Voor de deelnemers in de keten is het niet langer voldoende om de regels van de kettingcode te volgen - ze hebben ook bepaalde andere knooppunten nodig om af te spreken dat ze dat hebben gedaan. Erger nog, een kwaadaardige subset van sponsors zou databasewijzigingen kunnen goedkeuren die helemaal geen kettingcode volgen. Dit geeft endors veel meer macht dan de validators in reguliere blockchains, die transacties kunnen censureren maar de regels van de blockchain niet kunnen overtreden. Ontwikkelaars van blockchain-applicaties moeten beslissen of deze afweging in hun specifieke geval zinvol is.

Determinisme Stof MultiChain Ethereum Corda
Model Endorsements Aangepaste looptijd Speciaal gebouwde VM Aangepaste looptijd
Talen Ga + Java + JavaScript JavaScript Stevigheid Java + Kotlin
Zichtbaarheid van code Tegenpartijen +
bekrachtigers
Blockchain Blockchain Tegenpartijen +
ten laste
Afgedwongen Nee Ja Ja Niet voor nu)

Conflictpreventie

Tot dusver hebben we besproken hoe verschillende blockchain-platforms transactieregels in code uitdrukken en hoe ze er deterministisch voor zorgen dat elk knooppunt die regels identiek toepast. Nu is het tijd om te praten over een derde aspect van onze confrontatie: hoe gaat elk platform om met de mogelijkheid dat twee transacties, die op zichzelf geldig zijn, met elkaar conflicteren? Stel je in het eenvoudigste voorbeeld voor dat Alice $ 10 heeft in een financieel grootboek en twee transacties uitzendt: de ene stuurt $ 8 naar Bob en de andere $ 7 naar Charlie. Het is duidelijk dat slechts één van deze transacties kan slagen.

Twee modellen

We kunnen beginnen door de aanpak van MultiChain en Corda voor dit probleem samen te groeperen. Zoals eerder beschreven, gebruiken beide een invoer-uitvoermodel voor het weergeven van transacties en hun regels, waarbij elke transactie-invoer een eerdere transactie-uitvoer besteedt. Dit leidt tot een eenvoudig principe om conflicten te voorkomen: elke output kan slechts één keer worden uitgegeven. MultiChain-filters en Corda-contracten kunnen op hun respectievelijke platforms vertrouwen om deze beperking absoluut af te dwingen. Aangezien Alice's $ 10 wordt weergegeven door een eerdere transactie-uitvoer, stopt deze regel voor één besteding automatisch dat ze deze naar zowel Bob als Charlie stuurt.

Ondanks deze gelijkenis is het belangrijk om te wijzen op een belangrijk verschil in hoe MultiChain en Corda conflicten voorkomen. In MultiChain ziet elk knooppunt elke transactie en kan zo onafhankelijk verifiëren dat elke output slechts één keer wordt uitgegeven. Elke transactie waarbij een dubbele uitgave wordt gedaan ten opzichte van een eerder bevestigde transactie, wordt onmiddellijk en automatisch afgewezen. In Corda daarentegen is er geen wereldwijde blockchain, dus zijn 'notarissen' nodig om deze dubbele uitgaven te voorkomen. Elke Corda-outputstatus wordt toegewezen aan een notaris, die alle transactie-uitgaven voor die output moet ondertekenen, wat bevestigt dat deze niet eerder is uitgegeven. De deelnemers van een blockchain moeten notarissen vertrouwen om deze regel eerlijk te volgen, en kwaadwillende notarissen kunnen naar believen chaos veroorzaken. Net als bij de aantekeningen in Fabric, deze "eenmalige uitgaven als service'Design heeft voordelen op het gebied van vertrouwelijkheid, maar herintroduceert tussenpersonen, wat tegen de blockchain-korrel ingaat. (Het is belangrijk om te verduidelijken dat Corda-notarissen kunnen worden geleid door groepen deelnemers met behulp van een consensusalgoritme, zodat de integriteit van het grootboek nog steeds kan worden beschermd tegen individuele slechte actoren).

Laten we verder gaan met Ethereum. Ter herinnering, Ethereum gebruikt contracten en berichten in plaats van inputs en outputs. Als gevolg hiervan zijn transactieconflicten zoals de twee betalingen van Alice niet onmiddellijk zichtbaar voor de blockchain-engine. In plaats daarvan worden ze gedetecteerd en geblokkeerd door de contract die de transacties verwerkt, nadat hun bestelling op de keten is bevestigd. Bij het verwerken van alle betalingen van Alice controleert het contract of haar saldo voldoende is. Als de transactie die $ 8 aan Bob betaalt eerst komt, wordt deze op de gebruikelijke manier verwerkt, waardoor Alice $ 2 op haar account overhoudt. Als gevolg hiervan, wanneer het contract de tweede transactie verwerkt waarbij $ 7 aan Charlie wordt betaald, ziet het dat Alice het benodigde geld mist en wordt de transactie afgebroken.

Outputs versus contracten

Tot dusver hebben we twee verschillende technieken gezien om conflicterende transacties te voorkomen: output met één uitgave in MultiChain en Corda en contractgebaseerde verificatie in Ethereum. Dus wat is beter?

Laten we, om deze vraag te beantwoorden, een voorbeeld van een "1-van-2 multisignatuur" -account bekijken dat $ 100 namens Gavin en Helen aanhoudt, en een van hen beiden toestaat dat geld onafhankelijk uit te geven. Gavin instrueert zijn aanvraag om $ 80 aan Donna te betalen, en een paar seconden later wil Helen $ 40 aan Edward sturen. Aangezien er voor beide betalingen onvoldoende middelen zijn, zouden deze transacties onvermijdelijk in strijd zijn. In het geval dat beide transacties worden uitgezonden, wordt de uitkomst bepaald door degene die het eerst in de keten komt. Merk op dat dit conflict, in tegenstelling tot Alice's voorbeeld, is toevalligomdat niemand probeert de regels van de applicatie te overtreden - ze hadden gewoon een ongelukkige timing.

Bij het overwegen van de waarschijnlijkheid dat dit conflict zich voordoet, is de hamvraag: nadat Gavin zijn transactie heeft verzonden, hoe lang duurt het voordat Helen's knooppunt weet dat haar betaling mogelijk mislukt? Hoe korter deze periode is, hoe groter de kans dat Helen die betaling niet zal proberen, waardoor zij en haar sollicitatie voor een volgende verrassing worden behoed.

Met het input-outputmodel is elk conflict tussen transacties direct zichtbaar voor het blockchain-platform, aangezien de twee transacties expliciet zullen proberen dezelfde eerdere output te besteden. In MultiChain gebeurt dit zodra de transactie van Gavin is doorgevoerd naar de knoop van Helen, meestal binnen een seconde of minder. In Corda zal de notaris van de output het verzoek om Helen's transactie te ondertekenen weigeren, aangezien hij de transactie van Gavin al heeft ondertekend, zodat Helen onmiddellijk weet dat haar betaling zal mislukken. (Hoewel als de Corda-notaris zelf wordt gedistribueerd, ze misschien een paar seconden moet wachten op een antwoord.) Hoe dan ook, het is niet nodig om te wachten tot een transactie wordt bevestigd en besteld in de blockchain.

Hoe zit het met het model van Ethereum? In dit geval is er geen directe manier voor het blockchain-platform om te weten dat er een conflict zal optreden. Hoewel het knooppunt van Helen de transactie van Gavin op het netwerk kan zien, kan het niet weten hoe dit de eigen transactie van Helen zal beïnvloeden, aangezien dit vanuit zijn perspectief slechts twee berichten zijn die naar hetzelfde contract worden verzonden. Misschien tien seconden later, zodra de definitieve volgorde van de conflicterende transacties op de blockchain is bevestigd, zal Helen's knooppunt de feitelijke in plaats van de verwachte uitkomst herberekenen, en haar applicatie zal de weergave dienovereenkomstig bijwerken. Ondertussen zullen zowel Gavin als Helen in het donker worden achtergelaten.

Maar hieruit moeten we niet concluderen dat het input-outputmodel altijd het beste werkt. Overweeg een variatie op ons voorbeeldscenario, waarbij zowel Gavin als Helen op hetzelfde moment kleinere betalingen van $ 40 vragen vanaf het oorspronkelijke saldo van $ 100. In het input-outputmodel zouden deze transacties met elkaar in strijd zijn, aangezien ze beide dezelfde database-rij met die $ 100 uitgeven, en slechts één van de betalingen zou slagen. Maar in Ethereum zouden beide transacties met succes worden verwerkt, ongeacht hun definitieve bestelling, omdat de rekening voldoende saldo bevat voor beide. In dit geval vervult Ethereum meer trouw de bedoelingen van Gavin en Helen.

Lees-schrijf sets

Laten we tot slot praten over Fabric, wiens op goedkeuring gebaseerde benadering een hybride is van deze twee technieken. Zoals eerder uitgelegd, wanneer een Fabric "client" -knooppunt een bericht naar een contract wil verzenden, vraagt ​​het eerst enkele goedkeurende knooppunten om dat bericht namens hem uit te voeren. De ondersteunende knooppunten doen dit op een vergelijkbare manier als Ethereum - het contract uitvoeren tegen hun lokale database - maar dit proces wordt eerder waargenomen dan onmiddellijk toegepast. Elke endossant registreert de reeks rijen die gelezen en geschreven zou worden, en noteert ook de exacte versie van die rijen op dat moment. Deze "read-write set" van rijen met versies wordt expliciet genoemd in de goedkeuring en wordt opgenomen in de transactie die de klant uitzendt.

Conflicten tussen Fabric-transacties worden opgelost zodra hun bestelling in de keten is afgerond. Elk knooppunt verwerkt elke transactie onafhankelijk, controleert het goedkeuringsbeleid en past de gespecificeerde databasewijzigingen toe. Als een transactie echter een database-rijversie leest of schrijft die al is gewijzigd door een eerdere transactie, wordt die tweede transactie genegeerd. Om terug te gaan naar Alice's tegenstrijdige betalingen aan Bob en Charlie, zullen beide transacties dezelfde rijversie lezen en wijzigen, met de $ 10 waarmee Alice is begonnen. De tweede transactie wordt dus veilig en automatisch afgebroken.

Fabrics benadering van conflictoplossing werkt prima, maar combineert qua prestaties en flexibiliteit de slechtste van de vorige twee modellen. Omdat goedkeuringen transacties omzetten in specifieke lees-schrijfsets, zouden de gelijktijdige maar compatibele $ 40-betalingen van Gavin en Helen leiden tot een conflict dat Ethereum vermijdt. Fabric behaalt echter niet het snelheidsvoordeel van het input-outputmodel, aangezien endossers contracten uitvoeren tegen de meest recente versie van de database die door de blockchain is bevestigd, waarbij onbevestigde transacties worden genegeerd. Dus als Helen een paar seconden na Gavin haar betaling initieert, maar voordat Gavin op de blockchain is bevestigd, zal Fabric tegenstrijdige transacties creëren die een puur input-outputmodel vermijdt.

Conflictpreventie Stof MultiChain Ethereum Corda
Model Lees-schrijf sets Enkele uitgaven Contractcontroles Enkele uitgaven
Verificatie Onafhankelijk Onafhankelijk Onafhankelijk Vertrouwde notarissen
Speed ~ 10s (bevestiging) ~ 1s (vermeerdering) ~ 10s (bevestiging) 0 ~ 5s (notaris)

Een complexe keuze

In dit stuk hebben we veel van de verschillende manieren besproken waarop Corda, Ethereum, Fabric en MultiChain de belangrijkste uitdagingen van 'slimme contracten' of applicatiecode die in een blockchain is ingebed, aanpakken. En elk platform heeft verschillende antwoorden op onze drie kernvragen: hoe worden transactieregels weergegeven? Hoe wordt code deterministisch uitgevoerd? En hoe voorkomen we conflicten?

Dus wie is de winnaar van onze smart contract showdown? Het zou inmiddels duidelijk moeten zijn dat er geen eenvoudig antwoord is. Elk platform vertegenwoordigt een complexe wisselwerking tussen flexibiliteit, eenvoud, prestaties, desintermediatie, veiligheid en vertrouwelijkheid. De keuze van het platform voor een bepaalde applicatie moet dus beginnen met een gedetailleerd begrip van het vertrouwensmodel van die applicatie, de soorten transacties die ermee gemoeid zijn en hun waarschijnlijke conflictpatronen. Als u iemand tegenkomt die een specifieke slimme contractoplossing pusht voordat ze de antwoorden op deze vragen kennen, raad ik u beleefd maar met klem aan om een ​​"slimmere" benadering te volgen.

Plaats eventuele opmerkingen op LinkedIn.

Tijdstempel:

Meer van Multichain