Dieser Artikel ist der 6. Tag von Blockchain Adventskalender 2019. Gestern war @ y-chans Atomtausch verstehen.
"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.
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.
――Der Bereich "Machen wir eine sehr kleine Blockchain" (ca. 50 Zeilen)
Wir werden in der Reihenfolge von implementieren. Die Gesamtzahl der Zeilen ohne Kommentarzeilen betrug ca. 170.
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)
Jetzt ist die Blockchain als Datenstruktur abgeschlossen. Lassen Sie uns den Vorgang überprüfen, indem wir die bisher erstellten verbinden.
Das grobe Verfahren ist
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
Speichern wir nun die Lieferinformationen in der Blockchain. Da REST als Schnittstelle verwendet wird, erstellen wir es mit Flask.
Als Schnittstelle
/ mines
hinzu
--Blockchain Referenz / Blöcke
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.
Eine Blockchain (Anordnung) mit Genesis-Blöcken wurde zurückgegeben. Als nächstes registrieren wir die Snakecoin-Lieferinformationen unter "POST / Transaktionen".
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.
Lassen Sie uns Mining durchführen, um die Lieferungstransaktion abzuschließen. Drücke POST / Minen
.
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.
Wenn Sie "GET / Blocks" aktivieren, können Sie sehen, dass der Blockchain neue Blöcke hinzugefügt wurden.
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