[PYTHON] Ich habe versucht, eine Blockchain zu implementieren, die tatsächlich mit ungefähr 170 Zeilen funktioniert

Dieser Artikel ist der 6. Tag von Blockchain Adventskalender 2019. Gestern war @ y-chans Atomtausch verstehen.


Was ist passiert

"Es gibt viele Blockchain-Kommentarbücher, aber ich bin mir nicht sicher, wie sie am Ende funktionieren werden." "Strukturelle Blockchain scheint einfach zu sein, aber ich bin mir nicht sicher, wie ich den Inhalt des Blocks erstellen soll oder wie das Mining funktioniert."

ich dachte "Wenn Sie die Erklärung nicht verstehen, sollten Sie versuchen, sie zu implementieren. Es ist ein Programmierer von Mumuo." Also habe ich es implementiert.

Das Unterrichtsmaterial stammt von Gerald Nash

--Teil.1 Erstellen wir die kleinste Blockchain (Erstellen wir eine sehr kleine Blockchain) --Teil.2 Machen wir die kleinste Blockchain größer (Machen wir eine sehr kleine Blockchain)

ist.

Voraussetzungen

Geralds Artikel, der als Lehrmaterial verwendet wurde, wurde in Python2 implementiert, daher wurde er in Python3 (3.5) erneut implementiert. Übrigens repariere ich einige Teile wie "Ist das nicht die bessere Verarbeitungsreihenfolge?" Oder "Ich rufe Sie nicht nur an, um dies zu tun." Im ursprünglichen Artikel habe ich den Importteil des geteilten Codes weggelassen, aber in diesem Artikel werde ich ihn mit dem Code beschreiben, der funktioniert [^ 1]. Außerdem sind die Kommentare im Code nicht auf den Originalartikel beschränkt und können bei Bedarf frei hinzugefügt werden.

Der gesamte erstellte Quellcode wird unter der Annahme beschrieben, dass er sich im selben Verzeichnis befindet.

[^ 1]: Selbst im Originalartikel wird der Quellcode in voller Größe auf Gist veröffentlicht, aber es gab einige Dinge wie "Sie verwenden dies nicht, oder?". Also behebe ich es.

Implementierungsauftrag

――Der Bereich "Machen wir eine sehr kleine Blockchain" (ca. 50 Zeilen)

  1. Blockieren Sie die Implementierung
  2. Überprüfen Sie die Funktion der Blockchain ――Der Bereich "Machen wir eine sehr kleine Blockchain groß" (ca. 130 Zeilen)
  3. Registrieren Sie die Transaktion und fügen Sie einen neuen Block hinzu

Wir werden in der Reihenfolge von implementieren. Die Gesamtzahl der Zeilen ohne Kommentarzeilen betrug ca. 170.

Es ist Zeit zu implementieren

Blockieren Sie die Implementierung

Implementieren Sie zuerst den Block. Es ist eine sogenannte Bergbaueinheit. Die enthaltenen Informationen sind

--Indexinformationen

Wird sein.

snakecoin_block.py



import hashlib

class Block:
  def __init__(self, index, timestamp, data, previous_hash):
    self.index = index
    self.timestamp = timestamp
    self.data = data
    self.previous_hash = previous_hash
    self.hash = self.hashblock()
  
  def hashblock(self):
    sha = hashlib.sha256()
    sha.update((str(self.index) +
              str(self.timestamp) +
              str(self.data) +
              str(self.previous_hash)).encode('utf-8'))
    return sha.hexdigest()

Da der vorherige Block erforderlich ist, um eine neue Blockchain zu generieren, muss der erste Block im Voraus gespeichert werden. Es scheint, dass dies Genesis-Block (Erstellungsblock?) Genannt wird.

Für die Daten wird der durch den später beschriebenen PoW-Algorithmus (Proof of Work) berechnete Mindestwert "9" als Startwert festgelegt. Da der Hash des vorherigen Blocks nicht vorhanden ist, setzen Sie "0".

snakecoin_genesis.py



from snakecoin_block import Block
import datetime

def create_genesis_block():
  return Block(0, datetime.datetime.now(), {
    'message': 'Genesis Block',
    'proof-of-work': 9
  }, '0')

Um bis zu diesem Punkt zu testen, schreiben wir einen Testprozess, der am Ende der Blockchain einen Block hinzufügt. Da es sich um einen Test handelt, legen Sie eine entsprechende Zeichenfolge in den Daten fest.

snakecoin_next_block.py



