Cómo crear su propia criptomoneda usando Python

Con el aumento actual de las criptomonedas, blockchain está creando un gran revuelo en el mundo de la tecnología. Esta tecnología ha atraído tanta atención principalmente por su capacidad para garantizar la seguridad, hacer cumplir la descentralización y acelerar los procesos en varias industrias, especialmente en la industria financiera.

Básicamente, una cadena de bloques es una base de datos pública que documenta y autentica de manera irreversible la posesión y transmisión de activos digitales. Las monedas digitales, como Bitcoin y Ethereum, se basan en este concepto. Blockchain es una tecnología interesante que puede utilizar para transformar las capacidades de sus aplicaciones.

Últimamente, hemos visto gobiernos, organizaciones e individuos que utilizan la tecnología blockchain para crear sus propias criptomonedas y evitar quedarse atrás. En particular, cuando Facebook propuso su propia criptomoneda, llamada Libra, el anuncio agitó muchas aguas en todo el mundo.

¿Qué pasaría si también pudiera hacer lo mismo y crear su propia versión de una criptomoneda?

Pensé en esto y decidí desarrollar un algoritmo que crea una criptografía.

Decidí llamar a la criptomoneda fccCoin .

En este tutorial, voy a ilustrar el proceso paso a paso que utilicé para construir la moneda digital (utilicé los conceptos orientados a objetos del lenguaje de programación Python).

Aquí está el modelo básico del algoritmo blockchain para crear la fccCoin :

class Block: def __init__(): #first block class pass def calculate_hash(): #calculates the cryptographic hash of every block class BlockChain: def __init__(self): # constructor method pass def construct_genesis(self): # constructs the initial block pass def construct_block(self, proof_no, prev_hash): # constructs a new block and adds it to the chain pass @staticmethod def check_validity(): # checks whether the blockchain is valid pass def new_data(self, sender, recipient, quantity): # adds a new transaction to the data of the transactions pass @staticmethod def construct_proof_of_work(prev_proof): # protects the blockchain from attack pass @property def last_block(self): # returns the last block in the chain return self.chain[-1] 

Ahora, déjame explicarte lo que está sucediendo ...

1. Construyendo la primera clase Block

Una cadena de bloques se compone de varios bloques que se unen entre sí (eso suena familiar, ¿verdad?).

El encadenamiento de bloques se realiza de manera que si se manipula un bloque, el resto de la cadena se vuelve inválido.

Al aplicar el concepto anterior, creé la siguiente clase de bloque inicial:

import hashlib import time class Block: def __init__(self, index, proof_no, prev_hash, data, timestamp=None): self.index = index self.proof_no = proof_no self.prev_hash = prev_hash self.data = data self.timestamp = timestamp or time.time() @property def calculate_hash(self): block_of_string = "{}{}{}{}{}".format(self.index, self.proof_no, self.prev_hash, self.data, self.timestamp) return hashlib.sha256(block_of_string.encode()).hexdigest() def __repr__(self): return "{} - {} - {} - {} - {}".format(self.index, self.proof_no, self.prev_hash, self.data, self.timestamp) 

Como puede ver en el código anterior, definí la función __init __ () , que se ejecutará cuando se inicie la clase Block , al igual que en cualquier otra clase de Python.

Proporcioné los siguientes parámetros a la función de inicio:

  • self: se refiere a la instancia de la clase Block , lo que permite acceder a los métodos y atributos asociados a la clase;
  • índice: realiza un seguimiento de la posición del bloque dentro de la cadena de bloques;
  • proof_no: este es el número producido durante la creación de un nuevo bloque (llamado minería);
  • prev_hash: se refiere al hash del bloque anterior dentro de la cadena;
  • datos: proporciona un registro de todas las transacciones completadas, como la cantidad comprada;
  • marca de tiempo: esto coloca una marca de tiempo para las transacciones.

El segundo método de la clase, calculate_hash , generará el hash de los bloques utilizando los valores anteriores. El módulo SHA-256 se importa al proyecto para ayudar a obtener los valores hash de los bloques.

Después de que los valores se hayan ingresado en el algoritmo hash criptográfico, la función devolverá una cadena de 256 bits que representa el contenido del bloque.

Así es como se logra la seguridad en blockchains: cada bloque tendrá un hash y ese hash dependerá del hash del bloque anterior.

Como tal, si alguien intenta comprometer cualquier bloque de la cadena, los otros bloques tendrán hash no válidos, lo que provocará la interrupción de toda la red blockchain.

En última instancia, un bloque se verá así:

{ "index": 2, "proof": 21, "prev_hash": "6e27587e8a27d6fe376d4fd9b4edc96c8890346579e5cbf558252b24a8257823", "transactions": [ {'sender': '0', 'recipient': 'Quincy Larson', 'quantity': 1} ], "timestamp": 1521646442.4096143 } 

