After reading this, I have some understanding of the blockchain

Reprinted from https://www.2cto.com/kf/201803/727574.html

If you haven’t heard of the 3 o’clock blockchain group, it means that you are not in the chain; If you are not swiped by the blockchain group at 3 o'clock, it means that you have not yet realized what "one day in the currency circle, one year in the world".

\

"Blockchain at three o'clock" has undoubtedly become the source of anxiety during the Spring Festival, and "blockchain" is destined to be an industry hot topic that has been continuously discussed and paid attention to in 2018.

On March 1, Zhu Xiaohu fired again at the surging blockchain craze. On a picture full of blockchain applications in the circle of friends, Zhu Xiaohu questioned: How many daily active users are there with all these applications combined? "2000 The Internet bubble of 2009 still has eyeballs at least, what else does today's blockchain have besides speculation?"

Before that, Zhu Xiaohu reposted the article "Come, drink this bowl of blockchain's poisonous chicken soup!" in the circle of friends that satirizes blockchain investment, and stated: "Don't pull me into any 3 o'clock group, there are some hype I would rather miss it, some money would rather not be earned, everyone take care of the evening." Zhu Xiaohu also said that calling ICO a Ponzi scheme is an insult to a Ponzi scheme.

As a programmer, if you don't understand this technology, you may be eliminated in 2018! Let's get started with the blockchain from ten humorous jokes with the editor!

Laughing and squirting! A collection of ten pieces of blockchain

1. If you are a woman, every time your boyfriend says something nasty to you or promises to buy something for you, you immediately record it and send it to you and all his girlfriends, classmates, colleagues, and various Groups and circles of friends, so that he can no longer deny, this is called blockchain.

2. Mahjong is a traditional Chinese blockchain project: a group of four miners, the miners who collide with the correct hash value of 13 numbers first can obtain the right to book and get rewards. Immutable. Because it takes too much computing power and physical strength to convince the other three people.

3. There are several similarities between the little sisters who play in nightclubs and the little brothers who play virtual currency:

They are all good people who think they are smart

Those who don't make money for themselves are stupid X diaosi

I know a lot of big guys

understand a lot

They are all waiting for their own price increase or their own virtual currency price increase to be taken over by others

4. The blockchain is a serious technology, and you don’t know whether various coins are serious or not.

5. Wu Sangui's anger at Shanhaiguan is essentially to compete for the power of sleeping Chen Yuanyuan; the essence of the bosses' mutual confrontation on the blockchain is to compete for the power to cut leeks.

6. At the beginning of the new semester, the son asked his father: "How do I fill in the work column of my father? Is it written as a currency?" The father hesitated and said, "Just write the shareholders of several listed companies."

7. Recently, digital currency is very popular, and many altcoins have increased several times and dozens of times. Many coin speculators started to flutter, clamoring for "one coin, one tender model". A friend asks me if I want to go with me So, let them call "one coin, one tender model", don't follow the trend and blindly speculate on coins, we should make their money - go to be a tender model! Be a tender model! tender model!

8. I met a coin friend yesterday and asked him: "The currency market has plummeted recently, how is the quality of sleep?"

He said, "Ok, sleep like a baby!"

I said, "I'm jealous."

"Sleep for an hour, wake up, cry for an hour, sleep for another hour, wake up and cry for another hour," he said.

9. The old comrade said earnestly to the post-80s and post-90s: "Don't play those bitcoins, those virtual things, do something real to buy a house and marry a daughter-in-law in Beijing!" The post-90s replied: "You all The house that cost a few thousand yuan has grown to 101,000 square meters. We will not find another way out, we will sell you a series of figures of 100,000, how can we afford a house?”

10. First of all, I would like to thank the company for giving out 1 million bitcoins as a reward to employees. Secondly, I feel very lucky to get the reward of 950,000. Then I think I still have to plan the use of this 860,000. After all 700,000 is not a small sum of money. I plan to give 200,000 to my parents. I haven’t figured out how to use the remaining 360,000. In short, I would like to thank the company for the reward of 300,000 bitcoins. Thank you. I wish you all the same as me. You can get the 150,000 reward.

\

Illustration: What the vernacular understands the blockchain?

what is blockchain

\