from snakecoin_block import Block
import datetime

def next_block(last_block):
  this_index = last_block.index + 1
  this_timestamp = datetime.datetime.now()
  this_data = "Hey! I'm block " + str(this_index)
  previous_hash = last_block.hash
  return Block(this_index, this_timestamp, this_data, previous_hash)

Blockchain-Funktionsprüfung

Jetzt ist die Blockchain als Datenstruktur abgeschlossen. Lassen Sie uns den Vorgang überprüfen, indem wir die bisher erstellten verbinden.

Das grobe Verfahren ist

  1. Erstellen Sie einen Genesis-Block und eine Blockchain
  2. Blockinformationen ausgeben
  3. Angegebene Anzahl von Schleifen
  4. Verbinden Sie einen neuen Block mit der Blockchain
  5. Geben Sie neue Blockinformationen aus

ist.

snakecoin_blockchain_test.py



from snakecoin_genesis import create_genesis_block
from snakecoin_next_block import next_block

#Erstellen Sie einen Genesis-Block, um eine Blockchain zu erstellen
blockchain = [create_genesis_block()]
#Genesis-Block als Endblock festgelegt
previous_block = blockchain[0]

#Anzahl der zu verbindenden Blöcke
num_of_blocks_to_add = 3

#Ausgabeinformationen des Genesis-Blocks
print("Block #{} has been added to the blockchain!".format(previous_block.index))
print("Data: {}".format(previous_block.data))
print("PrHh: {}".format(previous_block.previous_hash))
print("Hash: {}\n".format(previous_block.hash))

for i in range(0, num_of_blocks_to_add):
  #Erstellen Sie einen neuen Block und fügen Sie ihn der Blockchain hinzu
  block_to_add = next_block(previous_block)
  blockchain.append(block_to_add)

  #Neue Blockinformationen ausgeben
  print("Block #{} has been added to the blockchain!".format(block_to_add.index))
  print("Data: {}".format(block_to_add.data))
  print("PrHh: {}".format(block_to_add.previous_hash))
  print("Hash: {}\n".format(block_to_add.hash))

  #Endblock aktualisieren
  previous_block = block_to_add

Bei der Ausführung wird das folgende Ergebnis ausgegeben. Der Hash Hash des eigenen Blocks wird im nächsten Block als Hash PrHh des vorherigen Blocks aufgezeichnet.

$ python snakecoin_blockchain_test.py
Block #0 has been added to the blockchain!
Data: {'proof-of-work': 9, 'message': 'Genesis Block'}
PrHh: 0
Hash: 96cab14611cd4e674d78bb2e3a93ccdf2364955575039d4ffa09a2714b12e8ac

Block #1 has been added to the blockchain!
Data: Hey! I'm block 1
PrHh: 96cab14611cd4e674d78bb2e3a93ccdf2364955575039d4ffa09a2714b12e8ac
Hash: 6023a093c0e3449692fe431679a3752a7201e74b17059087f777dfd54105f906

Block #2 has been added to the blockchain!
Data: Hey! I'm block 2
PrHh: 6023a093c0e3449692fe431679a3752a7201e74b17059087f777dfd54105f906
Hash: 18af14f5ab32bd40fa3c141290aba7a23cff058f391eb8769f4b5e4ea84aa0f8

Block #3 has been added to the blockchain!
Data: Hey! I'm block 3
PrHh: 18af14f5ab32bd40fa3c141290aba7a23cff058f391eb8769f4b5e4ea84aa0f8
Hash: 13ff0cbfcac15d705319e67abd48e3768fa6c4465ffe624689e65f29e91bf641

Transaktionsregistrierung und neue Blockaddition

Speichern wir nun die Lieferinformationen in der Blockchain. Da REST als Schnittstelle verwendet wird, erstellen wir es mit Flask.

Als Schnittstelle

ist.

Detailliertes Verhalten und Verarbeitung, die für den tatsächlichen Betrieb erforderlich sein können, werden im Code als Kommentare beschrieben.

snakecoin_node_transaction.py



from snakecoin_block import Block
from snakecoin_genesis import create_genesis_block
from flask import Flask, request, jsonify
import datetime
import json
import requests

#Blockchain definieren
blockchain = []
blockchain.append(create_genesis_block())

#Transaktionsliste
#Speichert Transaktionen innerhalb dieses Knotens
this_nodes_tx = []

#Liste der Knoten-URLs im Blockchain-Netzwerk
# TODO:Erstellen Sie einen Mechanismus zum Erkennen neuer Knoten
peer_nodes = []

