Mining is in essentie een stuk ingewikkelder dan de eenvoudige samenvatting uit een eerder blog. Met name het maken van het blok is een stuk technischer. In de basis doet een miner het volgende:
- Nieuwe transacties worden bekend gemaakt aan alle ‘nodes’ in het netwerk (een node hoeft geen miner te zijn)
- Elke miner (een speciaal soort node) verzamelt transacties en verifieert of deze geldig zijn a.d.h.v. de bitcoin software/regels
- De miner voegt de transacties toe aan zijn ‘mem pool’ (inclusief de extra transactie m.b.t. de miner beloning; deze bitcoins worden dus puur gecreëerd door deze extra transactie genaamd de ‘coinbase’)
- De miner begint met het maken van een blok
- Block aanmaken
- Voordat het blok bekend gemaakt kan worden aan de nodes moet eerst een Proof of Work (PoW) gevonden worden
- Wanneer een node een PoW vind laat hij dit weten aan alle andere nodes
- De andere nodes accepteren het blok alleen als alle transacties erin geldig zijn, bitcoins niet dubbel worden uitgegeven etc. (checkt alle regels van de blockchain)
- De andere nodes accepteren het blok door te werken aan het creëren van een volgend blok (waarmee ze de hash van dit vorige geaccepteerde blok gebruiken in het nieuwe te creëren blok)
Stel je voor dat iemand een transactie in een blok wil manipuleren; dat blok wordt wellicht door een deel van het netwerk geaccepteerd maar er moet heel veel ondersteuning en rekenkracht komen wil deze afsplitsing van de blockchain uiteindelijk de juiste worden; het principe van nodes, miners en hun reward zorgt ervoor dat de langste chain altijd de juiste is.
Mining en het aanmaken van een block
- Het missende deel in bovenstaande samenvatting is het aanmaken van het block:
- Het begint met het hashen (dmv sha-256) van elke transactie in de mem pool
- De gehashte transacties worden georganiseerd in een merkle tree
- Een merkle tree bundelt de hashes van de transacties in paren en hasht het paar dan nogmaals; deze output wordt wederom nogmaals gehasht.
- De hoogste hash in de root heet de Merkle Root/Root Hash.
- De merkle root wordt in de header van het blok geplaatst (samen met de hash van het voorgaande blok en de nonce).
- De header van het blok wordt ook gehasht en de output hiervan vormt de unieke identificatie van het blok.
Laten we eens kijken hoe een block er uiteindelijk uit hoort te zien:
Een blockheader bestaat uit:
- Root hash
- Hash uit het vorige block
- Nonce
- Timestamp
Tx0, Tx1 etc. staat voor een transactie. Een normaal block bestaat uit honderden transacties.
Verder bestaat een block uit:
- Versie info
- Merkle root
- Target (in bits)
Nonce en hash
In het bitcoin-protocol worden hash-functies gebruikt om nieuwe transacties, veilig in een blok, in de blockchain te schrijven. Hashing is een wiskundig proces dat een invoer omzet in een unieke reeks met een vast aantal karakters. De grootte of type van de input maakt niet uit. Je kunt bijvoorbeeld een reeks letters van een willekeurige lengte als invoer nemen. Na de omzetting zal hier een reeks van letters met een vaste lengte uit komen. Wanneer er slechts één cijfer of getal wijzigt in de invoer, verandert de uitkomst van de hash compleet.
Hashen komt ook vaak voor bij het aanmaken van een wachtwoord bv voor toegang tot je webwinkel account of tot je gmail. Daarbij wordt je aangemaakte wachtwoord door een hashfunctie geleid en wordt de versleutelde hash van het wachtwoord opgeslagen. Je wachtwoord wordt dus omgezet naar een reeks getallen en cijfers (hash) en op die manier opgeslagen. Wanneer je inlogt met je wachtwoord, wordt gekeken of je wachtwoord overeen komt met de opgeslagen hash. Komt de uitkomst overeen met de opgeslagen hash? Dan is het wachtwoord in orde. Dit proces kan dus makkelijk de ene kant op (naar de hashwaardes), maar is bedoeld om het moeilijker te maken de andere kant op te gaan (naar de oorspronkelijke waardes) m.a.w. als je één hashwaarde ziet, kun je niet raden wat de invoer was. Behalve door verschillende invoergegevens te proberen, net zo lang totdat je de gezochte hashwaarde tegenkomt.
Je kunt hier het principe van het hashen zelf testen: https://xorbin.com/tools/sha256-hash-calculator
Het verwerken van een hash functie kost tijd en rekenkracht. De miner haalt de block header uit het block en haalt die data (input/transacties) door de hash functie en vormt een hash nummer (output). Deze bepaald of het blok geldig is of niet: het succesvol aanmaken van een blok mag alleen als de miner de juiste hash vind. Miners vinden dus de juiste hash door bij elke poging een andere variabele toe te voegen aan bepaalde data uit het blok (de transactie informatie/header) en door te voldoen aan de gestelde voorwaarde. Een willekeurig getal elke keer toevoegen aan transactiedata, om zo de hash te vinden die voldoet aan de voorwaarden en wat het blok een geldig blok maakt, noemen we de nonce. Het uiteindelijk nonce wat voor de juiste hash zorgt noem je de Golden Nonce.
Nonce voorbeeld
Stel de bekende transactie-informatie is als volgt: ‘Nick maakt 10 bitcoin over naar Simon.’
Stel de voorwaarde is als volgt: de hash moet beginnen met 3 nullen.
Poging 1 (nog zonder nonce)
Als we deze informatie door het SHA-256 algoritme halen krijgen we de volgende (ingekorte) hash: a43ce36e94fef1d…
Poging 2
Vervolgens voegen we na de transactie-informatie een getal toe, laten we beginnen met een één.
‘Nick maakt 10 bitcoin over naar Simon.1.’
De resulterende (wederom ingekorte) hash is: 5e26acb30149f66…
Poging 3 en 4
Daarna verhogen we onze toevoeging steeds met één. Wanneer we bij vier aankomen vinden we onze eerste nul! ‘Nick maakt 10 bitcoin over naar Simon.4.’ resulteert in de hash: 05ce3be1632b6d6…
Poging 20 en verder…
Pas bij de twintigste poging komen we uit op een hash die start met twee nullen. En veel later vinden we onze derde nul.
Het is voorspelbaar hoeveel verschillende nonces je moet proberen voordat je een hash hebt die aan de eisen voldoet. De hoeveelheid nullen die verwacht wordt is afhankelijk van de gemiddelde tijd tussen blokken.
Omdat alle miners elke keer een willekeurige nonce gebruiken, is het toeval welke miner als eerste een hash vindt die voldoet aan de target. De eerste miner die, dus per toeval, op de juiste hash stoot, zal dat blok bekendmaken aan het hele netwerk. Zo weten de andere miners ook dat ze niet meer verder moeten proberen om die bepaalde block te gaan encrypteren en kunnen ze op een volgende overschakelen.
Vanaf dat de juiste hash is gevonden, kan dat block volledig versleuteld (ge hasht) worden opgenomen in de blockchain, waar het dus helemaal veilig is en nooit meer kan aangepast worden.
Een belangrijk kenmerk van cryptografische hashfuncties is dat ze eenrichtingsverkeer zijn. Dit betekent dat het niet haalbaar is om de hash-invoer af te leiden door alleen naar de hash-uitvoer te kijken. Een controle of een hash correct is is wel eenvoudig te doen. Miners komen uiteindelijk op de juiste hash uit door de SHA-256 hash (Secure Hashing Algorith) functie toe te passen op de ‘block header’. SHA256 beschermt de blockchain tegen herschrijven.
Hashing power
Het aantal berekeningen dat de apparatuur van een miner uit kan voeren om de hash te raden noem je de hashing power oftewel de hash rate (uitgedrukt in hashes per seconde).
Hoe hoger de hashrate, hoe meer rekenkracht, en hoe hoger ook de moeilijkheidsgraad wordt om daarvoor te compenseren. Meer rekenkracht betekent dus niet dat er sneller blocks worden gemaakt, maar wel dat het netwerk veiliger wordt. Hoe hoger de hashrate, hoe moeilijker het voor een aanvaller wordt om transacties terug te draaien.
Kilo hashes – 1 kH/s is 1,000 (duizend) hashes per seconde
Mega hashes – 1 MH/s is 1,000,000 (miljoen) hashes per seconde
Giga hashes – 1 GH/s is 1,000,000,000 (miljard) hashes per seconde
Theta hashes – 1 TH/s is 1,000,000,000,000 (biljoen) hashes per seconde
Pheta hashes – 1 PH/s is 1,000,000,000,000,000 (biljard) hashes per seconde
Exa hashes – 1 EH/s is 1,000,000,000,000,000,000 (triljoen) hashes per seconde
De geschiedenis van de moeilijkheidsgraad, hashrate en het minen van 1 blok: https://btc.com/stats/diff
Een aantal voorbeelden uit deze geschiedenis:
Datum: 27-02-2009
Difficulty (moeilijkheidsgraad): 1
Hashrate: 4,21 MH/s (miljoen!)
Duur minen 1 blok: 17 minuten
Datum: 09-03-2011
Difficulty (moeilijkheidsgraad): 76.192 (duizend)\
Hashrate: 544,74 GH/s (miljard!)
Duur minen 1 blok: 7 minuten
Datum: 24-08-2013
Difficulty (moeilijkheidsgraad): 65.750.060 (miljoen)
Hashrate: 470,12 TH/s (biljoen!)
Duur minen 1 blok: 7 minuten
Datum: 24-11-2015
Difficulty (moeilijkheidsgraad): 72.722.780.642 (miljard)
Hashrate: 520,33 PH/s (biljard!)
Duur minen 1 blok: 9 minuten
Datum: 01-11-2018
Difficulty (moeilijkheidsgraad): 7.184.404.942.701 (biljoen)
Hashrate: 51,37 EH/s (triljoen!)
Duur minen 1 blok: 10 minuten
Datum: 26-03-2020
Difficulty (moeilijkheidsgraad): 13.912.524.048.945 (biljoen)
Hashrate: 99,59 EH/s (triljoen!)
Duur minen 1 blok: 12 minuten
Target
Een geldige hash is er een die voldoet aan een aantal voorwaarden. De belangrijkste van deze voorwaarden is het vinden van een hash waarde die kleiner dan of gelijk is aan het ‘target’. Alleen dan mag een miner succesvol het blok toevoegen aan de blockchain. De target geeft een bepaald doel aan wat behaald moet worden om te ‘winnen’ met minen. Het target wordt bepaald door de moeilijkheidsgraad (difficulty). De moeilijkheidsgraad geeft simpelweg aan hoe moeilijk het is om een target te vinden.
De moeilijkheidsgraad regelt de snelheid waarmee nieuwe blokken aan de blockchain worden toegevoegd. Het zorgt voor genoeg tijd tussen het verspreiden van blokken tussen nodes en zorgt voor een continue snelheid van uitgifte van bitcoins. Elke 2016 blocks (circa 2 weken) past het zich aan, waardoor de gemiddelde tijd voor het vinden van een block op circa 10 minuten ligt. Door dit algoritme krijgt Bitcoin een vast en voorspelbaar ritme in de productie van nieuwe blokken.
Hoe lager het target, hoe moeilijker het is om een blok te genereren (moeilijkheidsgraad is hoger).
Hoe hoger het target, hoe makkelijker het is om een blok te genereren (moeilijkheidsgraad is lager).
Stel je een dobbelsteen voor: de kans dat je minder dan 2 gooit is kleiner dan dat je minder dan 5 gooit. Minder dan 2 is een lager target maar heeft wel een hogere moeilijkheidsgraad.
De moeilijkheidsgraad is uiteraard afhankelijk van de hoeveelheid miners en daarmee dus de hoeveelheid rekenkracht van het netwerk (hash rate).
Meer miners?
-> moeilijkheidsgraad omhoog (dus meer voorloopnullen) -> target verlaagd (de te vinden hash is nu nog kleiner en dus moeilijker te vinden).
Minder miners?
-> moeilijkheidsgraad omlaag (dus minder voorloopnullen) -> target verhoogd (de te vinden hash is nu groter en dus makkelijker te vinden).
Een voorbeeld van een gebruikt target (ten tijde van februari 2019) is een hash wat moet bestaan uit eerst 18 of meer nullen.
Voorbeeld van hoe en wanneer de moeilijkheidsgraad wordt aangepast:
Elke node gebruikt de verwachte tijd dat het duurt om 2016 blokken te minen (2016 blokken x 10 minuten= 20.160) en deelt dit door de actuele tijd dat het geduurd heeft (in minuten).
Stel dat het 9 minuten heeft geduurd voor het minen van 2016 blokken dan krijg je dus 2016 x 9 = 18.144:
Verwachte tijd: actuele tijd
20.160 : 18.144 = 1.11
Elke node gebruikt dan dit nummer als nieuwe moeilijkheidsgraad.
Bij een uitkomst groter dan 1 (blokken worden sneller gemined als 10 minuten) gaat de moeilijkheidsgraad omhoog
Bij een uitkomst lager dan 1 (blokken worden langzamer gemined als 10 minuten) gaat de moeilijkheidsgraad omlaag.
Elke miner werkt met de nieuwe moeilijkheidsgraad voor de komende 2016 blokken.