Zum Hauptinhalt springen




Das Ziel de esta serie de tutoriales, es ayudarte a construir una imagen de cómo se podría desarrollar la tecnología de Blockchain. Puedes encontrar la parte 1 aquí: Construyendo tu propio Blockchain en JavaScript – Parte 1.

In diesem zweiten Tutorial werden wir ..:

  • Erstellen Sie eine einfache Brieftasche.
  • Senden Sie signierte Transaktionen mit unserer Blockchain.

All dies führt zu unserer eigenen Kryptowährung.

Wenn wir mit dem letzten Tutorial fortfahren, haben wir eine überprüfbare grundlegende Blockchain. Derzeit speichert unsere Kette jedoch nur ziemlich nutzlose Nachrichten. Heute werden wir diese Daten durch Transaktionen ersetzen ("Unser Block kann mehrere Transaktionen ausführen"), die es uns ermöglichen, eine zu erstellen Kryptowährung sehr einfach. Wir werden unsere neue Währung nennen "NoobCoin".

In diesem Lernprogramm wird davon ausgegangen, dass Sie dem anderen Lernprogramm gefolgt sind.

Abhängigkeiten: Sie müssen importieren Bounceycastle y GSON.

Bereiten Sie eine Brieftasche vor

In Kryptowährungen wird das Eigentum an der Währung als Transaktion auf die Blockchain übertragen, die Teilnehmer haben eine Adresse, an die das Geld gesendet werden kann. In ihrer Grundform können Brieftaschen diese Adressen einfach speichern, die meisten Brieftaschen jedoch auch Software in der Lage, neue Transaktionen in der durchzuführen Blockchain.

Erstellen wir also eine Klasse von Brieftasche um unseren öffentlichen und privaten Schlüssel zu behalten:

Paket-Noobchain; java.security importieren *; Wallet der öffentlichen Klasse {öffentlicher PrivateKey privateKey; öffentlicher PublicKey publicKey; }

Wofür sind öffentliche und private Schlüssel?

Für unser 'noobcoin' Der öffentliche Schlüssel fungiert als unsere Adresse. Es ist in Ordnung, diesen öffentlichen Schlüssel mit anderen zu teilen, um bezahlt zu werden. Unser privater Schlüssel wird verwendet, um unsere Transaktionen zu signieren, damit niemand unsere ausgeben kann Noobcoins eher als der Besitzer des privaten Schlüssels. Benutzer müssen ihren privaten Schlüssel geheim halten. Wir senden auch unseren öffentlichen Schlüssel zusammen mit der Transaktion und er kann verwendet werden, um zu überprüfen, ob unsere Signatur gültig ist und ob die Daten nicht geändert wurden.

Wir generieren unsere privaten und öffentlichen Schlüssel in a Schlüsselpaar. Wir werden die Kryptographie mit elliptischen Kurven verwenden, um unsere zu generieren Schlüsselpaare. Fügen wir eine Methode hinzu generateKeyPair () zu unserer Klasse Brieftasche und nennen wir es in der Erbauer:

Paket-Noobchain; java.security importieren *; Wallet der öffentlichen Klasse {öffentlicher PrivateKey privateKey; öffentlicher PublicKey publicKey; öffentliche Brieftasche () {generateKeyPair (); } public void generateKeyPair () {try {KeyPairGenerator keyGen = KeyPairGenerator.getInstance ("ECDSA", "BC"); SecureRandom random = SecureRandom.getInstance ("SHA1PRNG"); ECGenParameterSpec ecSpec = neue ECGenParameterSpec ("prime192v1"); // Schlüsselgenerator initialisieren und KeyPair generieren keyGen.initialize (ecSpec, random); // 256 Byte bieten eine akzeptable Sicherheitsstufe KeyPair keyPair = keyGen.generateKeyPair (); // Konfigurieren Sie den öffentlichen und den privaten Schlüssel aus dem keyPair privateKey = keyPair.getPrivate (); publicKey = keyPair.getPublic (); } catch (Exception e) {throw new RuntimeException (e); }}}

Nachdem wir nun die Umrisse unserer Wallet-Klasse kennen, werfen wir einen Blick auf die Transaktionen.

Transaktionen und Signaturen

Jede Transaktion enthält eine bestimmte Datenmenge:

  • Der öffentliche Schlüssel (Adresse) des Absenders der Fonds.
  • Die öffentlichen Schlüssel des Empfängers der Mittel.
  • Der Wert / Betrag der zu überweisenden Mittel.
  • Eingaben, die auf frühere Transaktionen verweisen, die belegen, dass der Absender über zu sendende Mittel verfügt.
  • Ausgaben, die die Anzahl der relevanten Adressen anzeigen, die in der Operation empfangen wurden. (Diese Ausgaben werden als Eingaben für neue Transaktionen bezeichnet.)
  • Eine kryptografische Signatur, die beweist, dass der Eigentümer der Adresse derjenige ist, der die Transaktion sendet, und dass die Daten nicht geändert wurden. (Beispiel: Verhindern Sie, dass Dritte den gesendeten Betrag ändern.)

Erstellen wir diese neue Transaktionsklasse:

java.security importieren *; import java.util.ArrayList; öffentliche Klasse Transaktion {öffentliche Zeichenfolge Transaktions-ID; // Dies ist auch der Hash der Transaktion. öffentlicher PublicKey-Absender; // Absenderadresse / öffentlicher Schlüssel. öffentlicher PublicKey-Empfänger; // Empfängeradresse / öffentlicher Schlüssel. öffentlicher Float-Wert; öffentliches Byte [] Signatur; // Dies soll verhindern, dass jemand anderes Geld in unserer Brieftasche ausgibt. öffentliche ArrayList-Eingaben = neue ArrayList (); öffentliche ArrayList-Ausgaben = new ArrayList (); private statische int-Sequenz = 0; // eine ungefähre Anzahl der generierten Transaktionen. // Konstruktor: public Transaction (PublicKey from, PublicKey to, float value, ArrayList Eingaben) {this.sender = from; this.reciepient = to; this.value = Wert; this.inputs = Eingänge; } // Berechne den Hash der Transaktion (wird als Id verwendet) private String calulateHash () {sequence ++; // Erhöhen Sie die Sequenz, um 2 identische Transaktionen mit demselben Hash zu vermeiden Rückgabe StringUtil.applySha256 (StringUtil.getStringFromKey (Sender) + StringUtil.getStringFromKey (Empfänger) + Float.toString (Wert) + Sequenz); }}

Wir müssen auch leere Klassen erstellen TransactionInput y TransactionOutput, Keine Sorge, wir können sie später ausfüllen.

Unsere Transaktionsklasse enthält auch relevante Methoden zum Generieren / Überprüfen der Signatur und zum Überprüfen der Transaktion.

Was ist der Zweck von Signaturen und wie funktionieren sie?

Firmen führen zwei sehr wichtige Aufgaben in unserer Blockchain aus: Erstens erlauben sie nur dem Eigentümer, ihre Münzen auszugeben; Zweitens verhindern sie, dass andere die präsentierte Transaktion manipulieren, bevor ein neuer Block extrahiert wird (am Einstiegspunkt).

Der private Schlüssel wird zum Signieren der Daten verwendet, und der öffentliche Schlüssel kann zum Überprüfen der Integrität verwendet werden.

Beispiel: James möchte 2 NoobCoins an Allie senden, daher generiert seine Brieftaschensoftware diese Transaktion und sendet sie an die Bergleute, um sie in den nächsten Block aufzunehmen. Ein Bergmann versucht, den Empfänger der 2 Münzen in Juan zu ändern. Glücklicherweise hatte James die Transaktionsdaten jedoch mit seinem privaten Schlüssel signiert, sodass jeder überprüfen konnte, ob die Transaktionsdaten mit dem öffentlichen Schlüssel von James geändert wurden (da keine andere Person die Transaktion überprüfen kann).

Wir können (aus dem obigen Codeblock) sehen, dass unsere Signatur ein Bündel von Bytes ist. Erstellen wir also eine Methode, um sie zu generieren. Das erste, was wir brauchen, sind ein paar Hilfsfunktionen in der Klasse StringUtil :

// Wenden Sie die ECDSA-Signatur an und geben Sie das Ergebnis (in Bytes) zurück. öffentliches statisches Byte [] applyECDSASig (PrivateKey privateKey, String-Eingabe) {Signature dsa; Byte [] Ausgabe = neues Byte [0]; try {dsa = Signature.getInstance ("ECDSA", "BC"); dsa.initSign (privateKey); byte [] strByte = input.getBytes (); dsa.update (strByte); Byte [] realSig = dsa.sign (); Ausgabe = realSig; } catch (Exception e) {throw new RuntimeException (e); } Ausgabe zurückgeben; } // Eine String-Signatur überprüfen public static boolean verifyECDSASig (PublicKey publicKey, String data, byte [] signature) {try {Signature ecdsaVerify = Signature.getInstance ("ECDSA", "BC"); ecdsaVerify.initVerify (publicKey); ecdsaVerify.update (data.getBytes ()); ecdsaVerify.verify (Signatur) zurückgeben; } catch (Exception e) {throw new RuntimeException (e); }} public static String getStringFromKey (Schlüsselschlüssel) {return Base64.getEncoder ().encodeToString (key.getEncoded ()); }

Jetzt werden wir diese Signaturmethoden in unserer Klasse verwenden Transaktion, Hinzufügen der Methoden generateSignature () y verifiySignature ():

// Unterschreiben Sie alle Daten, die nicht geändert werden sollen. public void generateSignature (PrivateKey privateKey) {String data = StringUtil.getStringFromKey (Sender) + StringUtil.getStringFromKey (Empfänger) + Float.toString (Wert); Signatur = StringUtil.applyECDSASig (privateKey, Daten); } // Überprüfen Sie, dass die von uns signierten Daten nicht geändert wurden public boolean verifiySignature () {String data = StringUtil.getStringFromKey (sender) + StringUtil.getStringFromKey (reciepient) + Float.toString (value); StringUtil.verifyECDSASig zurückgeben (Absender, Daten, Signatur); }

Die Signaturen werden von den Bergleuten überprüft, wenn eine neue Transaktion zu einem Block hinzugefügt wird.

Nachweis von Brieftaschen und Unterschriften

Jetzt sind wir fast auf halbem Weg und probieren einige Dinge aus, die funktionieren. In der Klasse NoobChain agreguemos algunas variables nuevas y reemplacemos el Inhalt de nuestro método principal:

import java.security.Security; import java.util.ArrayList; java.util.Base64 importieren; com.google.gson.GsonBuilder importieren; öffentliche Klasse NoobChain {öffentliche statische ArrayList-Blockchain = neue ArrayList (); öffentlicher statischer int-Schwierigkeitsgrad = 5; öffentliche statische Wallet-WalletA; öffentliches statisches Wallet-WalletB; public static void main (String [] args) {// Konfigurieren Sie Bounceys Schloss als Sicherheitsanbieter Security.addProvider (new org.bouncycastle.jce.provider.BouncyCastleProvider ()); // Erstellen Sie die neuen Wallets WalletA = new Wallet (); BrieftascheB = neue Brieftasche (); // Testen von öffentlichen und privaten Schlüsseln System.out.println ("Private und öffentliche Schlüssel:"); System.out.println (StringUtil.getStringFromKey (WalletA.privateKey)); System.out.println (StringUtil.getStringFromKey (WalletA.publicKey)); // Erstellen Sie eine Testtransaktion von WalletA zu WalletB Transaction transaction = new Transaction (walletA.publicKey,walletB.publicKey, 5, null); Transaktion.generateSignature (WalletA.privateKey); // Überprüfen Sie die Funktion der Signatur und überprüfen Sie sie anhand des öffentlichen Schlüssels System.out.println ("Die Signatur wird überprüft"); System.out.println (transaction.verifiySignature ()); }

Inputs &Ampere; Outputs 1: Cómo se posee la divisa criptográfica….

Damit Sie eine (1) Bitcoin haben, müssen Sie 1 Bitcoin erhalten. Das Hauptbuch fügt keine Bitcoin-Münze hinzu und abzüglich einer Bitcoin-Münze vom Absender verweist der Absender darauf, dass er zuvor eine Bitcoin-Münze erhalten hat. Anschließend wurde eine Transaktionsausgabe erstellt, aus der hervorgeht, dass 1 Bitcoin an Ihre Adresse gesendet wurde. (Transaktionseinträge sind Verweise auf frühere Transaktionsausgänge.)

Ihr Brieftaschenguthaben ist die Summe aller nicht verwendeten Transaktionsausgaben, die an Sie gerichtet sind.

Ab diesem Zeitpunkt folgen wir der Bitcoin-Konvention und rufen die nicht verwendeten Transaktionsausgaben auf: UTXOs.

Erstellen wir also eine Transaktionseingabeklasse:

öffentliche Klasse TransactionInput {öffentlicher String transactionOutputId; // Referenz auf TransactionOutputs -> TransactionId public TransactionOutput UTXO; // Enthält die nicht verwendete Transaktionsausgabe public TransactionInput (String transactionOutputId) {this.transactionOutputId = transactionOutputId; }}

Und eine Klasse TransactionOutputs:

import java.security.PublicKey; öffentliche Klasse TransactionOutput {öffentliche String-ID; öffentlicher PublicKey-Empfänger; // auch bekannt als der neue Besitzer dieser Münzen. öffentlicher Float-Wert; // die Anzahl der Währungen mit öffentlichem String parentTransactionId; // der Bezeichner der Transaktion, in der diese Ausgabe erstellt wurde // öffentlicher TransactionOutput-Konstruktor (PublicKey-Empfänger, Gleitkommawert, String parentTransactionId) {this.reciepient = Empfänger; this.value = Wert; this.parentTransactionId = parentTransactionId; this.id = StringUtil.applySha256 (StringUtil.getStringFromKey (Empfänger) + Float.toString (Wert) + parentTransactionId); } // Prüft, ob die Währung Ihnen gehört public boolean isMine (PublicKey publicKey) {return (publicKey == Empfänger); }}

Die Ergebnisse der Transaktion zeigen den endgültigen Betrag, der an jede Partei der Transaktion gesendet wurde. Wenn diese als Einträge in neuen Transaktionen erwähnt werden, dienen sie als Beweis dafür, dass Sie Münzen senden müssen.

Ein- und Ausgänge 2: Abwicklung der Transaktion….

Die Blöcke in der Kette können viele Transaktionen empfangen und die Blockkette kann sehr, sehr lang sein. Es kann Äonen dauern, bis eine neue Transaktion verarbeitet ist, da wir ihre Eingaben finden und überprüfen müssen. Um dies zu vermeiden, werden wir eine zusätzliche Sammlung aller nicht ausgegebenen Transaktionen aufbewahren, die als Eingaben verwendet werden können. In unserer Klasse NoobChain füge diese Sammlung von allen hinzu UTXOs:

öffentliche Klasse NoobChain {öffentliche statische ArrayList-Blockchain = neue ArrayList (); öffentliche statische HashMap UTXOs = neue HashMap (); // Liste aller nicht ausgegebenen Transaktionen. öffentlicher statischer int-Schwierigkeitsgrad = 5; öffentliche statische Wallet-WalletA; öffentliches statisches Wallet-WalletB; public static void main (String [] args) {

Jetzt werden wir alles zusammenfügen, um die Transaktion mit einer booleschen Methode zu verarbeiten processTransaction in unserer Klasse Transaktion:

// Gibt true zurück, wenn eine neue Transaktion erstellt werden konnte. public boolean processTransaction () {if (verifiySignature () == false) {System.out.println ("#la Signatur der Transaktion wurde nicht verifiziert"); falsch zurückgeben; } // Sammeln Sie die Transaktionsdaten (stellen Sie sicher, dass sie nicht ausgegeben wurden): for (TransactionInput i: input) {i.UTXO = NoobChain.UTXOs.get (i.transactionOutputId); } // Überprüfen Sie, ob die Transaktion gültig ist: if (getInputsValue () <NoobChain.minimumTransaction) {System.out.println ("# kleine Transaktionseingaben:" + getInputsValue ()); falsch zurückgeben; } // Transaktionsergebnisse generieren: float leftOver = getInputsValue () - value; // Wert der Eingaben abrufen, dann die übrig gebliebene Änderung: transactionId = calulateHash (); output.add (new TransactionOutput (this.reciepient, value, transactionId)); // Wert an Empfänger senden output.add (new TransactionOutput (this.sender, leftOver, transactionId)); // die 'Änderung' zurück an den Absender senden // Ausgaben zur Liste der nicht verwendeten Produkte hinzufügen für (TransactionOutput o: Ausgaben) {NoobChain.UTXOs.put (o.id, o); } // Transaktionseinträge wie ausgegeben aus UTXO-Listen entfernen: for (TransactionInput i: input) {if (i.UTXO == null) continue; // wenn Transaktion nicht gefunden werden kann NoobChain.UTXOs.remove (i.UTXO.id); } true zurückgeben; } // gibt die Summe der Eingabewerte (UTXOs) zurück public float getInputsValue () {float total = 0; for (TransactionInput i: Eingaben) {if (i.UTXO == null) fortsetzen; // Wenn die Transaktion nicht gefunden werden kann, überspringen Sie sie. Gesamt + = i.UTXO.Wert; } Gesamtsumme zurückgeben; } // gibt die Summe der Ausgaben zurück: public float getOutputsValue () {float total = 0; for (TransactionOutput o: Ausgaben) {total + = o.value; } Gesamtsumme zurückgeben; }

… Mit dieser Methode führen wir einige Überprüfungen durch, um sicherzustellen, dass die Transaktion gültig ist. Dann sammeln wir Eingaben und generieren Ausgaben. (Weitere Informationen finden Sie in den kommentierten Zeilen im Code.)

Wichtig ist, dass wir gegen Ende die Eingaben aus unserer UTXO-Liste verwerfen, was bedeutet, dass eine Transaktionsausgabe nur einmal als Eingabe verwendet werden kann ... Daher muss der volle Wert der Eingaben verwendet werden, sodass der Absender die " ändern "zu sich selbst.

Endlich werden wir unsere Brieftasche aktualisieren auf:

Sammeln Sie unser Guthaben (durchlaufen Sie die Liste der UTXOs und prüfen Sie, ob die Ausgabe einer Transaktion Mine () ist)
Und Transaktionen für uns generieren….

java.security importieren *; import java.security.spec.ECGenParameterSpec; import java.util.ArrayList; import java.util.HashMap; java.util.Map importieren; Wallet der öffentlichen Klasse {öffentlicher PrivateKey privateKey; öffentlicher PublicKey publicKey; öffentliche HashMap UTXOs = neue HashMap (); // nur UTXOs, die dieser Wallet gehören. public Wallet () {... public void generateKeyPair () {... // Gibt den Saldo zurück und speichert die UTXOs, die dieser Wallet gehören, in this.UTXOs public float getBalance () {float total = 0; für (Map.Eintrag item: NoobChain.UTXOs.entrySet ()) {TransactionOutput UTXO = item.getValue (); if (UTXO.isMine (publicKey)) {// wenn die Ausgabe mir gehört (wenn die Währungen mir gehören) UTXOs.put (UTXO.id, UTXO); // fügen Sie es unserer Liste der nicht ausgegebenen Transaktionen hinzu. Gesamt + = UTXO.Wert; }} Gesamtsumme zurückgeben; } // Eine neue Transaktion aus diesem Wallet generieren und zurückgeben. öffentliche Transaktion sendFunds (PublicKey _recipient, float value) {if (getBalance () <value) {// Saldo sammeln und Geld verifizieren. System.out.println ("#De sind nicht genügend Guthaben zum Senden der Transaktion vorhanden. Transaktion verworfen."); Null zurückgeben; } // Array-Liste der Eingaben erstellen ArrayList input = new ArrayList (); Gesamtschwimmer = 0; für (Map.Eintrag item: UTXOs.entrySet ()) {TransactionOutput UTXO = item.getValue (); Gesamt + = UTXO.Wert; input.add (neuer TransactionInput (UTXO.id)); if (total> value) break; } Transaktion newTransaction = new Transaction (publicKey, _recipient, value, input); newTransaction.generateSignature (privateKey); for (TransactionInput Eingabe: Eingaben) {UTXOs.remove (input.transactionOutputId); } return newTransaction; }}

Hinzufügen von Transaktionen zu unseren Blöcken:

Jetzt, da wir ein funktionierendes Transaktionssystem haben, müssen wir es in unserer Blockchain implementieren. Wir sollten die nutzlosen Daten, die wir in unseren Blöcken hatten, durch eine ArrayList von Transaktionen ersetzen. Es kann jedoch Tausende von Transaktionen in einem einzelnen Block geben, zu viele, um sie in unsere Hash-Berechnung einzubeziehen ... aber keine Sorge, wir können die Merkle-Wurzel der Transaktionen verwenden (Sie können hier * bald schnell etwas über Merkle-Bäume lesen *).

Fügen wir eine Hilfsmethode hinzu, um das Merkleroot in StringUtils zu generieren:

// Führen Sie eine Reihe von Transaktionen durch und geben Sie eine Merkle-Wurzel zurück. public static String getMerkleRoot (ArrayList-Transaktionen) {int count =transaktionen.size (); ArrayList previousTreeLayer = new ArrayList(); for (Transaktionstransaktion: Transaktionen) { previousTreeLayer.add (transaction.transactionId); } ArrayList treeLayer = previousTreeLayer; while (count> 1) {treeLayer = new ArrayList (); for (int i = 1; i <vorherigeTreeLayer.size (); i ++) {treeLayer.add (applySha256 (vorherigeTreeLayer.get (i-1) + previousTreeLayer.get (i))); } count = treeLayer.size (); previousTreeLayer = treeLayer; } String merkleRoot = (treeLayer.size () == 1)? treeLayer.get (0): ""; merkleRoot zurück; }

Jetzt werden wir unsere Änderungen in der Blockklasse implementieren:

import java.util.ArrayList; java.util.Datum importieren; öffentliche Klasse Block {öffentlicher String-Hash; public String previousHash; öffentlicher String merkleRoot; öffentliche ArrayList-Transaktionen = neue ArrayList (); // Unsere Daten werden eine einfache Nachricht sein. öffentlicher langer Zeitstempel; // als Anzahl der Millisekunden seit dem 1.1.1970. öffentliche int nonce; // Blockkonstruktor. öffentlicher Block (String previousHash) {this. previousHash = previousHash; this.timeStamp = neues Datum ().getTime (); this.hash = berechneHash (); // Stellen Sie sicher, dass wir dies tun, nachdem wir die anderen Werte festgelegt haben. } // Berechne neuen Hash basierend auf dem Inhalt der Blöcke public String computeHash () {Stringcalculatedhash = StringUtil.applySha256 (vorherigerHash + Long.toString (timeStamp) + Integer.toString (nonce) + merkleRoot); berechneten Hash zurückgeben; } // Erhöhen Sie den Wert von Nonce, bis das Hash-Ziel erreicht ist. public void mineBlock (int-Schwierigkeit) {merkleRoot = StringUtil.getMerkleRoot (Transaktionen); String-Ziel = StringUtil.getDificultyString (Schwierigkeit); // Erzeuge einen String mit Schwierigkeit * "0" while (! Hash.substring (0, Schwierigkeit) .equals (target)) {nonce ++; hash = berechneHash(); } System.out.println ("Block abgebaut !!!:" + Hash); } // Transaktionen zu diesem Block hinzufügen public boolean addTransaction (Transaktionstransaktion) {// Transaktion verarbeiten und prüfen, ob sie gültig ist, es sei denn, der Block ist ein Genesis-Block und dann ignorieren. if (Transaktion == null) return false; if ((vorherigerHash! = "0")) {if ((transaction.processTransaction ()! = true)) {System.out.println ("Transaktion konnte nicht verarbeitet werden. Verworfen."); falsch zurückgeben; }} Transaktionen.add (Transaktion); System.out.println ("Transaktion erfolgreich zu Block hinzugefügt"); true zurückgeben; }}

Beachten Sie, dass wir auch unseren Blockkonstruktor aktualisieren, da wir die Zeichenfolgendaten nicht übergeben und die Wurzel von einschließen müssen merkle in der Hash-Berechnungsmethode.

Unsere boolesche Methode addTransaction Die Transaktionen werden hinzugefügt und nur dann true zurückgegeben, wenn die Transaktion erfolgreich hinzugefügt wurde.

Das große Finale (Am Anfang gab es keine Münzen):

Wir sollten das Senden von Münzen an und von Brieftaschen testen und unsere Blockchain-Gültigkeitsprüfung aktualisieren. Aber zuerst brauchen wir einen Weg, um neue Münzen in die Mischung einzuführen. Es gibt viele Möglichkeiten, neue Münzen zu erstellen, beispielsweise in der Bitcoin-Blockchain: Bergleute können eine Transaktion für sich selbst als Belohnung für jeden abgebauten Block einschließen. Im Moment werden wir jedoch nur alle Münzen freigeben, die wir im ersten Block (dem Genesis-Block) haben möchten. Wie Bitcoin werden wir den Genesis-Block codieren.

Wir werden unsere NoobChain-Klasse mit allem aktualisieren, was sie benötigt:

  • Ein Genesis-Block, der 100 Noobcoins für die Brieftasche freigibt.
  • Eine aktualisierte Gültigkeitsprüfung für Zeichenfolgen, die Vorgänge berücksichtigt.
  • Einige Testtransaktionen, um zu sehen, dass alles funktioniert.
öffentliche Klasse NoobChain {öffentliche statische ArrayList-Blockchain = neue ArrayList (); öffentliche statische HashMap UTXOs = neue HashMap (); öffentlicher statischer int-Schwierigkeitsgrad = 3; public static float minimumTransaction = 0.1f; öffentliche statische Wallet-WalletA; öffentliches statisches Wallet-WalletB; öffentliche statische Transaktion genesisTransaction; public static void main (String [] args) {// füge unsere Blöcke zur Liste hinzu ArrayList of blocks: Security.addProvider (new org.bouncycastle.jce.provider.BouncyCastleProvider ()); // Hüpfburg als Sicherheitsanbieter einrichten // Wallets erstellen WalletA = new Wallet (); BrieftascheB = neue Brieftasche (); Wallet-Coinbase = neue Wallet (); // eine Genesis-Transaktion erstellen, die 100 NoobCoin an WalletA sendet: genesisTransaction = new Transaction (coinbase.publicKey, WalletA.publicKey, 100f, null); genesisTransaction.generateSignature (coinbase.privateKey); // Genesis-Transaktion manuell signieren genesisTransaction.transactionId = "0"; // Transaktions-ID manuell setzen genesisTransaction.outputs.add (new TransactionOutput (genesisTransaction.reciepient, genesisTransaction.value, genesisTransaction.transactionId)); // Transaktionsausgabe manuell hinzufügen UTXOs.put (genesisTransaction.outputs.get (0) .id, genesisTransaction.outputs.get (0)); // Es ist wichtig, unsere erste Transaktion in der Liste der UTXOs zu speichern. System.out.println ("Erstellung und Nutzung des Genesis-Blocks ...."); Blockgenese = neuer Block ("0"); genesis.addTransaction (genesisTransaction); addBlock (Genese); // Testblock block1 = neuer Block (genesis.hash); System.out.println ("nDas Guthaben von WalletA ist:" + WalletA.getBalance ()); System.out.println ("nWalletA versucht, Gelder (40) an WalletB zu senden ..."); block1.addTransaction (walletA.sendFunds (walletB.publicKey, 40f)); addBlock (block1); System.out.println ("n WalletA's Guthaben ist:" + WalletA.getBalance ()); System.out.println ("WalletBs Guthaben ist:" + WalletB.getBalance ()); Block block2 = neuer Block (block1.hash); System.out.println ("nWalletA Versucht, mehr Geld (1000) zu senden, als es hat ..."); block2.addTransaction (walletA.sendFunds (walletB.publicKey, 1000f)); addBlock (Block2); System.out.println ("WalletA's Guthaben ist:" + WalletA.getBalance ()); System.out.println ("WalletBs Guthaben ist:" + WalletB.getBalance ()); Block block3 = neuer Block (block2.hash); System.out.println ("nWalletB versucht, Gelder (20) an WalletA zu senden ..."); block3.addTransaction (walletB.sendFunds (walletA.publicKey, 20)); System.out.println ("WalletA's Guthaben ist:" + WalletA.getBalance ()); System.out.println ("WalletBs Guthaben ist:" + WalletB.getBalance ()); isChainValid(); } public static Boolean isChainValid () {Block currentBlock; Vorhergehend blockierenBlockieren; String hashTarget = new String (neues Zeichen [Schwierigkeit]) Ersetzen ('', '0'); HashMap tempUTXOs = neue HashMap (); // eine temporäre Arbeitsliste nicht ausgegebener Transaktionen in einem bestimmten Blockstatus. tempUTXOs.put (genesisTransaction.outputs.get (0) .id, genesisTransaction.outputs.get (0)); // durch die Blockchain, um die Hashes zu überprüfen: for (int i = 1; i <blockchain.size (); i ++) {currentBlock = blockchain.get (i); previousBlock = blockchain.get (i-1); // vergleiche registrierten Hash und berechneten Hash: if (! currentBlock.hash.equals (currentBlock.calculateHash ())) {System.out.println ("Current #Hashes are not equal"); falsch zurückgeben; } // vergleiche den vorherigen Hash und den zuvor registrierten Hash if (! previousBlock.hash.equals (currentBlock. previousHash)) {System.out.println ("Vorherige #Hashes sind nicht gleich"); falsch zurückgeben; } // prüfen, ob das Hashing-Problem gelöst ist if (! currentBlock.hash.substring (0, Schwierigkeit) .equals (hashTarget)) {System.out.println ("#Edieser Block wurde nicht abgebaut"); falsch zurückgeben; } // durch Sperren von Transaktionen: TransactionOutput tempOutput; für (int t = 0; t <currentBlock.transactions.size(); t++) {
Transaction currentTransaction = currentBlock.transactions.get(t);

if(!currentTransaction.verifiySignature()) {
System.out.println("#La firma en la transacción (" + t + ") es inválida");
return false;
}
if(currentTransaction.getInputsValue() != currentTransaction.getOutputsValue()) {
System.out.println("#Las entradas son iguales a las salidas en la transacción(" + t + ")");
return false;
}

for(TransactionInput input: currentTransaction.inputs) {
tempOutput = tempUTXOs.get(input.transactionOutputId);

if(tempOutput == null) {
System.out.println("#Falta la entrada referenciada en Transacción(" + t + ")");
return false;
}

if(input.UTXO.value != tempOutput.value) {
System.out.println("#El valor de la entrada referenciada Transacción(" + t + ") es inválido");
return false;
}

tempUTXOs.remove(input.transactionOutputId);
}

for(TransactionOutput output: currentTransaction.outputs) {
tempUTXOs.put(output.id, output);
}

if( currentTransaction.outputs.get(0).reciepient != currentTransaction.reciepient) {
System.out.println("#El destinatario de la salida de la transacción (" + t + ") no es quien debería ser");
return false;
}
if( currentTransaction.outputs.get(1).reciepient != currentTransaction.sender) {
System.out.println("#Transacción(" + t + ") salida 'cambio' no es el remitente.");
return false;
}

}

}
System.out.println("La Blockchain es válida");
return true;
}

public static void addBlock(Block newBlock) {
newBlock.mineBlock(difficulty);
blockchain.add(newBlock);
}
}

Brieftaschen können jetzt sicher Geld in Ihrer Blockchain senden, nur wenn sie über Geld verfügen, um sie zu senden. Dies bedeutet, dass Sie Ihre eigene lokale Kryptowährung haben.

Sie sind mit den Transaktionen in Ihrer Blockchain fertig!

Sie haben erfolgreich Ihre eigene Kryptowährung erstellt. Deine Bockchain jetzt:

  • Ermöglicht Benutzern das Erstellen von Portfolios mit "new Portfolio ();".
  • Bietet Brieftaschen mit öffentlichen und privaten Schlüsseln mithilfe der Kryptografie mit elliptischen Kurven.
  • Asegura la transferencia de fondos, utilizando un Algorithmus de firma digital para probar la propiedad.
  • Und schließlich können Benutzer Transaktionen in ihrer Blockchain mit durchführen 'Block.addTransaction (walletA.sendFunds (walletB.publicKey, 20));'; »Block.addTransaction (walletA.sendFunds (walletB.publicKey, 20)); '.

Play-to-Earn-Spiele

Die Videospielindustrie befindet sich in einer Phase intensiven Wachstums und das „Play to Win“-System eröffnet neue Möglichkeiten für Blockchain-Gaming.

Spieler dieses Geschäftsmodells schaffen Wert für Spieleentwickler und andere Spieler, indem sie an der Spieleökonomie teilnehmen. Als Belohnung für ihre Teilnahme erhalten sie Spiel-Assets. Diese Assets reichen von Spielressourcen wie Spieltools, Waffen oder Kryptowährungen bis hin zu anderen Spielassets, die in der Blockchain tokenisiert und sogar als NFTs verkauft werden können. Aus diesem Grund hat sich das „Play-to-Earn“-Geschäftsmodell bei Blockchain-Spielen bewährt. Die Gesamteinnahmen aus dem Play-to-Earn-Spiel, Axie Unendlichkeit, Ich kenne näherte sich USD 120 Millionen im Juli.