#Die Nebenadresse ist vorerst festgelegt
# TODO:Erstellen Sie einen Mechanismus, um jeden Knoten eindeutig zu generieren und festzulegen
miner_address = "q3nf394hjg-random-miner-address-34nf3i4nflkn3oi"

#Proof of Work-Algorithmus
#BitCoin usw. ist eine Hashwertsuche nach bestimmten Bedingungen, die viel Berechnung erfordert
#Hier der Kürze halber
#"Verarbeitung * Die Häufigkeit ist durch 9 teilbar" UND "Durch das vorherige Ergebnis teilbar"
#* Diesmal ist es nur ein Inkrement
#Ist zu entdecken.
#In diesem Zustand führt der Server jedoch den Erkennungsprozess aus.
#Die Verarbeitung ist nicht verteilt, und es ist wahrscheinlich, dass eine Blockchain-Verzweigung auftritt.
# TODO:Es wird davon ausgegangen, dass das Teil mit einem hohen Rechenaufwand auf der Clientseite implementiert wird und nur der Bestätigungsprozess auf der Serverseite implementiert wird.
def proof_of_work(last_proof):
  incrementor = last_proof + 1
  while not (incrementor % 9 == 0 and incrementor % last_proof == 0):
    incrementor += 1
  return incrementor

#Ruft die Blockchain-Informationen ab, die von jedem Knoten gehalten werden
def find_new_chains():
  other_chains = []
  for node_url in peer_nodes:
    block = requests.get(node_url + '/blocks').content
    block = json.reloads(block)
    other_chains.append(block)
  return other_chains

#Suchen Sie das Ende, das neue Blöcke verbindet
def consensus():
  global blockchain
  longest_chain = blockchain
  #Abrufen von Blockchain-Informationen, die von anderen Knoten gehalten werden
  other_chains = find_new_chains()
  #Suchen Sie nach der längsten Blockchain und übernehmen Sie die längste Blockchain.
  #Wenn die Blockchain unter Verwendung der aktuellen Anordnung implementiert wird, gehen die Informationen zu den kurzen Zweigen der verzweigten Blockchain verloren.
  # TODO:Geändert zu einer Logik, die das längste Ende annimmt, anstatt die angenommene Blockchain zu übernehmen, während die verzweigten Zweige in der Implementierung wie ein gerichteter Graph beibehalten werden
  for chain in other_chains:
    if len(longest_chain) < len(chain):
      longest_chain = chain
  blockchain = longest_chain

#### endpoints

node = Flask(__name__)

#Registrieren Sie eine Snakecoin-Pass-Transaktion
@node.route('/transactions', methods=['POST'])
def transactions():
  if request.method == 'POST':
    #Fügen Sie der Transaktionsliste POST-Transaktionsdaten hinzu
    new_tx = request.get_json()
    this_nodes_tx.append(new_tx)

    #Standardausgabe der hinzugefügten Transaktionsdaten
    print("New Transaction")
    print("FROM: {}".format(new_tx['from']))
    print("TO: {}".format(new_tx['to']))
    print("AMOUNT: {}".format(new_tx['amount']))

    return jsonify({'message': 'Transaction submission successful'}), 200

#Blockieren Sie übergebende Transaktionen und verbinden Sie sie mit der Blockchain
@node.route('/mines', methods=['POST'])
def mines():
  #Nehmen Sie Konsens
  consensus()

  #Holen Sie sich den letzten Beweis
  last_block = blockchain[len(blockchain) - 1]
  last_proof = last_block.data['proof-of-work']

  #Bergbau
  # TODO:Erhalten Sie einen neuen Beweis als Parameter und führen Sie nur eine Konformitätsbeurteilung durch
  proof = proof_of_work(last_proof)

  #Es wurde eine Transaktion hinzugefügt, die Bergleute mit 1 Schlangenmünze belohnt
  this_nodes_tx.append({
    "from": "network",
    "to": miner_address,
    "amount": 1
  })

  #Vorbereiten der für den neuen Block erforderlichen Werte
  #Hier wird die Transaktionsliste in einem Block gespeichert
  new_block_index = last_block.index + 1
  new_block_timestamp = this_timestamp = datetime.datetime.now()
  new_block_data = {
    "proof-of-work": proof,
    "transactions": list(this_nodes_tx)
  }
  last_block_hash = last_block.hash

  #Generieren Sie einen neuen Block und fügen Sie ihn der Blockchain hinzu
  mined_block = Block(
    new_block_index,
    new_block_timestamp,
    new_block_data,
    last_block_hash
  )
  blockchain.append(mined_block)

  #Transaktionsliste initialisieren
  this_nodes_tx[:] = []

  return jsonify(
    {
      "index": new_block_index,
      "timestamp": new_block_timestamp,
      "data": new_block_data,
      "hash": last_block_hash
    }
  )

