Comment créer la blockchain la plus simple de Ruby

Dans cet article, nous allons explorer comment créer une démonstration de blockchain fonctionnelle simple en utilisant ** Ruby **.

Étape 1: transfert

À ce stade, nous vérifierons le solde et effectuerons le virement. Les transferts sont des ajouts ou des soustractions effectués en fonction du solde de votre compte.

Les protocoles HTTP GET et POST sont le meilleur moyen d'implémenter cette fonctionnalité. GET récupère les données du serveur et POST modifie les données sur le serveur.

Ici, l'affichage de l'interface utilisateur ne nécessite pas le protocole HTML. Vous pouvez utiliser le framework Web de Ruby Sinatra pour organiser les URL et les méthodes associées, et utiliser UE pour afficher les informations de transfert sur la ligne de commande.

Les méthodes côté client et les URL côté serveur sont très simples.

Client: client.rb

def create_user(name) … end

  def get_balance(user)  … end

  def transfer(from, to, amount) ... end

Serveur: hasebcoin.rb

get "/balance" ... end

  post "/users" ... end

  post "/transfers" ... end

Connaissances requises pour cette couche: ruby, HTTP GET, POST, Sinatra

Étape 2: Construire un réseau de potins

La blockchain a une structure décentralisée appelée «protocole de potins». «Gossip» ici n'est pas une rumeur, mais une information qui est diffusée dans un réseau distribué.

Construisons un réseau de potins où les noms de films sont échangés.

client.rb envoie un message au port spécifié.

def self.gossip(port, state)
  ...  

  Faraday.post("#{URL}:#{port}/gossip", state: state).body
 
  ...

end

gossip.rb reçoit deux paramètres: le port source et le port de destination. Échangez des informations via des sources spécifiques côté source, telles que les ports 1111 et 2222.

Dans un vrai réseau distribué, les deux ports sont essentiellement deux nœuds de réseau. L'échange d'informations entre différents ports locaux représente la communication entre différents nœuds du réseau simulé.

À chaque nœud Prononcez le nom de votre film préféré toutes les 3 secondes.

every(3.seconds) do

  …

  gossip_response = Client.gossip(port, JSON.dump(STATE))

  update_state(JSON.load(gossip_response))

  ...

end

Changez le nom de votre film préféré toutes les 8 secondes.

every(8.seconds) do

  …

  update_state(PORT => [@favorite_movie, @version_number])

  ...

end

Le serveur reçoit et traite les données.

post '/gossip' do

  …

  update_state(JSON.load(their_state))

  …

end

Dans un réseau de 4 personnes

  1. Exécutez gossip.rb 1111 sur le premier nœud. Le premier nœud prononce le nom de votre film préféré sur le port 1111. 2, lancez gossip.rb 2222 1111. Le deuxième nœud communique le nom de votre film préféré sur le port 2222 au premier nœud (port 1111). 3, lancez gossip.rb 3333 2222. Le troisième nœud prononce le nom de votre film préféré du port 3333 au deuxième nœud (port 2222). 4, lancez gossip.rb 4444 3333. Le quatrième nœud prononce le nom de votre film préféré du port 4444 au troisième nœud (port 3333).

Après un certain temps, seuls quatre nœuds obtiennent les informations du pair et les données changent constamment. Il s'agit d'un simple réseau Gossip.

Étape 3: Cryptage et décryptage des données

Les algorithmes de cryptage de haut niveau sont à la base de la blockchain. À cette couche, la technologie de cryptage asymétrique est utilisée pour mettre en œuvre des comptes blockchain. L'algorithme RSA peut générer des clés publiques et privées et forcer un cryptage asymétrique.

def generate_key_pair … end
def sign(plaintext, raw_private_key) ... end

Grâce au module OpenSSL du langage Ruby, vous pouvez rapidement implémenter un cryptage asymétrique et une vérification de signature. Dans la blockchain, la clé publique est le compte et la clé privée est le mot de passe. Chaque paire de clés sera un compte blockchain.

Décryptez le code.

def plaintext(ciphertext, raw_public_key) … end

Vérifiez si le chiffrement est un message.

def valid_signature?(message, ciphertext, public_key) … end

** Connaissances requises pour cette couche: algorithme de chiffrement asymétrique **

Étape 4: Exploration de données

