Làm cách nào để tạo một chuỗi khối bằng Python?

Spread the love

Bạn có biết rằng Bitcoin được xây dựng dựa trên Blockchain không? Hôm nay chúng ta sẽ xây dựng một Blockchain bằng Python từ đầu.

Chuỗi khối là gì?

Năm 2008 các giấy bitcoin được xuất bản bởi một cá nhân hoặc nhóm không xác định tên là Satoshi Nakamoto. Bitcoin ra đời như một phiên bản ngang hàng của tiền điện tử cho phép giao dịch mà không cần thông qua các tổ chức tập trung (ngân hàng). Hầu hết mọi người không biết rằng trong cùng một bài báo đó, Satoshi đã định nghĩa một cách lưu trữ thông tin phân tán, ngày nay được gọi là Blockchain.

công nghệ chuỗi khối

Nói một cách đơn giản, Blockchain là một sổ cái kỹ thuật số được chia sẻ, bất biến, lưu trữ các giao dịch trên một mạng máy tính phi tập trung.

Chúng ta có thể chia Blockchain thành hai thuật ngữ đơn giản:

  • Chặn: Một không gian nơi chúng tôi lưu trữ các giao dịch
  • Chuỗi: Một tập hợp các bản ghi được liên kết

Điều này định nghĩa Blockchain là một chuỗi các khối được liên kết, trong đó mỗi khối lưu trữ một giao dịch được thực hiện với các tham số cụ thể.

Mỗi khối được xây dựng trên một khối khác, tạo ra một chuỗi khối không thể đảo ngược. Nói cách khác, mọi khối phụ thuộc vào khối khác. Điều này trở thành một hệ thống mạnh mẽ và bất biến, trong đó bất kỳ ai có quyền phù hợp đều có thể xem xét tính toàn vẹn.

Blockchain giới thiệu một bộ tính năng thú vị:

  • lịch sử bất biến
  • Độ bền của thông tin
  • Không có lỗi với dữ liệu được lưu trữ

Rất nhiều hệ thống hiện đang dựa vào Blockchain, chẳng hạn như tiền điện tử, chuyển giao tài sản (NFT) và có thể trong tương lai gần là bỏ phiếu.

Điều đáng nói là Chuỗi khối Python không phải là một chương trình phức tạp với hàng nghìn dòng mã. Về cốt lõi, nó sẽ là một danh sách các giao dịch được liên kết với nhau.

Tất nhiên, đây là một lời giải thích ngắn gọn, nhưng nếu bạn muốn có một hướng dẫn đầy đủ, chúng tôi đã tạo ra một hướng dẫn đầy đủ về Blockchain cho người mới bắt đầu. Hãy chắc chắn để kiểm tra nó ra.

Còn chần chừ gì nữa, hãy xây dựng một Blockchain đơn giản với Python.

Xây dựng chuỗi khối với Python

Trước khi bắt đầu, hãy xác định những gì chúng ta sẽ làm trong hướng dẫn này:

  • Xây dựng hệ thống Blockchain đơn giản viết bằng Python
  • Sử dụng Chuỗi khối của chúng tôi với các giao dịch được thiết lập trước được biểu thị dưới dạng chuỗi
  • Kiểm tra tính bất biến của Blockchain của chúng tôi

Chúng tôi sẽ không sử dụng danh sách JSON mà là Python. Điều này sẽ cho phép chúng tôi đơn giản hóa quy trình và tập trung vào việc áp dụng các khái niệm chính của Chuỗi khối.

  Cách chỉnh sửa tin nhắn trên iPhone, iPad và Mac

Những gì bạn sẽ cần để làm theo hướng dẫn này:

Tạo lớp Khối

Mở trình chỉnh sửa mã yêu thích của bạn và tạo tệp main.py. Đây sẽ là tập tin chúng tôi sẽ làm việc với.

Bây giờ, nhập khẩu hashlib, một mô-đun cho phép chúng tôi tạo tin nhắn được mã hóa một chiều. Các kỹ thuật mã hóa như băm giúp Blockchain tạo ra các giao dịch an toàn.

Hàm băm là một thuật toán lấy một số dữ liệu (thường là một chuỗi được mã hóa) và trả về một mã định danh duy nhất, thường được đặt tên là “tiêu hóa” hoặc “chữ ký”. Phần cuối cùng này rất quan trọng; với hàm băm, một sự khác biệt nhỏ trong đầu vào sẽ tạo ra một mã định danh hoàn toàn khác làm đầu ra. Chúng ta sẽ thấy điều này trong hành động sau này.