#Weitere Informationen finden Sie in den Blockchain-Informationen dieses Knotens
@node.route('/blocks', methods=['GET'])
def get_blocks():
  chain_to_send = blockchain[:]
  for i in range(len(chain_to_send)):
    block = chain_to_send[i]
    #String die Eigenschaften der Block-Klasse
    block_index = str(block.index)
    block_timestamp = str(block.timestamp)
    block_data = str(block.data)
    block_hash = block.hash
    #In Wörterbuchtyp konvertieren, damit es in eine JSON-Zeichenfolge konvertiert werden kann
    chain_to_send[i] = {
      "index": block_index,
      "timestamp": block_timestamp,
      "data": block_data,
      "hash": block_hash
    }
  #In JSON-Zeichenfolge konvertieren und zum Client zurückkehren
  return jsonify(chain_to_send)

node.run()

Im ursprünglichen Artikel wurde cURL verwendet, um den Vorgang zu überprüfen. In diesem Artikel werde ich das Ausführungsergebnis von Postman veröffentlichen.

$ python snakecoin_node_transaction.py

Wenn Sie mit und GET / blocks beginnen, wird der folgende Inhalt zurückgegeben.

image.png

Eine Blockchain (Anordnung) mit Genesis-Blöcken wurde zurückgegeben. Als nächstes registrieren wir die Snakecoin-Lieferinformationen unter "POST / Transaktionen".

image.png

2 Die Transaktion, die die Schlangenmünzen bestanden hat, war erfolgreich (Status: 200 OK). Diese Transaktion wurde jedoch noch nicht in der Blockchain aufgezeichnet (= nicht abgeschlossen). Sie können sehen, dass sich der Inhalt nicht geändert hat, auch wenn Sie auf "GET / Blocks" klicken.

image.png

Lassen Sie uns Mining durchführen, um die Lieferungstransaktion abzuschließen. Drücke POST / Minen.

image.png

Die neu erstellten Blockinformationen werden zurückgegeben. Zusätzlich zu den Lieferinformationen von 2 Schlangenmünzen sind die Lieferinformationen von 1 Schlangenmünze als Belohnung für den Bergmann (minderjährig) enthalten.

image.png

Wenn Sie "GET / Blocks" aktivieren, können Sie sehen, dass der Blockchain neue Blöcke hinzugefügt wurden.

Zusammenfassung und Eindrücke

Blockchain ist nicht beängstigend!

Ich möchte immer noch etwas über Etheriums PoS (Proof of Stake) wissen, nicht über PoW, wie den Aufbau eines P2P-Netzwerks oder die Implementierung von Wallet! Ich habe das Gefühl, dass es verschiedene Engpässe gibt, aber ich habe das Gefühl, dass ich den Punkt erreicht habe, an dem ich die Blockchain vollständig verstehe ().