À ce stade, la preuve de travail est mise en œuvre et des blocs pour la blockchain sont générés. Il s'agit d'un processus long et fastidieux. Les fonctions de hachage sont irréversibles et il n'y a pas de conflits. Le processus de calcul est simple. Vous pouvez obtenir le résultat simplement en effectuant une opération de hachage sur l'entrée.

L'entrée est des informations sur la remise, telles que le montant de la remise, le nom de l'expéditeur et le nom du destinataire. Il existe différents algorithmes pour les opérations de hachage.

Ici, nous utilisons l'algorithme SHA256.

def hash(message) … end

Si vous hachez les mêmes informations, vous obtiendrez des résultats différents à chaque fois. Le calcul se poursuit jusqu'à ce que le résultat obtenu satisfasse la caractéristique telle que "à partir de plusieurs chiffres de 0".

Vérifiez si le résultat commence par quelques chiffres de 0.

def is_valid_nonce?(nonce, message)

  hash(message + nonce).start_with?("0" * NUM_ZEROES)

end

Il n'est pas facile d'effectuer des travaux pour satisfaire aux conditions ci-dessus. Cela prend beaucoup de temps. Tout ce travail s'appelle l'exploitation minière.

def find_nonce(message)

  …  

  until is_valid_nonce?(nonce, message)

  ...

end

L'entrée contient le résultat de l'opération de hachage précédente. Par conséquent, chaque opération de hachage est affectée par l'opération de hachage précédente. En d'autres termes, il s'agit d'une structure en chaîne. C'est la raison pour laquelle on l'appelle une blockchain.

Étape 5: règle de la chaîne la plus longue

À ce stade, le premier bloc est initialisé, la structure de la blockchain est générée en conséquence et la blockchain est formée. La blockchain est stockée dans une structure Array. Lors de la sauvegarde, le bloc doit subir une validation.

Initialisez le bloc.

def initialize(prev_block, msg)

  @msg = msg

  @prev_block_hash = prev_block.own_hash if prev_block
  
  mine_block!
    
end

La tâche la plus gratifiante pendant l'extraction est de trouver du nonce.

def mine_block!

  @nonce = calc_nonce

  @own_hash = hash(full_block(@nonce))

end

Le bloc complet est compressé de cette manière.

def full_block(nonce)

  [@msg, @prev_block_hash, nonce].compact.join

end

Initialisez la blockchain: classe BlockChain

Enregistrez simplement en utilisant Array!

def initialize(msg)
  
  @blocks = []

  @blocks << Block.new(nil, msg)

end

Ajoutez des blocs à la chaîne. L'ensemble de la blockchain se développe continuellement.

def add_to_chain(msg)

  @blocks << Block.new(@blocks.last, msg)

  puts @blocks.last

end

Vous devez vérifier rigoureusement que le bloc est sain.

def valid?

  @blocks.all? { |block| block.is_a?(Block) } &&

    @blocks.all?(&:valid?) &&
    
    @blocks.each_cons(2).all? { |a, b| a.own_hash == b.prev_block_hash }
    
end

Étape 6. Combinaison de pièces

Enfin, Blockchain opère sa magie grâce à une collaboration harmonieuse avec tous les composants du réseau. Dans la première étape, le transfert est une classe de transaction et vous devez utiliser la clé privée pour signer les informations.

@signature = PKI.sign(message, priv_key)

La récompense du mineur pour avoir obtenu le premier bloc est de 500 000 pièces d'argent.

def self.create_genesis_block(pub_key, priv_key)

  genesis_txn = Transaction.new(nil, pub_key, 500_000, priv_key)

  Block.new(nil, genesis_txn)

end

Vérifiez si les dépenses portées à votre compte sont valides.

def all_spends_valid?

  compute_balances do |balances, from, to|

    return false if balances.values_at(from, to).any? { |bal| bal < 0 }

  end

  true

end

Ajoutez un nœud inconnu $ PEERS pour maintenir la croissance du réseau

if PEER_PORT.nil?

  # You are the progenitor!

  $BLOCKCHAIN = BlockChain.new(PUB_KEY, PRIV_KEY)

  else

  # You're just joining the network.

  $PEERS << PEER_PORT

end

Le traitement des données entre les nœuds charge et met à jour la blockchain et PEER.

# @param blockchain

# @param peers

post '/gossip' do

  their_blockchain = YAML.load(params['blockchain'])

  their_peers = YAML.load(params['peers'])

  update_blockchain(their_blockchain)

  update_peers(their_peers)  

  YAML.dump('peers' => $PEERS, 'blockchain' => $BLOCKCHAIN)

end