2. Construyendo la clase Blockchain

La idea principal de una cadena de bloques, tal como su nombre lo indica, implica "encadenar" varios bloques entre sí.

Por lo tanto, voy a construir una clase Blockchain que será útil para administrar el funcionamiento de toda la cadena. Aquí es donde se llevará a cabo la mayor parte de la acción.

La clase Blockchain tendrá varios métodos de ayuda para completar varias tareas en la cadena de bloques.

Déjame explicarte el papel de cada uno de los métodos en la clase.

a. Método constructor

Este método garantiza que se instancia la cadena de bloques.

class BlockChain: def __init__(self): self.chain = [] self.current_data = [] self.nodes = set() self.construct_genesis() 

Estos son los roles de sus atributos:

  • self.chain: esta variable mantiene todos los bloques;
  • self.current_data: esta variable mantiene todas las transacciones completadas en el bloque;
  • self.construct_genesis (): este método se encargará de construir el bloque inicial.

segundo. Construyendo el bloque génesis

La cadena de bloques requiere un método construct_genesis para construir el bloque inicial en la cadena. En la convención de blockchain, este bloque es especial porque simboliza el inicio de blockchain.

En este caso, vamos a construirlo simplemente pasando algunos valores predeterminados al método construct_block .

Le di a proof_no y prev_hash un valor de cero, aunque puede proporcionar el valor que desee.

def construct_genesis(self): self.construct_block(proof_no=0, prev_hash=0) def construct_block(self, proof_no, prev_hash): block = Block( index=len(self.chain), proof_no=proof_no, prev_hash=prev_hash, data=self.current_data) self.current_data = [] self.chain.append(block) return block 

C. Construyendo nuevos bloques

El método construct_block se utiliza para crear nuevos bloques en la cadena de bloques.

Esto es lo que está sucediendo con los diversos atributos de este método:

  • índice: representa la longitud de la cadena de bloques;
  • proof_nor & prev_hash: el método del llamador los pasa;
  • datos: contiene un registro de todas las transacciones que no están incluidas en ningún bloque del nodo;
  • self.current_data—this is used to reset the transaction list on the node. If a block has been constructed and the transactions allocated to it, the list is reset to ensure that future transactions are added into this list. And, this process will take place continuously;
  • self.chain.append()—this method joins newly constructed blocks to the chain;
  • return—lastly, a constructed block object is returned.

d. Checking validity

The check_validity method is important in assessing the integrity of the blockchain and ensuring anomalies are absent.

As mentioned earlier, hashes are essential for the security of the blockchain as even the slightest change in the object will lead to the generation of a completely new hash.

Therefore, this check_validitymethod uses if statements to check whether the hash of every block is correct.

It also verifies if every block points to the right previous block, through comparing the value of their hashes. If everything is correct, it returns true; otherwise, it returns false.

@staticmethod def check_validity(block, prev_block): if prev_block.index + 1 != block.index: return False elif prev_block.calculate_hash != block.prev_hash: return False elif not BlockChain.verifying_proof(block.proof_no, prev_block.proof_no): return False elif block.timestamp <= prev_block.timestamp: return False return True 

e. Adding data of transactions

The new_data method is used for adding the data of transactions to a block. It’s a very simple method: it accepts three parameters (sender’s details, receiver’s details, and quantity) and append the transaction data to self.current_data list.

Anytime a new block is created, this list is allocated to that block and reset once more as explained in the construct_block method.

Once the transaction data has been added to the list, the index of the next block to be created is returned.

This index is calculated by adding 1 to the index of the current block (which is the last in the blockchain). The data will assist a user in submitting the transaction in future.

def new_data(self, sender, recipient, quantity): self.current_data.append({ 'sender': sender, 'recipient': recipient, 'quantity': quantity }) return True 

f. Adding proof of work

Proof of work is a concept that prevents the blockchain from abuse. Simply, its objective is to identify a number that solves a problem after a certain amount of computing work is done.

If the difficulty level of identifying the number is high, it discourages spamming and tampering with the blockchain.

In this case, we’ll use a simple algorithm that discourages people from mining blocks or creating blocks easily.

@staticmethod def proof_of_work(last_proof): '''this simple algorithm identifies a number f' such that hash(ff') contain 4 leading zeroes f is the previous f' f' is the new proof ''' proof_no = 0 while BlockChain.verifying_proof(proof_no, last_proof) is False: proof_no += 1 return proof_no @staticmethod def verifying_proof(last_proof, proof): #verifying the proof: does hash(last_proof, proof) contain 4 leading zeroes? guess = f'{last_proof}{proof}'.encode() guess_hash = hashlib.sha256(guess).hexdigest() return guess_hash[:4] == "0000" 