"Blockchain is just a technology", "Bitcoin" is just an application of blockchain technology, just like, a person can cook the technology, but the application of his cooking skills can make " Kung Pao Chicken", "Fish-flavored Pork" and other dishes.

So, what exactly is "blockchain"? Here, we use a popular joke on the Internet to show it to everyone in the form of graphics.

\

We can abstract "Bitcoin" into "photo of a certain Rong" as shown in the figure above. If many users on the Internet want to get a photo of a certain Rong, they need to go to a fixed website to search.

Of course, you don't have any other place to go. That's good. This certain website pops up ads and small windows for you every day.

\

Furthermore, what should I do if this website is suddenly blocked by the police uncle? Or is there a power outage? The internet is disconnected? Whatever, the server crashed anyway, so all the 2,100 photos beloved by fans of the tragic "A Rong" will be lost. place of resources.

This is the new word "centralization" circulating on the Internet. Its disadvantage is that resources are concentrated together, and the anti-risk and fault tolerance is very weak. Resources are easily lost.

So, how to solve this problem? Let's imagine, can we let every fan of "A Rong" have these 2100 photos? For example, the picture below:

\

In this case, it seems that you don't have to rely on that "a certain pomegranate" website. Even if a fan suddenly crashes his computer, he can find any other fan to get these 2100 photos, no worries, no worries.

Later, an avatar named "Satoshi" provided a shared folder of photos of a certain Rong with a protocol, from which users could obtain photos, but they had to follow the protocol.

\

In this way, every fan can get the 2100 photos of Zhang Mourong from this folder, but all the obtained fans must follow a protocol, of course, the protocol defined by a certain Satoshi.

"Do not copy, modify, share any photos in the file, any behavior of fans in the shared folder will be recorded, and it will be recorded according to time!"

Fans love Mourong so much, and they don't need to go to Moulu to get it, so of course they join in enthusiastically~

Suddenly, one day, the naughty little One wanted to violate the rules and deleted the photos of a certain Rong numbered 1-100 at 12:00 noon on January 15, 2018.

According to the protocol, this action will be recorded and broadcast to other fans.

\

Have the photos been deleted? Of course not, because Xiaolu also has photos in her hands. After she receives the broadcast, she can immediately restore the deleted photos in the shared folder. Xiao One will never try to modify or destroy the "shared folder". , and all actions are synchronously recorded in other users' computers.

\

This is the blockchain, data is stored in a decentralized way, and it is decentralized. All actions are recorded by time-stamped broadcast and cannot be modified, corrupted, or falsified.

\

Unless the computers of 1 million users are blown up at the same time, or the Internet disappears, or the world is destroyed.... Data will always exist~~

\

How to increase the resources protected by the blockchain? "Satoshi" is here again. He said, you can add a photo of a certain Rong to the document, but you must reach some kind of "consensus"? What is "consensus", it is the rule that we all recognize.

\

So what kind of consensus is that? Ah, Xiao One and Xiaolu immediately understood what a certain Satoshi meant, and took 100 photos of Mourong as soon as possible within the stipulated time every year, so that they could be added to the "Sharing files of Mourong". folder”, our resources will be expanded.

\

However, the good times did not last long. A certain Satoshi found a large number of photos, hitting the top 100, and it will be achieved soon, and there is no difficulty in taking photos.

And the photo quality is still poor, it seems that anyone can easily add photo resources, so the photo quality of a certain Rong cannot be guaranteed. So, a certain Satoshi came again, increasing the consensus difficulty of taking pictures.

\

As loyal fans, Xiao One and Xiao Lu, how could they give up? They bought high-end cameras, let Mourong pose in various poses, and spent a lot of time and sweat to complete high-quality photos. Of course, they also worked very hard.

\

Such high-quality photos can be added to "A Rong's Folder".

What is an ICO?

\

Little One thought: Each photo is unforgeable, so it is unique, and it is numbered separately. If you value each photo, isn't it worth it? It's like a famous painting that cannot be replicated in the real world!

Little One constructed the corresponding "A Rong coin" from the previous photo of a certain Rong. Of course, this behavior is similar to our government issuing the equivalent RMB through the amount of gold in the treasury.

As for the valuation, of course, what Xiao One said, he is the owner of the photo.

\

In order to confirm that a certain Rong coin is 5W per block, Little One first bought 1100 of the 2100, and the rest was distributed to the people who eat melons. We have already bought one with 5W, indicating that he is already worth the price, and the remaining 1000 Let's buy it together.

