Hva er smarte kontrakter?
Smart contracts should be considered self-funded bug-bounty platforms.
(Luke Plant: The Technological Case against Bitcoin and Blockchain)
Smarte kontrakter er programvare som kjører på en blokkjede. Både programkoden og programmets tilstand ligger lagret på blokkjeden. Kontraktens skriveoperasjoner kalles ved å registrere transaksjoner mot blokkjeden. Blokkjedens utvinnere håndterer disse ved å kjøre kontrakten i en virtuell maskin. Dette fører til en ny tilstand, som så lagres i blokkjeden.
Tilstanden kan for eksempel være en liste over de som har sendt kryptomynter til kontrakten. Jeg registrerer en transaksjon som overfører 0.1 ETH til kontrakten. Utvinnerne kjører så kontrakten på en virtuell maskin som legger meg til i denne listen. Når den neste blokken registreres på blokkjeden, vil den så inneholde denne nye tilstanden, som nå er den nye offisielle listen over hvem som har sendt midler til kontrakten.
Kontrakten inneholder kanskje også en test som sier at hvis kontrakten har mer enn 10 ETH, skal vi plukke en (pseudo-)tilfeldig adresse fra listen, vektet etter hvor mye de bidro med, og sende 9 ETH til denne, og resten til utviklerne bak kontrakten.
Hurra, vi har laget et lotteri på blokkjeden.
Kontrakten inneholder kanskje i stedet en test som sier at hvis kontrakten har mer enn 10 ETH, skal vi plukke en (pseudo-)tilfeldig adresse fra listen, som er implementert slik at den “tilfeldigvis” alltid plukker en adresse som er kontrollert av utviklerne bak kontrakten.
Hurra, vi har laget et falskt lotteri på blokkjeden.
Bankutgaven av en brusautomat
Programmene vi snakker om her er ikke “kontrakter” i juridisk forstand, men snarere en digital erstatning for mye av rollen kontrakter, lover og regler fyller i organisasjoner og bedrifter. Organisasjoner har regler for hvordan man tar beslutninger om hvordan organisasjonens midler skal benyttes, for eksempel for hvordan man velger personene som har autoritet til å flytte midlene. Bruken av midlene er også underlatt lover, blant annet for regnskapsføring. Hvis reglene eller lovene har blitt brutt, kan man involvere politiet eller rettsvesenet.
En DAO, det vil si en organisasjon som bygger på smarte kontrakter, er i langt mindre grad underlagt politiet og rettsvesents autoritet. Dette er hele poenget med en slik organisasjon. Motivasjonen for å frigjøre seg fra rettsvesenet på denne måten kan være at man ønsker å lettere kunne utføre en svindel, eller det kan være å skape en internasjonal organisasjon som fungerer på tvers av ulike jurisdiksjoner.
I en smart kontrakt er uansett rettsvesenet irrelevant, fordi kontrakten håndhever seg selv. Programvare kan bare oppføre seg i henhold til sin egen kode. Den får input, bearbeider input, og leverer fra seg output, for eksempel i form av en transaksjon som overfører kryptokuponger til en mottaker.
Nick Szabo, som introduserte begrepet smarte kontrakter i 1990-årene, brukte brusautomaten som eksempel på en smart kontrakt. Du velger hva du vil ha og fyller på med den nødevndige summen med penger. Dette utløser en ugjenkallelig serie hendelser inne i automaten. Pengene blir tatt vare på, flaska hentes og leveres. Han så for seg at man kunne bygge en digital utgave av det samme som var i stand til å gjenspeile tradisjonelle kontrakter.
Ideen om smarte kontrakter er altså ikke bundet til blokkjeder. Man kunne sett for seg at en bank tillot deg å laste opp et program som forvalter pengene til firmaet ditt, og at banken var koblet til offentlige registre slik at programmet for eksempel kunne endre eierskapet til selskapets aksjer. Det ville verken banken eller de offentlige registrene ønsket å gjøre, men hvis de gjorde det, ville dette også vært en form for smarte kontrakter.
En smart kontrakt i en blokkjede har ikke tilgang på bankkontoen din eller til offentlig registre. Det den derimot har kontroll over, er kuponger og tilstandsdata på blokkjeden. Ettersom disse kupongene i dag kjøpes og selges for enorme summer, er resultatet litt det samme som om banken lot deg laste opp programmer med autoritet til å flyttet pengene dine.
Når du hører begrepet smart kontrakt, bør du altså se for deg bankutgaven av en brusautomat. Det kommer input. Dette utløser en ugjenkallelig serie hendelser inne i programmet. Dette fører til en output, for eksempel at en kupong endrer eier. Hvem som helst kan kode en slik automat, publisere den på blokkjeden, og oppfordre folk til å bruke den.
Turingkompletthet
Vi må skille mellom blokkjeder hvor de smarte kontraktene er turingkomplette og de hvor de ikke er turingkomplette. Et turingkomplett system (oppkalt etter Alan Turing) styres etter et regelsett som er så komplekst at du kan gjøre hva som helst med programmene dine. Alle utbredte programmeringsspråk er turingkomplette. Det er derfor noen kunne lage programmet eller appen du leser denne teksten på. Et system som ikke er turingkomplett, styres etter enklere regler, slik at det er mer begrenset hva man kan oppnå. Føringene legges av de som designer det underliggende systemet, mens det i et turingkomplett system er helt åpent hva man kan bygge.
Det er litt som forskjellen mellom Playmobil og Lego. Playmobil legger opp til helt bestemte måter å leke på. Legoklosser er så fleksible at de kan brukes til nesten hva som helst.
Bitcoin har smarte kontrakter som ikke er turingkomplette. Disse kan brukes til å utføre enkle operasjoner som Bitcoin-utviklerne har valgt å legge inn støtte for. (Noen Bitcoin-entusiaster er uenige og mener at Bitcoin Script er turingkomplett. Det er uansett ikke ment eller egnet til komplekse kontrakter.)
Ethereum var den første blokkjeden som hadde støtte for turingkomplette smarte kontrakter, og er fremdeles den viktigste plattformen for dette. Nesten alt innenfor web3-verden som ikke er Bitcoin eller Bitcoin-kloner, gjør bruk av denne typen smarte kontrakter.
Fordelen med turingkomplette systemer at du kan bruke dem til å utføre komplekse operasjoner som designerne av systemet ikke har tenkt på. Ulempen er at det er vanskelig å unngå feil. Her bruker jeg ordet “vanskelig” i flere betydninger. En av dem er “umulig”: Det er en del situasjoner i programvare det er umulig å forutse uten å kjøre selve programmet. Det klassiske eksempelet ble beskrevet av Alan Turing i 1936. Han beviste at det er umulig å lage en algoritme som kan fortelle deg om et gitt program kommer til å kjøre til evig tid eller ikke. Den eneste måten å finne ut dette på, er å kjøre programmet, og vente til det eventuelt gjør seg ferdig. Sagt på en annen måte: Når systemet kan gjøre hva som helst, kan du ikke vite sikkert hva det kommer til å gjøre før det gjør det.
Dette innebærer at når noen har lastet opp en smart kontrakt til Ethereum, og du skal vurdere om den kan brukes til å svindle deg, eller inneholder en alvorlig feil, (her er en oversikt over vanlige angrep), kan du ikke automatisere denne analysen på en måte som garantert gir deg det riktige svaret. Du kan lese koden, men kanskje overser du noe viktig. Du kan starte en lokal simulering av Ethereum og teste kontrakten der, men hvordan skal du teste samspillet mellom denne og andre kontrakter? Den eneste måten å vite sikkert, er å bruke kontrakten - og da er det allerede for sent.
Kanskje tar du også for gitt at økosystemet du kjører kontraktene i er stabilt, men det vi vet fra andre komplekse systemer den digitale verden er avhengig av, er at de ofte er skjøre byggverk hvor essensielle deler vedlikeholdes av noen få dårlig betalte utviklere, og det er ingen grunn til å tro at det er annerledes for smarte kontrakter.
Skyte seg selv i foten
Den andre betydningen av ordet vanskelig jeg har i tankene her er det som følger av hvordan et språk og et system er designet. Gode språk hjelper deg å skrive korrekt og forståelig programvare. I dårlige språk er det lettere å begå feil og vanskelig å forstå hva et program gjør.
Solidity, programmeringsspråket som brukes av Ethereum, er inspirert av JavaScript, et språk som er notorisk vanskelig å bruke riktig. Solidity har blitt kritisert for å bygge videre på denne tradisjonen på sine egne uransakelige måter. JavaScript brukes normalt til å lage webapplikasjoner. Syntaxen er ikke designet for å formulere komplekse kontraktsforhold. En annen ulempe med å legge syntaxen tett opp mot et kjent språk er at de som allerede kan JavaScript, lett vil ta for gitt at Solidity fungerer nøyaktig som JavaScript, og dermed bli overrasket av forskjellene. Overraskelser er det siste du vil ha fra en smart kontrakt.
Ethereum ignores all of this. Its standard contract language, Solidity, is a procedural language based on the web programming language JavaScript – to make it as easy as possible for beginners to write their first smart contract. It contains many constructs that mislead programmers coming from JavaScript into shooting themselves in the foot. It is ill-suited and hazardous for concurrency (e.g., the Solarstorm vulnerability), despite this being a specific intended use case. There are endless guides to writing a secure smart contract for Ethereum, but most Ethereum contracts ignore them, with the obvious consequences.
Å skyte seg selv i foten er et utviklerbegrep for det å bruke et verktøy på en dum måte med store konsekvenser. Du ønsker helst et språk som gjør det vanskelig å skyte deg selv i foten.
Den tredje måten det er vanskelig å unngå feil på har å gjøre med at det rett og slett bare er vanskelig å skrive programvare, uansett hvor gode språk og verktøy du har til rådighet. Programmerere gjør feil hele tiden. Noen ganger fordi vi er udugelige, andre ganger fordi vi er late eller har hastverk, og andre ganger igjen fordi systemet vi bygger er så komplekst at vi ikke klarer å se hele systemet foran oss mens vi jobber med det. Det finnes arbeidsrutiner som reduserer problemet, for eksempel automatiserte tester og kodegjennomgang, men ingen har funnet en måte å jobbe på som garantert fører til feilfri programvare.
Konsekvensene av dette veksler vanligvis mellom irriterende og ille. Det er irriterende når laptopen din låser seg og du må restarte den. Det er ille når en angriper låser datasystemene til organisasjonen din og krever løsepenger for å åpne dem opp igjen.
Skaden som kan forårsakes av tradisjonell programvare er likevel begrenset, fordi det dypeste nivået av samfunnet vårt ikke styres av programvare, men av lover og institusjoner. Altså mennesker. Du kan for eksempel hacke aksjonærregisteret hos Skatteetaten slik at det ser ut som om du eier selskapet mitt, men det er til syvende og sist myndighetene og rettsvesenet som bestemmer hvem som faktisk eier det. En hacker kan endre dataene som brukes i en rettsak, men de kan ikke hacke dommeren.
Ubegrenset skade
Det er denne begrensningen smarte kontrakter prøver å oppheve. Det sies ofte at prinsippet bak smarte kontrakter er at koden er loven, men det er ikke helt riktig. I smarte kontrakter er koden noe langt “bedre” enn loven: Den er et form for lovverk som håndhever seg selv, uten behov for byråkrater, politibetjenter, dommere og advokater.
Smarte kontrakter innfører i tillegg et ekstra vanskelighetsnivå ved at det er umulig å endre på kode du allerede har publisert til blokkjeden. Den må være perfekt på første forsøk.
Derfor blir også skaden langt større når programvaren inneholder feil, eller er designet for å brukes til svindel. Alle midlene kontrakten har kontroll over, står på spill. Selv om du oppdager feilen før den har blitt utnyttet, er det vanskelig å redde midlene dine.
I en av Nick Szabos artikler om smarte kontrakter foreslår han at de kunne skrives med et enkelt språk som er spesiallaget for kontrakter. Språket han foreslår fremstår ikke turingkomplett, men selv om det skulle være det, er det designet for å gjøre det lett å lage gode, oversiktlige kontrakter som kan analyseres for feil. Syntaksen tvinger deg til å tenke som en advokat.
Første gang jeg hørte kom smarte kontrakter på blokkjeden, så jeg for meg at de måtte fungere på samme måte. At man hadde designet et språk som la opp til at du skulle tenke mer som en advokat enn som en apputvikler. Dette ville skapt en høy terskel for nye utviklere, men det måtte da også vært en god ting? Vi vil vel ikke at hvem som helst skal hoppe rett uti dette?
Blokkjedeutviklerne ser ut til å ha tenkt omvendt: Gjør det lettest mulig for flest mulig å skrive smarte kontrakter, med et språk hvor du kan gjøre hva som helst og hvor det er lett å gjøre feil. Resultatet er deretter: Daglige svindler i størrelsesorden millioner av kroner.