Tự xây dựng một hệ thống Blockchain đơn giản

Nói đến Bitcoin có lẽ ai cũng biết, nhưng không phải ai cũng biết đến Blockchain, công nghệ sử dụng để xây dựng đồng tiền ảo mạnh nhất thế giới đến thời điểm hiện tại. Theo cafef:

Blockchain là công nghệ lưu trữ và truyền tải thông tin bằng các khối được liên kết với nhau và mở rộng theo thời gian do đó được gọi là chuỗi khối (blockchain). Mỗi khối chứa đựng các thông tin về thời gian khởi tạo và được liên kết với các khối trước đó. Blockchain được thiết kế để chống lại sự thay đổi dữ liệu. Thông tin trong blockchain không thể bị thay đổi và chỉ được bổ sung thêm khi có sự đồng thuận của tất cả các nút trong hệ thống. Ngay cả khi nếu một phần của hệ thống blockchain sụp đổ, những máy tính và nút khác sẽ tiếp tục hoạt động để bảo vệ thông tin.

Bạn có thể tìm hiểu thêm về Blockchain và Bitcoin từ nhiều nguồn trên internet, cả tiếng Anh và tiếng Việt, ví dụ như từ bài viết này trên genk hoặc video này từ Diễn đàn kinh tế thế giới (World Economic Forum). Trong phạm vi bài viết này, mình sẽ tiến hành xây dựng một hệ thống Blockchain đơn giản, theo hướng dẫn từ bài viết Learn Blockchains by Building One của tác giả Daniel van Flymen được đăng tải trên medium. Bạn có thể xem mã nguồn của bài viết tại github của mình (có chỉnh sửa sắp xếp lại so với mã nguồn gốc của Daniel)

Github: https://github.com/nvh95/blockchain_demo

Chuẩn bị

Trước hết, Blockchain là chuỗi các bản ghi bất biến, gọi là Block. Nó có thể bao gồm các giao dịch, file hoặc bất cứ kiểu dữ liệu nào. Một khái niệm quan trọng mà bạn cần biết trước khi bắt đầu đó là hash.

Bạn có thể hiểu hash là một ánh xạ từ x->y=f(x), sao cho mỗi x sẽ có duy nhất một y. Nếu chưa chắc chắn về hash, hãy xem thêm tại đây

Bài viết này sẽ sử dụng Python 3.6+, Flask 0.12.2 và requests 2.18.4. Cài đặt Flask và requests sử dụng lệnh:
pip install Flask==0.12.2 requests==2.18.4

Các bạn có thể sử dụng bất cứ một IDE hay text editor nào để code, cá nhân mình chọn Pycharm vì nó dễ dùng, chức năng gợi ý code hỗ trợ viết code tốt.

Bước 1: Xây dựng Blockchain

Trước hết là xây dựng cấu trúc của Blockchain, mình sẽ xây dựng class Blockchain trong file blockchain.py Dưới đây là khung của class Blockchain

class Blockchain(object):
    def __init__(self):
        self.chain = []
        self.current_transaction = []

    def new_block(self):
        """Create a new block and adds it the the chain"""
        pass

    def new_transaction(self, sender, recipient, amount):
        """
        Creates a new transaction to go into the next mined Block

        :param sender: <str> Address of the sender
        :param recipient: <str> Address of the recipient
        :param amount:  <int> Amount
        :return: <int> Index of block gold this transaction
        """

        self.current_transaction.append({
            'sender': sender,
            'recipient': recipient
        })

    @staticmethod
    def hash(block):
        """Hash a block"""
        pass

    @property
    def last_block(self):
        """Returns the last block in the chain"""
        pass

Constructor của class này khởi tạo một list rỗng để chứa blockchain và một list khác để lưu các giao dịch. Class sẽ có chức năng lưu trữ các chain và một số hàm có một số chức năng như thêm một khối mới hoặc một giao dịch mới.

Cấu trúc của một khối

Mỗi một khối (block) sẽ có index, timestamp, danh sách các giao dịch và proof (sẽ nói chi tiết hơn ở sau) và hash của khối trước. Dưới đây là một khối ví dụ