Es gibt noch einige Dinge, die untersucht werden müssen, bevor es tatsächlich betrieben wird, aber von dem Punkt, an dem "Ich kann den Weg zum tatsächlichen Betrieb nicht sehen" bis zu "Ich denke, ich kann ein Punktesystem zum Spaß in ein bisschen mehr erstellen". Überlegen. Aber gibt die Implementierung rund um das Mining dem Client auch eine Serverfunktion? Ich bin mir immer noch nicht sicher, also dachte ich, ich würde lernen, indem ich [Adventskalender-Artikel] lese (https://qiita.com/advent-calendar/2019/blockchain).

Ich hoffe, das hilft Ihnen, die Blockchain zu verstehen. Und nochmals vielen Dank an Herrn Gerald.


Morgen? Ist @ shu-kobs Lassen Sie uns Bitcoin Signet berühren.

Recommended Posts

Ich habe versucht, eine Blockchain zu implementieren, die tatsächlich mit ungefähr 170 Zeilen funktioniert
Implementieren Sie eine Blockchain mit ca. 60 Zeilen
Ich habe versucht, mit Quantx eine Linie mit gleitendem Durchschnitt des Volumens zu implementieren
Ich habe versucht, Autoencoder mit TensorFlow zu implementieren
Ich habe versucht, CVAE mit PyTorch zu implementieren
[Python] Ein Memo, das ich versucht habe, mit Asyncio zu beginnen
Ich habe versucht, das Lesen von Dataset mit PyTorch zu implementieren
Ich habe versucht, die Zusammenführungssortierung in Python mit möglichst wenigen Zeilen zu implementieren
Ich habe versucht, einen Übersetzungs-BOT zu erstellen, der mit Discord unter Verwendung von Googletrans funktioniert
Ich habe versucht, DCGAN mit PyTorch zu implementieren und zu lernen
Ich habe versucht, Mine Sweeper auf dem Terminal mit Python zu implementieren
Ich habe versucht, einen Pseudo-Pachislot in Python zu implementieren
Ich habe versucht, künstliches Perzeptron mit Python zu implementieren
Ich habe versucht, Grad-CAM mit Keras und Tensorflow zu implementieren
Ich habe versucht, SSD jetzt mit PyTorch zu implementieren (Dataset)
Ich habe versucht, PCANet zu implementieren
Ich habe versucht, StarGAN (1) zu implementieren.
Ich habe versucht, das grundlegende Modell des wiederkehrenden neuronalen Netzwerks zu implementieren
Ich habe versucht, einen eindimensionalen Zellautomaten in Python zu implementieren
Ich habe versucht, automatisch einen Bericht mit der Markov-Kette zu erstellen
Ich habe versucht, mit Quantx einen Ausbruch (Typ der Täuschungsvermeidung) zu implementieren
Ich habe versucht, das Problem der Kombinationsoptimierung mit Qiskit zu lösen
Ich habe versucht, mit Hy ・ Define a class zu beginnen
[Python] Ich habe versucht, Tweets über Corona mit WordCloud zu visualisieren
Ich habe versucht, ListNet of Rank Learning mit Chainer zu implementieren
Ich habe einen harten Pomodoro-Timer entwickelt, der mit CUI funktioniert
Ich habe versucht, Harry Potters Gruppierungshut mit CNN umzusetzen
Ich habe versucht, eine zufällige FizzBuzz-Spalte mit Blasensortierung zu sortieren.
Ich habe versucht, in einem tief erlernten Sprachmodell zu schreiben
Ich habe versucht, SSD jetzt mit PyTorch zu implementieren (Modellversion)
Ich habe versucht, Deep VQE zu implementieren
[1 Stunde Herausforderung] Ich habe versucht, eine Wahrsagerseite zu erstellen, die für Python zu geeignet ist
Ich habe versucht, eine kontroverse Validierung zu implementieren
Ich habe versucht, einen Generator zu erstellen, der mit Python eine C # -Containerklasse aus CSV generiert
Ich habe versucht, mich über MCMC zu organisieren.
Ich habe versucht, Realness GAN zu implementieren
Ich habe versucht, mit Docker einen Dienst aufzubauen, der maschinell erlernte Daten mit explosiver Geschwindigkeit verkauft
[5.] Ich habe versucht, mit Python ein bestimmtes Authenticator-ähnliches Tool zu erstellen
Ich habe versucht, eine Serverumgebung zu erstellen, die unter Windows 10 ausgeführt wird
Ich möchte einen Platzhalter verwenden, den ich mit Python entfernen möchte
Ich habe versucht, ein System zu erstellen, das nur gelöschte Tweets abruft
[2nd] Ich habe versucht, mit Python ein bestimmtes Authenticator-ähnliches Tool zu erstellen
Ein Memorandum beim automatischen Erwerb mit Selen
[Python] Ich habe versucht, eine stabile Sortierung zu implementieren
[3.] Ich habe versucht, mit Python ein bestimmtes Authenticator-ähnliches Tool zu erstellen
Ich habe versucht, mit Python eine Liste von Primzahlen zu erstellen
Ich habe versucht, ein missverstandenes Gefangenendilemma in Python zu implementieren
Ich habe versucht, mit Selenium und Python einen regelmäßigen Ausführungsprozess durchzuführen
Ich habe versucht, mit Python eine 2-Kanal-Post-Benachrichtigungsanwendung zu erstellen
Ich habe versucht, die Satzklassifizierung durch Self Attention mit PyTorch zu implementieren
Ich habe versucht, Bulls and Cows mit einem Shell-Programm zu erstellen
Ich habe ein Werkzeug ausprobiert, das Gochs Muster mit KI imitiert
Ich habe versucht, eine ToDo-App mit einer Flasche mit Python zu erstellen