In this case, if all 2,100 coins are subscribed, 2,100 coins can be valued at 105 million yuan. This process of financing through the issuance of digital currency is called ICO.

\

According to the meaning of this picture, if Xiao One and Xiao Lu are a trusted institution or public figure, they can still be trusted. Of course, there will be many criminals who maliciously issue currency to cash out.

This is also the reason why our country prohibits ICO issuance, because there is currently no perfect ICO regulation that can guarantee the trustworthiness of the institutions that issue currency and supervise them legally, so the people who eat melons have to take their own risks to find a credible one. institution.

\

In this way, all 2,100 Rong coins were successfully subscribed, and the fund was established. This is ICO. Of course, people who eat melons can continue to take pictures to create a certain Rong coin, but it is a bit difficult.

\

Now you know what blockchain and ICO are. Let's teach you how to create a blockchain in Python  ? 

Create a blockchain from 0 with Python

We are new to the rise of digital currency and want to know how the technology behind it, the blockchain, is realized. This article builds a blockchain through Python to deepen the understanding of the blockchain.

Ready to work

This article requires readers to have a basic understanding of Python, to be able to read and write basic Python, and to have a basic understanding of HTTP requests.

We know that blockchain is an immutable, ordered chain structure composed of records of blocks, records can be transactions, files or any data you want, the important thing is that they are linked by hashes of.

If you are not familiar with hashing yet, check out this article https://learncryptography.com/hash-functions/what-are-hash-functions.

Environment preparation:

Environment preparation, make sure that Python3.6+, pip, Flask, and requests have been installed.

installation method:

pip install Flask==0.12.2 requests==2.18.4

Also requires an HTTP client, such as Postman, cURL, or others.