block ={"index": 8,
            "previous_hash": "76c16ecf0b8e83cabae7e3c4e0c1898db0c31d7ed7a4e5de63d82cec4b4cc3db",
            "proof": 9675,
            "timestamp": 1507383586.468118,
            "transactions": [
                {
                    "amount": 1,
                    "recipient": "19501b91d05a41f1915b6a2830a074c2",
                    "sender": "0"
                }
            ]}

Hãy dành chút thời gian để suy nghĩ về việc mỗi một block chứa trong nó hash của block ngay trước đó. Điều này khiến cho blockchain có tính bất biến, nếu một block bị hacker thay đổi thì các block sau sẽ bị hỏng vì hash sẽ không còn đúng nữa, đồng nghĩa với việc có điều gì đó không ổn đã xảy ra.

Thêm một giao dịch vào Block

Chúng ta sẽ implement hàm new_transaction()

    def new_transaction(self, sender, recipient, amount):
        """
        Creates a new transaction to go into the next mined Block
        :param sender: <str> Address of the sender
        :param recipient: <str> Address of the recipient
        :param amount:  <int> Amount
        :return: <int> Index of block gold this transaction
        """

        self.current_transactions.append({
            'sender': sender,
            'recipient': recipient,
            'amount': amount,
        })

        return self.last_block['index'] + 1

Hàm này thêm một giao dịch vào list và trả về index của block mà giao dịch đó sẽ được thêm vào (là block tiếp theo được đào). Bạn sẽ hiểu rõ vấn đề hơn khi code chức năng đào một khối mới (mining-đào tiền)

Tạo khối mới

Khi khởi tạo Blockchain, chúng ta cần phải khởi tạo block genesis, đây là block đầu tiên (tham số proof sẽ được giải thích kỹ hơn ở phần sau)

class Blockchain(object):
    def __init__(self):
        self.current_transactions = []
        self.chain = []

        # Create the genesis block
        self.new_block(previous_hash=1, proof=100)