g. Getting the last block

Lastly, the latest_blockmethod is a helper method that assists in obtaining the last block in the blockchain. Remember that the last block is actually the current block in the chain.

@property def latest_block(self): return self.chain[-1] 

Let’s sum everything together

Here is the entire code for creating the fccCoin cryptocurrency.

You can also get the code on this GitHub repository.

import hashlib import time class Block: def __init__(self, index, proof_no, prev_hash, data, timestamp=None): self.index = index self.proof_no = proof_no self.prev_hash = prev_hash self.data = data self.timestamp = timestamp or time.time() @property def calculate_hash(self): block_of_string = "{}{}{}{}{}".format(self.index, self.proof_no, self.prev_hash, self.data, self.timestamp) return hashlib.sha256(block_of_string.encode()).hexdigest() def __repr__(self): return "{} - {} - {} - {} - {}".format(self.index, self.proof_no, self.prev_hash, self.data, self.timestamp) class BlockChain: def __init__(self): self.chain = [] self.current_data = [] self.nodes = set() self.construct_genesis() def construct_genesis(self): self.construct_block(proof_no=0, prev_hash=0) def construct_block(self, proof_no, prev_hash): block = Block( index=len(self.chain), proof_no=proof_no, prev_hash=prev_hash, data=self.current_data) self.current_data = [] self.chain.append(block) return block @staticmethod def check_validity(block, prev_block): if prev_block.index + 1 != block.index: return False elif prev_block.calculate_hash != block.prev_hash: return False elif not BlockChain.verifying_proof(block.proof_no, prev_block.proof_no): return False elif block.timestamp <= prev_block.timestamp: return False return True def new_data(self, sender, recipient, quantity): self.current_data.append({ 'sender': sender, 'recipient': recipient, 'quantity': quantity }) return True @staticmethod def proof_of_work(last_proof): '''this simple algorithm identifies a number f' such that hash(ff') contain 4 leading zeroes f is the previous f' f' is the new proof ''' proof_no = 0 while BlockChain.verifying_proof(proof_no, last_proof) is False: proof_no += 1 return proof_no @staticmethod def verifying_proof(last_proof, proof): #verifying the proof: does hash(last_proof, proof) contain 4 leading zeroes? guess = f'{last_proof}{proof}'.encode() guess_hash = hashlib.sha256(guess).hexdigest() return guess_hash[:4] == "0000" @property def latest_block(self): return self.chain[-1] def block_mining(self, details_miner): self.new_data( sender="0", #it implies that this node has created a new block receiver=details_miner, quantity= 1, #creating a new block (or identifying the proof number) is awarded with 1 ) last_block = self.latest_block last_proof_no = last_block.proof_no proof_no = self.proof_of_work(last_proof_no) last_hash = last_block.calculate_hash block = self.construct_block(proof_no, last_hash) return vars(block) def create_node(self, address): self.nodes.add(address) return True @staticmethod def obtain_block_object(block_data): #obtains block object from the block data return Block( block_data['index'], block_data['proof_no'], block_data['prev_hash'], block_data['data'], timestamp=block_data['timestamp']) 

Now, let’s test our code to see if it works.

blockchain = BlockChain() print("***Mining fccCoin about to start***") print(blockchain.chain) last_block = blockchain.latest_block last_proof_no = last_block.proof_no proof_no = blockchain.proof_of_work(last_proof_no) blockchain.new_data( sender="0", #it implies that this node has created a new block recipient="Quincy Larson", #let's send Quincy some coins! quantity= 1, #creating a new block (or identifying the proof number) is awarded with 1 ) last_hash = last_block.calculate_hash block = blockchain.construct_block(proof_no, last_hash) print("***Mining fccCoin has been successful***") print(blockchain.chain) 

It worked!

Here is the output of the mining process:

***Mining fccCoin about to start*** [0 - 0 - 0 - [] - 1566930640.2707076] ***Mining fccCoin has been successful*** [0 - 0 - 0 - [] - 1566930640.2707076, 1 - 88914 - a8d45cb77cddeac750a9439d629f394da442672e56edfe05827b5e41f4ba0138 - [{'sender': '0', 'recipient': 'Quincy Larson', 'quantity': 1}] - 1566930640.5363243] 

Conclusion

There you have it!

That’s how you could create your own blockchain using Python.

Let me say that this tutorial just demonstrates the basic concepts for getting your feet wet in the innovative blockchain technology.

If this coin were deployed as-is, it could not meet the present market demands for a stable, secure, and easy-to-use cryptocurrency.

Therefore, it can still be improved by adding additional features to enhance its capabilities for mining and sending financial transactions.

Nonetheless, it’s a good starting point if you decide to make your name known in the amazing world of cryptos.

If you have any comments or questions, please post them below.

Happy (crypto) coding!