Le traitement du bloc reçu se concentre sur la longueur de la chaîne.

def update_blockchain(their_blockchain)  

  return if their_blockchain.nil?

  return if $BLOCKCHAIN && their_blockchain.length <= $BLOCKCHAIN.length
  
  return unless their_blockchain.valid?  $BLOCKCHAIN = their_blockchain
  
  end

Mettez à jour PEER jusqu'à nouveau.

def update_peers(their_peers)

  $PEERS = ($PEERS + their_peers).uniq

end

Lorsque vous envoyez de l'argent, récupérez la pub_key du destinataire et envoyez-la via la pub_key de l'expéditeur.

# @param to (port_number)

# @param amount

post '/send_money' do

  to = Client.get_pub_key(params['to'])

  amount = params['amount'].to_i

  $BLOCKCHAIN.add_to_chain(Transaction.new(PUB_KEY, to, amount, PRIV_KEY))

  'OK. Block mined!'


end

Mettez la blockchain dans le réseau de potins et assemblez tous les composants fonctionnels. C'est tout ce qu'on peut en dire. Vous avez créé avec succès une blockchain.

Plus d'informations sur cette démo peuvent être trouvées sur Github: [https://github.com/Haseeb-Qureshi/lets-build-a-blockchain](https://github.com/Haseeb-Qureshi/lets- construire une blockchain? spm = a2c65.11461447.0.0.30084c44XBVTHc)

Pour plus d'informations sur la blockchain et d'autres technologies innovantes, veuillez visiter www.alibabacloud.com.

Recommended Posts

Comment créer la blockchain la plus simple de Ruby
Comment itérer indéfiniment en Ruby
Comment installer Bootstrap dans Ruby
Comment récupérer la valeur de hachage dans un tableau dans Ruby
Comment obtenir la date avec Java
Comment installer le langage utilisé dans Ubuntu et comment créer l'environnement
Comment trouver la cause de l'erreur Ruby
Comment construire android-midi-lib
Comment déboguer le traitement dans le modèle Ruby on Rails avec juste la console
Comment créer un fichier exécutable dans Maven
Comment vérifier les commandes Rails dans le terminal
Comment implémenter la pagination dans GraphQL (pour ruby)
Je veux obtenir la valeur en Ruby
[Introduction à Ruby] Comment utiliser la méthode slice
Comment résoudre les erreurs qui se produisent lors du test d'intégration "Ruby on Rails"
[Ruby] Comment utiliser la sortie standard dans le branchement conditionnel
Comment régler l'heure d'affichage sur l'heure japonaise dans les rails
[Java] Comment omettre le constructeur privé dans Lombok
[Ruby on Rails] Comment changer le nom de la colonne
Organisé comment interagir avec le JDK par étapes
[Ruby On Rails] Comment réinitialiser DB dans Heroku
Comment lancer une autre commande dans un programme Ruby
Comment spécifier le chemin de la ressource dans l'importation HTML
[Rails] Comment afficher les images dans la vue
Comment résoudre l'erreur SSL_connect dans le SDK PayPal Ruby
Comment utiliser le retour Ruby
[Ruby] Comment commenter
Ruby: Comment utiliser les cookies
Comment écrire un exemple d'implémentation du problème dans E05 (ruby, C11) en temps réel hors ligne
Comment obtenir le nom d'une classe / méthode exécutée en Java
Comment utiliser la méthode getter / setter (en orientation objet)
Comment régler chrony lorsque le temps change dans CentOS7
Comment connecter les chaînes de la liste séparées par des virgules
Comment changer une chaîne dans un tableau en un nombre dans Ruby
Comment créer une partie d'espace réservé à utiliser dans la clause IN
[Avec des astuces de retour] Comment présenter React aux rails les plus simples
Comment afficher des graphiques dans Ruby on Rails (LazyHighChart)
[Ruby] Comment récupérer le contenu du double hachage
Comment ajouter les mêmes index dans un tableau imbriqué
Comment dériver le dernier jour du mois en Java
Comment changer Java à l'ère d'OpenJDK sur Mac
[Rails] Comment afficher les informations stockées dans la base de données dans la vue
Comment utiliser Lombok au printemps
Comment trouver May'n dans XPath
Comment masquer la barre de défilement dans WebView
Comment utiliser la méthode form_with
Comment exécuter JUnit dans Eclipse
Passer les paramètres régionaux i18n à JavaScript
Essayez d'implémenter Yuma dans Ruby