Chúng ta cũng implement các hàm new_block(), new_transaction()hash(). Code dưới đấy đi kèm comment khá dễ hiểu.
Cụ thể:
– Hàm new_block() sẽ tạo ra một block mới và đẩy nó vào trong Blockchain.
– Hàm new_transaction() tạo ra một giao dịch mới, sau này sẽ được lưu vào Block được đào tiếp theo.
– Hàm hash() để tạo hash cho Block. Cụ thể ở đây sử dụng SHA-256


    def new_block(self, proof, previous_hash=None):
        """
        Create a new block and adds it the the chain
        :param proof: <int> The proof given by the Proof of Work algorithm
        :param previous_hash: (Optional) <str> hash of the previous block
        :return: <dict> a 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 transaction
        self.current_transactions = []

        self.chain.append(block)

        return block

    def new_transaction(self, sender, recipient, amount):
        """
        Creates a new transaction to go into the next mined Block

        :param sender: <str> Address of the sender
        :param recipient: <str> Address of the recipient
        :param amount:  <int> Amount
        :return: <int> Index of block gold this transaction
        """

        self.current_transactions.append({
            'sender': sender,
            'recipient': recipient,
            'amount': amount,
        })

        return self.last_block['index'] + 1

    @staticmethod
    def hash(block):
        """
        Hash a block using SHA-256
        :param block: <dict> Block
        :return: <str>
        """

        # The dictionary must be ordered, or we'll have inconsistent hashes
        block_string = json.dumps(block, sort_keys=True).encode()

        return hashlib.sha256(block_string).hexdigest()

Proof of Work là gì

Phần này sẽ mô tả cơ chế hoạt động của Bitcoin/Blockchain. Đây là phần khiến những người mới tìm hiểu cảm thấy khó hiểu nhất. Khi tra khảo trên mạng hoặc được người khác giải thích, bạn sẽ nghe thấy rằng: “Tiền ảo kiếm được là do chúng ta giải các bài toán phức tạp, sau khi giải được bài toán đó thì ta sẽ được… tặng tiền”.
Mình xin dám chắc phần lớn các bạn sẽ được giải thích trên và phản ứng của bạn sẽ là rất khó hiểu. Thế quái nào mà giải toán mà lại được tiền? Nghe vô lý thế, vậy thiên hạ đổ xô đi giải toán à? Hay bọn này lừa đảo nhỉ?
Trong phần này, mình sẽ giải đáp cho các bạn câu hỏi “Làm sao giải toán mà lại được tiền?” đi kèm ví dụ và mã nguồn minh hoạ để các bạn có thể tự cài đặt được.
Trước hết hãy nhắc lại về hash. Nó là một cách mã hoá hiểu nôm na như một hàm số. Cho hai đầu vào giống nhau thì sẽ luôn cho ra một kết quả giống nhau. Nhưng nếu có một đầu ra thì rất rất khó để có thể tìm lại được đầu vào. Bạn hãy xem lại ở đây (https://learncryptography.com/hash-functions/what-are-hash-functions).
Bài toán chúng ta đi tìm hiểu trong phần này là Proof of Work (PoW), nó là cách một khối của Blockchain được đào hoặc được tạo ra. Mục tiêu của chúng ta là tìm ra được lời giải của bài toán (thường là một con số). Tương tự, số đó phải dễ dàng kiểm chứng nhưng rất khó để tìm ra bởi bất cứ ai trong hệ thống.

Hãy lấy một ví dụ để làm rõ vấn đề này hơn. Giả sử ta có hai số xy. Bài toán của chúng ta là hash của x*y phải kết thúc bởi số 0, cụ thể hash(x*y) = a2hc1w....0. Để cho đơn giản. giả sử x = 5. Hãy xem lời giải của bài toán qua đoạn code dứoi đây:

from hashlib import sha256
x = 5
y = 0  # We don't know what y should be yet...
while sha256(f'{x*y}'.encode()).hexdigest()[-1] != "0":
    y += 1
print(f'The solution is y = {y}')

Đáp án là y = 21. Vì

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

Trong bitcoin thì thuật toán Proof of Work này gọi là Hashcash. Và nó cũng tương tự như ví dụ bên trên. Trong thực tế, các tay đào bitcoin phải giải những bài toán phức tạp hơn thế này gấp nhiều lần. Ví dụ như hash phải bắt đầu bằng chuỗi “123456” chẳng hạn (thực tế ví dụ này vẫn rất đơn giản và chỉ mất có 92 giây để tìm được lời giải). Việc một người giải được bài toán thì khó chứ để xác thực là người đó có giải được bài toán hay không thì rất đơn giản. Và để trả công cho người giải được thì người đó sẽ được thưởng một đơn vị tiền qua một giao dịch.

(Ví dụ vè một bài toán khó hơn, tìm (x,y) sao cho hash(x*y) bắt đầu bằng chuỗi "123456", có thể thấy ở file proof_of_work.py trên repository của mình)

from hashlib import sha256
from time import time
from random import randint

x = randint(0,10000)
y = 0
t1 = time()
while (sha256(f'{x*y}'.encode()).hexdigest()[:6] != '123456'):
    print(y)
    y +=1

print("x = {}".format(x))
print("y = {}".format(y))
print(sha256(f'{x*y}'.encode()).hexdigest())
t2= time()
print(t2-t1)

# x = 5385
# y = 21069182
# hash(x*y) = 123456432081821574050d2ee4a7acef0f94a52a1011a77ad5e2f37543cf8629
# total_time_to_find_y = 92.40833306312561

Cài đặt Proof of Work

Xét bài toán tương tự: Tìm số p sao cho khi hash(pp') thì 4 ký tự đầu đều là số 0 (p' cho trước-là proof_of_work của block trước)

def proof_of_work(self, last_proof):
    """
    Simple proof of work algorithm:
    - Find a number p' satisfied valid_proof() function
    - p is the previus proof, p' is the new proof

    :param last_proof: <int>
    :return: <int> new poof
    """
    proof = 0
    while self.valid_proof(last_proof, proof) is False:
        proof += 1

    return proof

@staticmethod
def valid_proof(last_proof, proof):
    """
    Validate the proof if:
    - hash(last_proof, proof) contains 4 leading zeroes

    :param last_proof: <int> previous proof
    :param proof: <int> current proof
    :return: <bool> true or false
    """

    guess = f'{last_proof*proof}'.encode()
    guess_hash = hashlib.sha256(guess).hexdigest()
    return guess_hash[:4] == '0000'

Bài toán của bạn có thể thay đổi để tăng độ khó lên. Bạn có thể thay đổi một cách đơn giản.
Đến đây, chúng ta đã implement gần xong phần lõi của hệ thống Blockchain rồi. Tiếp đến sẽ là phần tương tác để sử dụng hệ thống này qua HTTP.

Bước 2: Xây dựng API

Phần này chúng ta sẽ sử dụng Flask, framework khá đơn giản và dễ dùng sẽ giúp chúng ta có thể tiến hành các thao tác với hệ thống Blockchain vừa xây dựng.

Chúng ta sẽ cài đặt 3 method:

  • /transactions/new to create a new transaction to a block
  • /mine to tell our server to mine a new block.
  • /chain to return the full Blockchain.

Setting up Flask

Để thuận lợi hãy tạo file server.py và dựng khung chương trình

from uuid import uuid4

from blockchain import Blockchain

from flask import Flask, jsonify

# 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 will mind a new Block"

@app.route('/transaction/new', methods=['POST'])
def new_transaction():
    return "Well will 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__':
    from argparse import ArgumentParser
    parser = ArgumentParser()
    parser.add_argument('-p', '--port', default=5000, type=int, help='port listening')
    args = parser.parse_args()
    port = args.port
    app.run(host='0.0.0.0', port=port)

Tóm tắt đoạn code trên:

  • Dòng 8 : Khởi tạo Flask
  • Dòng 11: Tạo tên ngẫu nhiên cho node.
  • Dòng 14: Khởi tạo Blockchain class.
  • Dòng 16–8: Tạo /mine endpoint, là GET request.
  • Dòng 20–22: Tạo /transactions/new endpoint, là POST request, chúng ta sẽ gửi dữ liệu đến đó.
  • Dòng 24-30: Tạo /chain endpoint, trả về full Blockchain.
  • Dòng 32-38: Chạy server.

The Transactions Endpoint

Một request lên server sẽ có dạng như sau:

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

Chúng ta đã code hàm để thêm một giao dịch vào block. Công việc còn lại khá đơn giản:

@app.route('/transactions/new', methods=['POST'])
def new_transaction():
    values = request.get_json()
    print(values)
    # 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 parameters', 400

    # Crate 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

The Mining Endpoint

Mining Endpoint là nơi các hoạt động đào được diễn ra. Nó sẽ phụ trách 3 việc sau:

  1.  Tính toán Proof Of Work
  2. Thưởng cho người thành công 1 đồng tiền
  3. Tạo ra một block mới và thêm vào chain
@app.route('/mine', methods=['GET'])
def mine():
    # Run 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)

    # We must receive a reward for finding the proof.
    # The sender is '0' to signify that this node has mined a new coin
    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

Ta có thể thấy rằng địa chỉ người nhận là địa chỉ của chúng ta, người gửi là 0, là hệ thống.

Bước 3: Tương tác với hệ thống

Phần này mình sử dụng Postman để minh hoạ hệ thống. Trước hết, hãy chạy server bằng lệnh:

$ python blockchain.py --port 5000
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

Chúng ta hãy bắt đầu bằng việc đào (mine) bằng cách gửi một request GET đến http://localhost:5000/mine. Bạn có thể nhìn thấy bạn đã được thưởng 1 coin, và một giao dịch được khởi tạo với người nhận là bạn, ngưởi gửi là hệ thống (hệ thống có địa chỉ là 0)
Screen Shot 2017-10-19 at 12.53.53 AM.png
Hãy tạo một giao dịch mới bằng việc gửi một request POST đến http://localhost:5000/transactions/new với nội dung như hình.
Screen Shot 2017-10-19 at 12.58.10 AM.png
Hãy gửi một request GET đến http://localhost:5000/chain để xem toàn bộ nội dung của dãy chain.
Screen Shot 2017-10-19 at 12.59.40 AM.png

Bước 4: Consensus

Chúng ta đã đi được một chặng đường tương đối. Đã xây dựng được một hệ thống Blockchain cơ bản, chạy được, có thể tiến hành đào và giao dịch. Tuy nhiên, một đặc điểm quan trọng của các hệ thống Blockchain đó là tính phân tán. Có nghĩa là hệ thống này sẽ được lưu trữ ở nhiều thiết bị khác nhau. Điều này nảy sinh một vấn đề đó là làm sao tất cả các nơi khác lưu trữ hệ thống này đều có chuối blockchain giống nhau. Câu hỏi này đươc đặt ra và có tên là Problem of Consensus. Trong phần này, chúng ta sẽ cài đặt thuật toán Consensus để giải quyết vấn đề khi trong mạng cho hơn hai node.

Register node mới

Để có thể cài đặt được thuật toán Consensus, chúng ta phải khiến các node trong mạng biết đến sự tồn tại của nhau. Mỗi node cần lưu trữ thông tin của các node khác. Chúng ta sẽ tiến hành cài đặt thêm hai endpoint:

  1. /nodes/register làm công việc giúp các node biết đến sự tồn tại của các nút khác
  2. /nodes/resolve cài đặt thuật toán Consensus, giải quyết xung đột để chắc chắn rằng tất cả các node đều có chung một chuỗi Blockchain

Chúng ta cần sửa một chút constructor và cung cấp một method để register các node:

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: <str> Address od node (e.g: http://192.168.0.2:5000')
        :return: None
        """

        parsed_url = urlparse(address)
        self.nodes.add(parsed_url.netloc)