Hiện tại, chỉ cần nhập hashlib mô-đun tích hợp:

# main.py file
"""
A simple Blockchain in Python
"""

import hashlib

Mô-đun này bao gồm hầu hết các thuật toán băm mà bạn sẽ cần. Chỉ cần lưu ý rằng chúng ta sẽ sử dụng hàm hashlib.sha256().

Bây giờ, hãy truy cập vào GeekCoinBlock, tên chuỗi khối hoàn toàn nguyên bản của chúng tôi.

class GeekCoinBlock:
    
    def __init__(self, previous_block_hash, transaction_list):

        self.previous_block_hash = previous_block_hash
        self.transaction_list = transaction_list

        self.block_data = f"{' - '.join(transaction_list)} - {previous_block_hash}"
        self.block_hash = hashlib.sha256(self.block_data.encode()).hexdigest()

Tôi biết điều này có thể dẫn đến một đoạn mã lộn xộn. Hãy chia nhỏ từng phần trong phần tiếp theo.

Giải thích khối GeekCoin

Đầu tiên, chúng tôi tạo một lớp có tên GeekCoinBlock, một trình bao bọc cho các đối tượng sẽ có các đặc điểm (thuộc tính) và hành vi (phương thức) nhất định.

Sau đó, chúng tôi xác định phương thức __init__ (cũng được đặt tên là hàm tạo), được gọi mỗi khi một đối tượng GeekCoinBlock được tạo.

Phương thức này có ba tham số:

  • self (thể hiện của từng đối tượng)
  • previous_block_hash (tham chiếu đến khối trước đó)
  • transaction_list (danh sách các giao dịch được thực hiện trong khối hiện tại).

Chúng tôi lưu trữ danh sách giao dịch và hàm băm trước đó và tạo một biến thể hiện block_data dưới dạng một chuỗi. Điều này không xảy ra với tiền điện tử thực, trong đó chúng tôi lưu trữ loại dữ liệu đó dưới dạng hàm băm khác, nhưng vì mục đích đơn giản, chúng tôi sẽ lưu trữ mọi khối dữ liệu dưới dạng chuỗi.

Cuối cùng, chúng tôi tạo block_hash, mà các khối khác sẽ sử dụng để tiếp tục chuỗi. Đây là nơi hashlib có ích; thay vì tạo một hàm băm tùy chỉnh, chúng ta có thể sử dụng sha256 dựng sẵn để tạo các khối bất biến.

Hàm này nhận các chuỗi (hoặc byte) được mã hóa làm tham số. Đó là lý do tại sao chúng tôi đang sử dụng phương thức block_data.encode(). Sau đó, chúng tôi gọi hexdigest() để trả lại dữ liệu được mã hóa thành định dạng thập lục phân.

Tôi biết tất cả những điều này có thể khiến bạn choáng ngợp, vì vậy hãy chơi với hashlib trên trình bao Python.

In [1]: import hashlib

In [2]: message = "Python is great"

In [3]: h1 = hashlib.sha256(message.encode())

In [4]: h1
Out[4]: <sha256 ... object @ 0x7efcd55bfbf0>

In [5]: h1.hexdigest()
Out[5]: 'a40cf9cca ... 42ab97'

In [6]: h2 = hashlib.sha256(b"Python is not great")

In [7]: h2
Out[7]: <sha256 ... object @ 0x7efcd55bfc90>

In [8]: h2.hexdigest()
Out[8]: 'fefe510a6a ... 97e010c0ea34'

Như bạn có thể thấy, một thay đổi nhỏ trong đầu vào như “Python rất tuyệt” thành “Python không tuyệt” có thể tạo ra một hàm băm hoàn toàn khác. Tất cả điều này liên quan đến tính toàn vẹn của Blockchain. Nếu bạn đưa một số thay đổi nhỏ vào một chuỗi khối, hàm băm của nó sẽ thay đổi đáng kể. Đây là lý do tại sao câu nói “Bạn không thể làm hỏng một Blockchain” là đúng.

  Hiểu thuật ngữ chính của AWS cho người mới bắt đầu

Sử dụng Lớp khối của chúng tôi

Chúng ta sẽ xây dựng toàn bộ lớp Blockchain sau, nhưng bây giờ, hãy sử dụng lớp Block của chúng ta để tạo một chuỗi các khối (Blockchain).