Refer to the source code (the original code didn't work when I translated it, I forked a copy, fixed the errors, and added the translation, thanks to star).

Start creating a Blockchain

Create a new file blockchain.py, all the code in this article is written in this file, you can refer to the source code at any time.

Blockchain class

First create a Blockchain class and create two lists in the constructor, one for storing blockchains and one for storing transactions.

Here is the skeleton of the Blockchain class:

class Blockchain(object): def __init__(self): self.chain = [] self.current_transactions = [] def new_block(self): # Creates a new Block and adds it to the chain pass def new_transaction(self): # Adds a new transaction to the list of transactions pass @staticmethod def hash(block): # Hashes a Block pass @property def last_block(self): # Returns the last Block in the chain pass

The Blockchain class is used to manage the chain, it can store transactions, add new blocks, etc. Let's further improve these methods.

block structure

Each block contains properties: index (index), Unix timestamp (timestamp), transaction list (transactions), proof of work (explained later) and the hash value of the previous block.

The following is the structure of a block:

block = { 'index': 1, 'timestamp': 1506057125.900785, 'transactions': [ { 'sender': "8527147fe1f5426f9dd545de4b27ee00", 'recipient': "a77f5cdfa2934df3954a5c7c7da5df1f", 'amount': 5, } ], 'proof': 324984774000, 'previous_hash': "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824" }

At this point, the concept of blockchain is clear. Each new block contains the Hash of the previous block. This is the key point, which ensures the immutability of the blockchain.

If an attacker corrupts one of the preceding blocks, the hashes of all subsequent blocks will become incorrect. If you don't understand it, digest it slowly, you can refer to {% post_link whatbc blockchain technology principle%}.

Join the deal

Next we need to add a transaction to complete the new_transaction method:

class Blockchain(object): ... def new_transaction(self, sender, recipient, amount): """ Generate new transaction information, which will be added to the next block to be mined: param sender:  Address of the Sender : param recipient:  Address of the Recipient :param amount:  Amount :return:  The index of the Block that will hold this transaction """ self.current_transactions.append({ 'sender': sender, 'recipient': recipient, 'amount' : amount, }) return self.last_block['index'] + 1

The method adds a transaction record to the list and returns the index of the block to which the record will be added (the next block to be mined), which will be useful later when the user submits the transaction.

Create new block

When the Blockchain is instantiated, we need to construct a genesis block (the first block without the previous block) and add a proof-of-work to it. Each block needs to go through proof-of-work, commonly known as mining, which will be explained later.

In order to construct the genesis block, we also need to improve the new_block(), new_transaction() and hash() methods:

import hashlib import json from time import time class Blockchain(object): def __init__(self): self.current_transactions = [] self.chain = [] # Create the genesis block self.new_block(previous_hash=1, proof=100) def new_block(self, proof, previous_hash=None): """ 生成新块 :param proof: The proof given by the Proof of Work algorithm :param previous_hash: (Optional) Hash of previous Block :return: New Block """ block = { 'index': len(self.chain) + 1, 'timestamp': time(), 'transactions': self.current_transactions, 'proof': proof, 'previous_hash': previous_hash or self.hash(self.chain[-1]), } # Reset the current list of transactions self.current_transactions = [] self.chain.append(block) return block def new_transaction(self, sender, recipient,amount): """ Generate new transaction information, which will be added to the next block to be mined :param sender: Address of the Sender :param recipient: Address of the Recipient :param amount: Amount :return: The index of the Block that will hold this transaction """ self.current_transactions.append({ 'sender': sender, 'recipient': recipient, 'amount': amount, }) return self.last_block['index'] + 1 @property def last_block(self): return self.chain[-1] @staticmethod def hash(block): """ 生成块的 SHA-256 hash值 :param block: Block :return: """ # We must make sure that the Dictionary is Ordered, or we'll have inconsistent hashes block_string = json.dumps(block, sort_keys=True).encode() return hashlib.sha256(block_string).hexdigest()

Through the above code and comments, we can have an intuitive understanding of the blockchain. Next, let's see how the blocks are mined.

Understanding Proof of Work

New blocks rely on a proof-of-work (PoW) algorithm to construct. The goal of PoW is to find a number that meets certain conditions, which is difficult to calculate but easy to verify. This is the core idea of ​​Proof of Work.

For ease of understanding, here is an example:

Suppose that the hash value of the product of an integer x times another integer y must be 0-terminated, ie hash(x * y) = ac23dc...0. Let the variable x = 5, find the value of y?

Implemented in Python as follows:

from hashlib import sha256 x = 5 y = 0 # y未知 while sha256(f'{x*y}'.encode()).hexdigest()[-1] != "0": y += 1 print(f'The solution is y = {y}')

The result is: y = 21 because:

hash(5 * 21) = 1253e9373e...5e3600155e860

In Bitcoin, a proof-of-work algorithm called Hashcash is used, which is similar to the problem above, where miners compete for the right to create blocks to calculate the results.

Usually, the calculation difficulty is proportional to the number of specific characters that the target string needs to satisfy, and miners are rewarded with bitcoins after calculating the result. Of course, it is very easy to verify this result on the web.

Implement proof-of-work

Let's implement a similar PoW algorithm, the rule is: find a number p such that the hash value of the string concatenated with the proof of the previous block starts with 4 zeros.

import hashlib import json from time import time from uuid import uuid4 class Blockchain(object): ... def proof_of_work(self, last_proof): """ Simple proof of work: - Find a p' such that hash(pp') is 4 0s - p is the proof of the previous block, p' is the current proof :param last_proof:  :return:  """ proof = 0 while self.valid_proof(last_proof, proof) is False: proof += 1 return proof @staticmethod def valid_proof(last_proof, proof): """ Validate proof: Does hash(last_proof, proof) start with 4 zeros? :param last_proof:  Previous Proof :param proof:  Current Proof :return:  True if correct, False if not. """ guess = f'{last_proof}{proof}'.encode() guess_hash = hashlib.sha256(guess).hexdigest() return guess_hash[:4] == "0000"

The way to measure the complexity of the algorithm is to modify the number of leading zeros. Use 4 zeros for demonstration purposes, and you'll see that one more zero greatly increases the time it takes to compute the result.

Now that the Blockchain class is basically complete, the next step is to use HTTP requests to interact.

Blockchain as an API interface

We'll use the Python Flask framework, a lightweight web application framework that facilitates mapping network requests to Python functions, and now let's get Blockchain running on Flask Web.

We will create three interfaces:

/transactions/new creates a transaction and adds it to the block

/mine tells the server to mine new blocks

/chain returns the entire blockchain

create node

Our "Flask server" will act as a node in the blockchain network, let's add some skeleton code first:

import hashlib import json from textwrap import dedent from time import time from uuid import uuid4 from flask import Flask class Blockchain(object): ... # Instantiate our Node app = Flask(__name__) # Generate a globally unique address for this node node_identifier = str(uuid4()).replace('-', '') # Instantiate the Blockchain blockchain = Blockchain() @app.route('/mine', methods=['GET']) def mine(): return "We'll mine a new Block" @app.route('/transactions/new', methods=['POST']) def new_transaction(): return "We'll add a new transaction" @app.route('/chain', methods=['GET']) def full_chain(): response = { 'chain': blockchain.chain, 'length': len(blockchain.chain), } return jsonify(response), 200 if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)

Briefly explain the above code:

Line 15: Create a node.

Line 18: Create a random name for the node.

Line 21: Instance the Blockchain class.

Lines 24–26: Create the /mine GET interface.

Lines 28–30: Create the /transactions/new POST interface, which can send transaction data to the interface.

Lines 32–38: Create the /chain interface, which returns the entire blockchain.

Lines 40–41: The service is running on port 5000.

send transaction

The transaction data structure sent to the node is as follows:

{ "sender": "my address", "recipient": "someone else's address", "amount": 5 }

There are already methods for adding transactions, and adding transactions based on the interface is very simple:

import hashlib import json from textwrap import dedent from time import time from uuid import uuid4 from flask import Flask, jsonify, request ... @app.route('/transactions/new', methods=['POST']) def new_transaction(): values = request.get_json() # Check that the required fields are in the POST'ed data required = ['sender', 'recipient', 'amount'] if not all(k in values for k in required): return 'Missing values', 400 # Create a new Transaction index = blockchain.new_transaction(values['sender'], values['recipient'], values['amount']) response = {'message': f'Transaction will be added to Block {index}'} return jsonify(response), 201

mining

Mining is the magic, it's simple, it does three things:

Computational proof-of-work PoW.

Grant the miner (themselves) a coin by adding a transaction.

Construct a new block and add it to the chain.

import hashlib import json from textwrap import dedent from time import time from uuid import uuid4 from flask import Flask, jsonify, request ... import hashlib import json from time import time from uuid import uuid4 from flask import Flask, jsonify, request ... @app.route('/mine', methods=['GET']) def mine(): # We run the proof of work algorithm to get the next proof... last_block = blockchain.last_block last_proof = last_block['proof'] proof = blockchain.proof_of_work(last_proof) # 给工作量证明的节点提供奖励. # 发送者为 "0" 表明是新挖出的币 blockchain.new_transaction( sender="0", recipient=node_identifier, amount=1, ) # Forge the new Block by adding it to the chain block = blockchain.new_block(proof) response = { 'message': "New Block Forged", 'index': block['index'], 'transactions':block['transactions'], 'proof': block['proof'], 'previous_hash': block['previous_hash'], } return jsonify(response), 200

Note that the recipient of the transaction is our own server node, and most of the work we do is just interacting around the Blockchain class methods. At this point, our blockchain is complete, let's actually run it.

run the blockchain

You can use cURL or Postman to interact with the API.

Start the server:

$ python blockchain.py * Runing on https://127.0.0.1:5000/ (Press CTRL+C to quit)

Let's mine by requesting https://localhost:5000/mine:

\

With a post request, add a new transaction:

\

If you're not using Postman, it's the same with the following cURL statement:

$ curl -X POST -H "Content-Type: application/json" -d '{ "sender": "d4ee26eee15148ee92c6cd394edd974e", "recipient": "someone-other-address", "amount": 5 }' "https://localhost:5000/transactions/new"

After mining twice, there are 3 blocks, all block information can be obtained by requesting https://localhost:5000/chain.

{ "chain": [ { "index": 1, "previous_hash": 1, "proof": 100, "timestamp": 1506280650.770839, "transactions": [] }, { "index": 2, "previous_hash": "c099bc...bfb7", "proof": 35293, "timestamp": 1506280664.717925, "transactions": [ { "amount": 1, "recipient": "8bbcb347e0634905b0cac7955bae152b", "sender": "0" } ] }, { "index": 3, "previous_hash": "eff91a...10f2", "proof": 35089, "timestamp": 1506280666.1086972, "transactions": [ { "amount": 1, "recipient": "8bbcb347e0634905b0cac7955bae152b", "sender": "0" } ] } ], "length": 3 }

Consistency (Consensus)

We already have a basic blockchain that accepts transactions and mining, but the blockchain system should be distributed.

Since it is distributed, what exactly do we use to ensure that all nodes have the same chain? This is the consistency problem. If we want to have multiple nodes on the network, we must implement a consistent algorithm.

register node

Before implementing the consensus algorithm, we need to find a way for a node to know its neighbors.

Each node needs to keep a record of other nodes in the network, so let's add a few more interfaces:

/nodes/register receives a list of new nodes as a URL.

/nodes/resolve executes the consensus algorithm, resolves any conflicts, and ensures that nodes have the correct chain.

We modify Blockchain's init function and provide a method for registering nodes:

... from urllib.parse import urlparse ... class Blockchain(object): def __init__(self): ... self.nodes = set() ... def register_node(self, address): """ Add a new node to the list of nodes :param address: Address of node. Eg. 'https://192.168.0.5:5000' :return: None """ parsed_url = urlparse(address) self.nodes.add(parsed_url.netloc)

We use a set to store nodes, which is an easy way to avoid adding nodes repeatedly.

Implement a consensus algorithm

As mentioned earlier, conflict means that different nodes have different chains. In order to solve this problem, it is stipulated that the longest and valid chain is the final chain. In other words, the longest valid chain in the network is the actual chain.

We use the following algorithm to achieve consensus in the network:

... import requests class Blockchain(object) ... def valid_chain(self, chain): """ Determine if a given blockchain is valid :param chain: A blockchain :return: True if valid, False if not """ last_block = chain[0] current_index = 1 while current_index < len(chain): block = chain[current_index] print(f'{last_block}') print(f'{block}') print("\n-----------\n") # Check that the hash of the block is correct if block['previous_hash'] != self.hash(last_block): return False # Check that the Proof of Work is correct if not self.valid_proof(last_block['proof'], block['proof']): return False last_block = block current_index += 1 return True def resolve_conflicts(self): """ 共识算法解决冲突 使用网络中最长的链. :return: True 如果链被取代, 否则为False """ neighbours = self.nodes new_chain = None # We're only looking for chains longer than ours max_length = len(self.chain) # Grab and verify the chains from all the nodes in our network for node in neighbours: response = requests.get(f'https://{node}/chain') if response.status_code == 200: length = response.json()['length'] chain = response.json()['chain'] # Check if the length is longer and the chain is valid if length > max_length and self.valid_chain(chain): max_length = length new_chain = chain # Replace our chain if we discovered a new, valid chain longer than ours if new_chain: self.chain = new_chain return True return False

The first method valid_chain() is used to check whether it is a valid chain, traversing each block to verify the hash and proof.

The second method resolve_conflicts() is used to resolve conflicts, traverse all neighbor nodes, and use the previous method to check the validity of the chain. If a longer valid chain is found, it will replace its own chain.

Let's add two routes, one to register the node and one to resolve conflicts.

@app.route('/nodes/register', methods=['POST']) def register_nodes(): values = request.get_json() nodes = values.get('nodes') if nodes is None: return "Error: Please supply a valid list of nodes", 400 for node in nodes: blockchain.register_node(node) response = { 'message': 'New nodes have been added', 'total_nodes': list(blockchain.nodes), } return jsonify(response), 201 @app.route('/nodes/resolve', methods=['GET']) def consensus(): replaced = blockchain.resolve_conflicts() if replaced: response = { 'message': 'Our chain was replaced', 'new_chain': blockchain.chain } else: response = { 'message': 'Our chain is authoritative', 'chain': blockchain.chain } return jsonify(response), 200

You can run nodes on different machines, or open different network ports on one machine to simulate a multi-node network.

Here is a demonstration of opening different ports on the same machine. Run the following commands in different terminals to start two nodes:

https://localhost:5000

https://localhost:5001

pipenv run python blockchain.py pipenv run python blockchain.py -p 5001

\

Then dig two blocks on node 2 to ensure a longer chain, and then access the interface /nodes/resolve on node 1. At this time, the chain of node 1 will be replaced by the chain of node 2 through the consensus algorithm.

\

Well, you can invite your friends to test your blockchain together.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324994907&siteId=291194637