Chúng ta sử dụng cấu trúc dữ liệu set() để lưu trữ các node vì tính chất của set() chỉ lưu trữ các phần tử khác nhau nên chúng ta có register node nhiều lần cũng không vấn đề gì.

Cài đặt thuật toán Consensus

Trong một mạng Blockchain, xung đột xảy ra khi các node trong mạng không có chung một chuỗi Blockchain. Để giải quyết vấn đề này, chúng ta sẽ sử dụng luật chuỗi nào dài nhất là chuối hợp lệ.

class Blockchain(object)
    ...

    @staticmethod
    def valid_proof(last_proof, proof):
        """
        Validate the proof if:
        - hash(last_proof, proof) contains 4 leading zeroes

        :param last_proof: <int> previous proof
        :param proof: <int> current proof
        :return: <bool> true or false
        """

        guess = f'{last_proof*proof}'.encode()
        guess_hash = hashlib.sha256(guess).hexdigest()
        return guess_hash[:4] == '0000'

    def valid_chain(self, chain):
        """
        Determine if a given blockchain is valid
        :param chain: <list> A blockchain
        :return: <bool> 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 has 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):
        """
        Consensus Algorithm: resolves conflicts by replacing
        our chain with the longest one in the network
        :return: <bool> True if our blockchain was replaced, False if not
        """

        neighbors = self.nodes
        new_chain = None

        # We're only looking for chains longer than ours
        max_length = len(self.chain)

        # Downloads and Verify the chains from all the nodes in our networks
        for node in neighbors:
            response = requests.get(f'http://{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 there is a new, valid chain longer than ours
        if new_chain:
            self.chain = new_chain
            return True
        return False

Method valid_chain() chịu trách nhiệm cho việc kiểm tra một chain có hợp lệ hay không
Method resolve_conflicts() kiểm tra xem các node trong mạng có hợp lệ hay không. Nếu một chain hợp lệ và dài hơn chain hiện tại thì nó sẽ tiến hành thay thế chain hiện tại.

Chúng ta tiến hành thêm 2 endpont API như đã nói bên trên

@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

Đến đây bạn có thể lấy một máy tính khác để tạo thành một node mới, hoặc có thể chạy chương trình trên các cổng khác nhau. Mình sẽ chạy thêm chương trình với cổng 5001, sau đó register.
Screen Shot 2017-10-19 at 12.48.54 AM.png
Mình sẽ tiến hành đào một vài coin ở node mới tạo (cổng 5001).
Screen Shot 2017-10-19 at 12.49.26 AM.png
Sau đó gọi /nodes/resolve ở node 1 và thấy rằng chuỗi chain ở node 5000 đã được thay thế bởi chuỗi chain ở node 5001 (dài hơn và hợp lệ)
Screen Shot 2017-10-19 at 12.49.51 AM.png

Vậy là đã xong. Bạn đã tự tay xây dựng được cho mình một hệ thống Blockchain đơn giản với những chức năng cơ bản nhất. Hi vọng bài viết sẽ giúp bạn hiểu hơn về Blockchain, một trong những công nghệ mới và hot nhất hiện nay.

P.S: Sau khi tự xây dựng được một hệ thống Blockchain, để hiểu hơn về cấu trúc thiết kế của đồng tiền ảo Bitcoin, mình gợi ý mọi người hãy xem paper Bitcoin: A Peer-to-Peer Electronic Cash System của Satoshi Nakamoto được công bố vào năm 2008. Bạn sẽ thấy được hệ thống Bitcoin được thiết kế phức tạp hơn hệ thống của chúng ta nhiều lần. Tuy nhiên, bạn sẽ thấy những khái niệm quan trọng tương tự xuất hiện trong bài báo như transactions, proof of work, phân phối nodes trong network, mining gold (trong phần 6. Incentive)…

Một suy nghĩ 11 thoughts on “Tự xây dựng một hệ thống Blockchain đơn giản

  1. Bài viết này sẽ sử dụng Python 3.6+, Flask 0.12.2 và requests 2.18.4. Cài đặt Flask và requests sử dụng lệnh:
    pip install Flask==0.12.2 requests==2.18.4

    Mình cài Python okay, Flask và requests không hiểu lắm, bạn cho link tải nha.
    Cái này mình có thể cài đặt trên máy win chạy được không? hay phải linux?
    Thanks.

    Thích

    1. Chạy trên windows được bạn nhé. Bạn cứ mở cmd lên và gõ lệnh pip install Flask==0.12.2 requests==2.18.4 vào thôi. Nếu bị lỗi thì bạn hãy mở cmd bằng quyền Administrator rồi chạy lại lệnh trên là được.

      Thích

  2. Mình chạy thử request POST đến http://localhost:5000/transactions/new
    thông tin:
    {
    “sender”: “02a63a8be75745debb1f8a5bff83ed43”,
    “recipient”: “12a63a8be75745debb1f8a5bff83ed43”,
    “amount”: 5
    }
    nó báo:

    Internal Server Error

    The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.

    Vậy là sao hả bạn?

    Thích

  3. Cảm ơn anh về bài viết rất rõ ràng cho người mới bắt đầu như em, em có một số thắt mắc mong được giải đáp:
    Nếu ứng dụng blockchain vào các lĩnh vực khác thì PoW có quan trọng không, và có thể bỏ qua nó không.
    Em chưa hiểu lắm về cách lưu trữ các dữ liệu của blockchain và làm sao để các transaction có thể đồng nhất với tất cả máy khác trong mạng lưới blockchain.

    Thích

  4. sao mình clone code về rồi chạy python blockchain.py –port 5000 nó báo lỗi như thế này vậy b:
    File “blockchain.py”, line 112
    guess = f'{last_proof*proof}’.encode()
    ^
    SyntaxError: invalid syntax

    Thích

  5. Cho mình hỏi : Ở bước số 3 đoạn POST sender là cái địa chỉ recipient ở đoạn GET mine. Vậy recipient là địa chỉ nào lấy ở đâu.
    Thanks

    Thích

Bình luận về bài viết này