Trong cùng một tệp, hãy tạo một vài giao dịch được tạo thành từ các chuỗi đơn giản được lưu trữ trong các biến, ví dụ:

class GeekCoinBlock:
    ...

t1 = "Noah sends 5 GC to Mark"
t2 = "Mark sends 2.3 GC to James"
t3 = "James sends 4.2 GC to Alisson"
t4 = "Alisson sends 1.1 GC to Noah"

Tất nhiên, GC đề cập đến GeekCoin

Bây giờ, hãy xây dựng khối đầu tiên của Chuỗi khối của chúng tôi bằng cách sử dụng lớp GeekCoinBlock và in các thuộc tính của nó. Lưu ý rằng tham số previous_hash của khối genesis (khối đầu tiên đứng trước các khối khác) sẽ luôn là một chuỗi hoặc hàm băm tùy ý, trong trường hợp này là “khối đầu tiên”.

block1 = GeekCoinBlock('firstblock', [t1, t2])

print(f"Block 1 data: {block1.block_data}")
print(f"Block 1 hash: {block1.block_hash}")

Sau đó, chúng tôi làm tương tự với khối thứ hai, nhưng chuyển hàm băm khối đầu tiên làm đối số previous_hash.

block2 = GeekCoinBlock(block1.block_hash, [t3, t4])

print(f"Block 2 data: {block2.block_data}")
print(f"Block 2 hash: {block2.block_hash}")

Hãy chạy và phân tích đầu ra mà chúng ta nhận được từ đoạn mã này. Một lần nữa, gõ vào thiết bị đầu cuối của bạn:

❯ python main.py
Block 1 data: Noah sends 5 GC to Mark - Mark sends 2.3 GC to James - firstblock
Block 1 hash: 01e4e15242a9601725f4a86ca01fbddaaec7105b442955bb0efcadbfc759806d
Block 2 data: James sends 4.2 GC to Alisson - Alisson sends 1.1 GC to Noah - 01e4e15242a9601725f4a86ca01fbddaaec7105b442955bb0efcadbfc759806d
Block 2 hash: 448c4306caf7f6937b0307f92f27fbea3bb73b3470363dee5026a1209dadcfa8

Hiện tại, bạn chỉ thấy văn bản và một số băm 64 ký tự, nhưng điều này tiếp tục gần như cơ chế của một Chuỗi khối.

Bạn bắt đầu với một khối genesis, cơ sở của tất cả các khối khác.

Bất kỳ ai cũng có thể xác thực tính toàn vẹn của chuỗi và đó là lý do tại sao Chuỗi khối là một hệ thống an toàn như vậy. Ví dụ: nếu chúng tôi sửa đổi một chút nội dung của giao dịch, hãy nói:

t2 = "Mark sends 2.3 GC to James" -> t2 = "Mark sends 3.2 GC to James" 

Chúng tôi thấy một sự thay đổi đáng kể trong hàm băm của các khối.

Block 1 data: Noah sends 5 GC to Mark - Mark sends 3.2 GC to James - firstblock
Block 1 hash: 7a990bf1d70230bf2dad6160496c0b3046da7a17b1281fd1d4c63d4eac58e78c
Block 2 data: James sends 4.2 GC to Alisson - Alisson sends 1.1 GC to Noah - 7a990bf1d70230bf2dad6160496c0b3046da7a17b1281fd1d4c63d4eac58e78c
Block 2 hash: 569b977306ce88b53e001dca7ba00c03a51c60d6df4650e7657dcd136f2da0ac

Bạn có thể xem dự án hiện tại trên này Kho lưu trữ GitHub.

Mã hóa một chuỗi khối

Sẽ không thông minh nếu đặt tính toàn vẹn của hệ thống của chúng tôi dựa trên các biến được mã hóa thủ công, vì vậy chúng tôi cần một cách tiếp cận khác.

Chúng tôi có các khối. Đã đến lúc xây dựng một lớp kết hợp chúng thành một Chuỗi khối.

Hãy bắt đầu bằng cách xóa các giao dịch trước đó của chúng ta và chặn các đối tượng, sau đó sử dụng mã bên dưới.

# main.py

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

    def generate_genesis_block(self):
        self.chain.append(GeekCoinBlock("0", ['Genesis Block']))
    
    def create_block_from_transaction(self, transaction_list):
        previous_block_hash = self.last_block.block_hash
        self.chain.append(GeekCoinBlock(previous_block_hash, transaction_list))

    def display_chain(self):
        for i in range(len(self.chain)):
            print(f"Data {i + 1}: {self.chain[i].block_data}")
            print(f"Hash {i + 1}: {self.chain[i].block_hash}n")

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

Đây lại là một đoạn mã lớn. Hãy chia nhỏ từng phần:

  • self.chain — Danh sách ghi lại tất cả các khối. Chúng tôi có thể truy cập từng khối thông qua các chỉ mục danh sách.
  • generate_genesis_block — Nối khối gốc hoặc khối đầu tiên vào chuỗi. Hàm băm trước đó của khối là “0” và danh sách các giao dịch chỉ đơn giản là “Khối Genesis”.
  • create_block_from_transaction — Điều này cho phép chúng tôi thêm các khối vào chuỗi chỉ bằng một danh sách các giao dịch. Sẽ rất khó chịu khi tạo khối theo cách thủ công mỗi khi chúng tôi muốn ghi lại giao dịch
  • display_chain — In chuỗi khối bằng vòng lặp for
  • last_block — Một thuộc tính cho phép chúng ta truy cập phần tử cuối cùng của chuỗi. Chúng tôi đã sử dụng nó trên phương thức create_block_from_transaction.
  Cách lưu email Gmail dưới dạng tệp EML vào ổ cứng của bạn

Hãy chạy thử nghiệm Blockchain này.

# main.py

import hashlib

class GeekCoinBlock:
    ...


class Blockchain:
    ...

t1 = "George sends 3.1 GC to Joe"
t2 = "Joe sends 2.5 GC to Adam"
t3 = "Adam sends 1.2 GC to Bob"
t4 = "Bob sends 0.5 GC to Charlie"
t5 = "Charlie sends 0.2 GC to David"
t6 = "David sends 0.1 GC to Eric"

myblockchain = Blockchain()

myblockchain.create_block_from_transaction([t1, t2])
myblockchain.create_block_from_transaction([t3, t4])
myblockchain.create_block_from_transaction([t5, t6])

myblockchain.display_chain()

Bây giờ, hãy chạy tệp main.py.

Data 1: Genesis Block - 0
Hash 1: 39331a6a2ea1cf31a5014b2a7c9e8dfad82df0b0666e81ce04cf8173cc5aed3e

Data 2: George sends 3.1 GC to Joe - Joe sends 2.5 GC to Adam - 39331a6a2ea1cf31a5014b2a7c9e8dfad82df0b0666e81ce04cf8173cc5aed3e
Hash 2: 98cf363aecb33989aea0425a3c1287268bd86f63851bc08c0734a31db08506d5

Data 3: Adam sends 1.2 GC to Bob - Bob sends 0.5 GC to Charlie - 98cf363aecb33989aea0425a3c1287268bd86f63851bc08c0734a31db08506d5
Hash 3: 6f1cfcc3082488b97db8fdf8ed33f9ac7519be3e285a37a6fcc2f1904f373589

Data 4: Charlie sends 0.2 GC to David - David sends 0.1 GC to Eric - 6f1cfcc3082488b97db8fdf8ed33f9ac7519be3e285a37a6fcc2f1904f373589
Hash 4: 869df2f03c9860767d35b30a46233fbeea89a3000ae5019d1491e3829d1ab929

Xin chúc mừng! 🙌 Bạn vừa tạo một Chuỗi khối Python đơn giản từ đầu.

Giờ đây, bạn có thể tăng cường tính bất biến của Chuỗi khối bằng cách sử dụng getters và setters và triển khai các tính năng khác như bằng chứng công việc, khai thác hoặc bất kỳ khái niệm nào khác mà chúng tôi đã giải thích trong bài viết cơ bản về Khai thác Bitcoin.

Sự kết luận

Chuỗi khối là công nghệ đằng sau Bitcoin, Etherium và mọi loại tiền điện tử khác ngoài kia. Trong bài viết này, bạn đã học cách tạo Chuỗi khối bằng Python bằng cách sử dụng các thuật toán băm như sha256, lớp và đối tượng.

Thách thức của bạn là tạo ra một hệ thống khai thác và tại sao không, triển khai hệ thống đó bằng API REST bằng cách sử dụng các khung như Django hoặc Flask.

Nhiều người đang kiếm bộn tiền từ tiền điện tử. Chỉ cần tưởng tượng những gì bạn có thể làm nếu bạn tự tạo một cái. 🤑

Tiếp tục viết mã! 👨‍💻

x