آموزش ساخت بلاک چین (Blockchain) با پایتون — راهنمای کاربردی

۲۷۴۴ بازدید
آخرین به‌روزرسانی: ۱۷ تیر ۱۴۰۲
زمان مطالعه: ۱۳ دقیقه
آموزش ساخت بلاک چین (Blockchain) با پایتون — راهنمای کاربردی

افراد علاقمند به موضوع داغ و جذاب «رمز ارزها» (Cryptocurrencies) مخاطبان اصلی این مطلب خواهند بود. همچنین، به کلیه علاقمندان به یادگیری چگونگی عملکرد «بلاک چین» (Blockchain | زنجیره بلوکی) و فناوری پایه نهفته در پس آن، مطالعه این مطلب توصیه می‌شود. نکته قابل توجه آن است که بلاک چین در فارسی «زنجیره بلوکی» ترجمه شده و بنابراین در ادامه این مطلب سعی بر آن است که از این معادل نیز در کنار واژه شناخته شده بلاک چین استفاده شود. لازم به ذکر است که درک بلاک چین آسان نیست و برای یادگیری دقیق و عمیق آن نیاز به تخصیص وقت قابل توجه و مطالعه راهنماهای متنی و ویدئویی متعدد و مشاهده مثال‌های گوناگون است. در ادامه سعی بر آن است که مفهوم بلاک چین (زنجیره بلوکی) از طریق ساخت آن با کدهایی به زبان برنامه‌نویسی پایتون آموزش داده شود. به مخاطبان توصیه می‌شود برای درک بهتر مطلب و داشتن یک بلاک چین (زنجیره بلوکی) در پایان این مطلب، مراحل انجام شده را گام به گام همراه با این نوشتار انجام دهند. با مطلب آموزش ساخت بلاک چین مجله فرادرس همراه باشید.

پیش از آغاز

بلاک چین (زنجیره بلوکی) یک زنجیره پیوسته و تغییرناپذیر از رکوردهایی است که به آن‌ها «بلوک» (Block) گفته می‌شود. این بلوک‌ها می‌توانند در برگیرنده «تراکنش‌ها» (Transactions)، فایل‌ها یا هر نوع داده انتخابی دیگری باشند. اما مساله مهم آن است که این بلوک‌ها با استفاده از «هش‌ها» (hashes) به یکدیگر زنجیر شده‌اند. (مطالعه مطلب «تابع هش یا درهم سازی (Hash Function) چیست؟ -- به زبان ساده» برای آشنایی با مفهوم هش توصیه می‌شود.)

پرسشی که امکان دارد برای مخاطبان این مطلب مطرح شود آن است که برای مطالعه نوشتار پیش رو به چه پیش‌نیازهایی نیاز دارند؟ آشنایی مقدماتی با نوشتن و خواندن کدهای پایتون و داشتن درک مقدماتی از چگونگی عملکرد درخواست‌های HTTP مورد نیاز است، زیرا بلاک چین ساخته شده در این مطلب برمبنای HTTP است. کدهای ارائه شده در اینجا بر اساس پایتون ۳.۶ نوشته شده‌اند، بنابراین مخاطبان باید اقدام به نصب پایتون ۳.۶، و همچنین چارچوب Flask و کتابخانه Requests کنند. برای انجام این کار با بهره‌گیری از pip، می‌توان از دستور زیر استفاده کرد.

1 pip install Flask==0.12.2 requests==2.18.4

همچنین، نیاز به یک کلاینت HTTP مانند Postman یا cURL نیز هست. کد نهایی استفاده شده در این مطلب از اینجا (+) در دسترس است.

گام ۱: ساخت بلاک چین

در اولین مرحله از آموزش ساخت بلاک چین با پایتون ابتدا ویرایشگر متن را باز کرده (هر کس می‌تواند از ویرایشگر متن مورد علاقه خود استفاده کند، ولیکن نویسنده این مطلب از PyCharm استفاده کرده است) و یک فایل جدید با عنوان blockchain.py ساخته می‌شود. در ادامه همواره از همین یک فایل استفاده می‌شود.

ارائه بلاک چین

یک کلاس Blockchain ساخته می‌شود که «سازنده» (Creator) آن یک لیست اولیه خالی (برای ذخیره‌سازی بلاک چین)، و یک فایل دیگر نیز برای ذخیره‌سازی تراکنش‌ها ایجاد می‌کند. کد کلاس مذکور در ادامه آمده است.

1class Blockchain(object):
2    def __init__(self):
3        self.chain = []
4        self.current_transactions = []
5        
6    def new_block(self):
7        # Creates a new Block and adds it to the chain
8        pass
9    
10    def new_transaction(self):
11        # Adds a new transaction to the list of transactions
12        pass
13    
14    @staticmethod
15    def hash(block):
16        # Hashes a Block
17        pass
18
19    @property
20    def last_block(self):
21        # Returns the last Block in the chain
22        pass

کلاس Blockchain پاسخگوی مدیریت زنجیره است. این کلاس، تراکنش‌ها را ذخیره کرده و تعدادی متد یاری‌گر برای اضافه کردن بلوک‌های جدید به زنجیره دارد. در ادامه برخی از این متدها بررسی می‌شوند.

یک بلوک چگونه است؟

در بحث ساخت بلاک چین، هر بلوک دارای یک «اندیس» (index)، «برچسب زمان» (timestamp) (به زمان یونیکس)، یک لیست از تراکنش‌ها، یک proof و هش بلوک قبلی است.

در ادامه مثالی از چگونگی یک بلوک مجرد آمده است.

1block = {
2    'index': 1,
3    'timestamp': 1506057125.900785,
4    'transactions': [
5        {
6            'sender': "8527147fe1f5426f9dd545de4b27ee00",
7            'recipient': "a77f5cdfa2934df3954a5c7c7da5df1f",
8            'amount': 5,
9        }
10    ],
11    'proof': 324984774000,
12    'previous_hash': "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
13}

در اینجا، ایده و مفهوم زنجیره بلوکی شفاف شده است، و در آن هر بلوک در برگیرنده هش بلوک پیشین است. این مساله از این رو دارای اهمیت محسوب می‌شود که خصوصیت «غیر قابل تغییر بودن» را به زنجیره می‌دهد. اگر یک «حمله‌کننده» (Attacker) یک بلوک اولیه را در زنجیره بلوکی تخریب کند سایر بلوک‌های بعدی در زنجیره هش‌های اشتباهی را در بر می‌گیرند.

افزودن تراکنش به یک بلوک

همانطور که پیش‌تر بیان شد، هر بلوک دارای یک لیست از تراکنش‌ها است، بنابراین در این وهله نیاز به راهکاری برای افزودن تراکنش به بلوک وجود دارد.

متد ()new_transaction مسئول انجام این کار خواهد بود. کد این متد به شرح زیر است.

1class Blockchain(object):
2    ...
3    
4    def new_transaction(self, sender, recipient, amount):
5        """
6        Creates a new transaction to go into the next mined Block
7        :param sender: <str> Address of the Sender
8        :param recipient: <str> Address of the Recipient
9        :param amount: <int> Amount
10        :return: <int> The index of the Block that will hold this transaction
11        """
12
13        self.current_transactions.append({
14            'sender': sender,
15            'recipient': recipient,
16            'amount': amount,
17        })
18
19        return self.last_block['index'] + 1

پس از آنکه ()new_transaction یک تراکنش را به لیست اضافه می‌کند، اندیس بلوکی را که تراکنش به آن افزوده شده باز می‌گرداند. این کار بعدا برای کاربر جهت وارد کردن تراکنش‌ها مفید خواهد بود.

ساخت بلوک جدید

هنگامی که Blockchain نمونه‌سازی شد مرحله بعدی در ساخت بلاک چین نیاز به خوراک دادن به آن با یک «بلوک پیدایش» (genesis block) - یک بلوک بدون هیچ‌گونه اجدادی - است. همچنین نیاز به اضافه کردن یک «proof» به بلوک genesis است که در نتیجه کاوش (mining) (یا اثبات کارکرد | Proof of Work) به وقوع می‌پیوندد.

در این رابطه بعدا بیش‌تر صحبت خواهد شد. علاوه بر ساخت بلوک genesis در سازنده، متدهایی برای ()new_block() ،new_transaction و ()hash نیاز است.

1import hashlib
2import json
3from time import time
4
5
6class Blockchain(object):
7    def __init__(self):
8        self.current_transactions = []
9        self.chain = []
10
11        # Create the genesis block
12        self.new_block(previous_hash=1, proof=100)
13
14    def new_block(self, proof, previous_hash=None):
15        """
16        Create a new Block in the Blockchain
17        :param proof: <int> The proof given by the Proof of Work algorithm
18        :param previous_hash: (Optional) <str> Hash of previous Block
19        :return: <dict> New Block
20        """
21
22        block = {
23            'index': len(self.chain) + 1,
24            'timestamp': time(),
25            'transactions': self.current_transactions,
26            'proof': proof,
27            'previous_hash': previous_hash or self.hash(self.chain[-1]),
28        }
29
30        # Reset the current list of transactions
31        self.current_transactions = []
32
33        self.chain.append(block)
34        return block
35
36    def new_transaction(self, sender, recipient, amount):
37        """
38        Creates a new transaction to go into the next mined Block
39        :param sender: <str> Address of the Sender
40        :param recipient: <str> Address of the Recipient
41        :param amount: <int> Amount
42        :return: <int> The index of the Block that will hold this transaction
43        """
44        self.current_transactions.append({
45            'sender': sender,
46            'recipient': recipient,
47            'amount': amount,
48        })
49
50        return self.last_block['index'] + 1
51
52    @property
53    def last_block(self):
54        return self.chain[-1]
55
56    @staticmethod
57    def hash(block):
58        """
59        Creates a SHA-256 hash of a Block
60        :param block: <dict> Block
61        :return: <str>
62        """
63
64        # We must make sure that the Dictionary is Ordered, or we'll have inconsistent hashes
65        block_string = json.dumps(block, sort_keys=True).encode()
66        return hashlib.sha256(block_string).hexdigest()

به کد بالا «توضیحات» (comments) زیادی اضافه شده که پیرامون عملکرد هر قطعه از کد توضیحاتی ارائه می‌دهد و در عین حال docstring‌ها نیز به شفاف نگه داشتن کد کمک می‌کنند، بنابراین کدی واضح و بی‌نیاز از توضیحات محسوب می‌شود. چگونگی ساخت بلوک‌ها و کاوش آن‌ها تا این لحظه کاری بسیار شگفت‌انگیز بوده است.

درک الگوریتم Proof of Work

الگوریتم Proof of Work (به اختصار PoW | اثبات کارکرد) چگونگی ساخت یا کاوش بلوک‌های جدید در بلاک چین (زنجیره بلوکی) است. هدف از PoW کشف عددی محسوب می‌شود که مساله را حل می‌کند. پیدا کردن این عدد - از جهت محاسبات کامپیوتری -  توسط هر شخصی که در شبکه قرار دارد باید دشوار و تایید پاسخ آن باید آسان باشد.

این ایده اصلی نهفته در پس الگوریتم Proof of Work است. در ادامه نگاهی به مثالی ساده در این رابطه انداخته می‌شود. هش یک عدد صحیح x توسط یک y چندین برابر می‌شود و عدد حاصل باید به صفر ختم شود. بنابراین، hash(x * y) = ac23dc...0. در مثال ساده پیش رو، x = 5 در نظر گرفته می‌شود. پیاده‌سازی این مثال در پایتون به صورت زیر است.

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

راهکار در اینجا y = 21 است، زیرا هش تولید شده توسط آن با ۰ پایان پیدا می‌کند.

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

در رمزارز «بیت‌کوین» (Bitcoin)، الگوریتم Proof of Work با عنوان «Hashcash» نامیده می‌شود و خیلی از مثال پایه‌ای مطرح شده در بالا متفاوت نیست. این الگوریتمی است که ماینرها (miners) برای حل آن به منظور ساخت یک بلوک جدید با یکدیگر رقابت می‌کنند. به طور کلی، دشواری با تعداد کاراکترهایی که برای یک رشته جست‌و‌جو می‌شوند تعیین می‌شود. بنابراین، ماینرها برای راهکارهای خود با دریافت سکه - در یک تراکنش - پاداش دریافت می‌کنند و از سوی دیگر شبکه به سادگی قادر به تایید راهکار آن‌ها است.

پیاده‌سازی الگوریتم پایه Proof of Work

اکنون الگوریتم مشابهی برای بلاک چین ساخته شده در این مطلب پیاده‌سازی می‌شود.

قاعده مورد استفاده مطابق آنچه در بالا بیان شد است:

عدد P را پیدا کن که وقتی با بلاک پیشین هش می‌شود یک هش با چهار «0» مقدم تولید شود.

1import hashlib
2import json
3
4from time import time
5from uuid import uuid4
6
7
8class Blockchain(object):
9    ...
10        
11    def proof_of_work(self, last_proof):
12        """
13        Simple Proof of Work Algorithm:
14         - Find a number p' such that hash(pp') contains leading 4 zeroes, where p is the previous p'
15         - p is the previous proof, and p' is the new proof
16        :param last_proof: <int>
17        :return: <int>
18        """
19
20        proof = 0
21        while self.valid_proof(last_proof, proof) is False:
22            proof += 1
23
24        return proof
25
26    @staticmethod
27    def valid_proof(last_proof, proof):
28        """
29        Validates the Proof: Does hash(last_proof, proof) contain 4 leading zeroes?
30        :param last_proof: <int> Previous Proof
31        :param proof: <int> Current Proof
32        :return: <bool> True if correct, False if not.
33        """
34
35        guess = f'{last_proof}{proof}'.encode()
36        guess_hash = hashlib.sha256(guess).hexdigest()
37        return guess_hash[:4] == "0000"

برای تنظیم سختی الگوریتم، می‌توان تعداد صفرهای مقدم را تغییر داد. اما چهار صفر تعداد مناسبی است. با آزمودن تعداد صفرهای بیشتر به سادگی می‌توان متوجه شد که افزودن یک صفر مقدم بیشتر، تفاوت بسیار زیادی در زمان لازم برای پیدا کردن راهکار ایجاد می‌کند. در حال حاضر کلاس ساخته شده تقریبا کامل است و می‌توان با استفاده از درخواست‌های HTTP با آن ارتباط برقرار کرد.

گام ۲: زنجیره بلوکی به عنوان یک رابط کاربردی برنامه‌نویسی

اکنون از «چارچوب پایتون فلسک» (Python Flask Framework) استفاده خواهد شد. فلسک یک میکرو-چارچوب است و نگاشت «نقاط پایانی» (endpoints) به توابع پایتون را آسان‌تر می‌سازد.

این کار امکان مکالمه با بلاک چین ساخته شده را در وب از طریق درخواست‌های HTTP فراهم می‌کند. در ادامه سه متد ساخته خواهد شد:

  • transactions/new/: برای ساخت یک تراکنش جدید برای یک بلاک
  • mine/: برای آنکه به سرور گفته شود بلوک جدید را «ماین» (mine) کند.
  • chain/: برای بازگرداندن بلاک چین کامل.

راه‌اندازی Flask

«سرور» یک گره مجرد جدید را در شبکه بلاک چین شکل می‌دهد. اکنون نیاز به کدهایی است که در ادامه همراه با چگونگی عملکردشان آورده شده‌اند.

1import hashlib
2import json
3from textwrap import dedent
4from time import time
5from uuid import uuid4
6
7from flask import Flask
8
9
10class Blockchain(object):
11    ...
12
13
14# Instantiate our Node
15app = Flask(__name__)
16
17# Generate a globally unique address for this node
18node_identifier = str(uuid4()).replace('-', '')
19
20# Instantiate the Blockchain
21blockchain = Blockchain()
22
23
24@app.route('/mine', methods=['GET'])
25def mine():
26    return "We'll mine a new Block"
27  
28@app.route('/transactions/new', methods=['POST'])
29def new_transaction():
30    return "We'll add a new transaction"
31
32@app.route('/chain', methods=['GET'])
33def full_chain():
34    response = {
35        'chain': blockchain.chain,
36        'length': len(blockchain.chain),
37    }
38    return jsonify(response), 200
39
40if __name__ == '__main__':
41    app.run(host='0.0.0.0', port=5000)

یک توضیح کوتاه از کاری که کد بالا انجام می‌دهد:

  • خط ۱۵: نمونه‌گیری از گره
  • خط ۱۸: ساخت یک نام تصادفی برای گره
  • خط ۲۱: نمونه‌گیری از کلاس Blockchain
  • خط ۲۶-۲۳: ساخت نقطه پایانی mine/ که یک درخواست GET است.
  • خط ۳۰-۲۸: ساخت نقطه پایانی transactions/new/ که یک درخواست POST است زیرا داده‌ها به آن ارسال خواهند شد.
  • خط ۳۸-۳۲: ساخت یک نقطه پایانی chain/ که کل بلاک چین را باز می‌گرداند.
  • خط ۴۱-۴۰: سرور را روی پورت ۵۰۰۰ اجرا می‌کند.

نقطه پایانی تراکنش

خروجی زیر، شکلی است که تراکنش به نظر خواهد رسید و در واقع آنچه است که کاربر به سرور ارسال می‌کند.

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

از آنجا که در حال حاضر متد کلاس برای افزودن تراکنش به بلوک وجود دارد، ادامه کار آسان خواهد بود. کد زیر، تابع لازم برای افزودن تراکنش‌ها است:

1import hashlib
2import json
3from textwrap import dedent
4from time import time
5from uuid import uuid4
6
7from flask import Flask, jsonify, request
8
9...
10
11@app.route('/transactions/new', methods=['POST'])
12def new_transaction():
13    values = request.get_json()
14
15    # Check that the required fields are in the POST'ed data
16    required = ['sender', 'recipient', 'amount']
17    if not all(k in values for k in required):
18        return 'Missing values', 400
19
20    # Create a new Transaction
21    index = blockchain.new_transaction(values['sender'], values['recipient'], values['amount'])
22
23    response = {'message': f'Transaction will be added to Block {index}'}
24    return jsonify(response), 201

نقطه پایانی ماینینگ

نقطه پایانی ساخت بلاک چین ماینینگ است که شگفتی واقعی در آن به وقوع می‌پیوندد.

در این نقطه تنها کافی است سه کار اتفاق بیافتد:

  1. محاسبه Proof of Work
  2. پاداش دادن به ماینر با افزودن تراکنشی که ۱ سکه به کاربر می‌دهد.
  3. Forge کردن بلوک جدید با افزودن آن به زنجیره
1import hashlib
2import json
3
4from time import time
5from uuid import uuid4
6
7from flask import Flask, jsonify, request
8
9...
10
11@app.route('/mine', methods=['GET'])
12def mine():
13    # We run the proof of work algorithm to get the next proof...
14    last_block = blockchain.last_block
15    last_proof = last_block['proof']
16    proof = blockchain.proof_of_work(last_proof)
17
18    # We must receive a reward for finding the proof.
19    # The sender is "0" to signify that this node has mined a new coin.
20    blockchain.new_transaction(
21        sender="0",
22        recipient=node_identifier,
23        amount=1,
24    )
25
26    # Forge the new Block by adding it to the chain
27    previous_hash = blockchain.hash(last_block)
28    block = blockchain.new_block(proof, previous_hash)
29
30    response = {
31        'message': "New Block Forged",
32        'index': block['index'],
33        'transactions': block['transactions'],
34        'proof': block['proof'],
35        'previous_hash': block['previous_hash'],
36    }
37    return jsonify(response), 200

شایان توجه است که گیرنده بلوک ماین شده آدرس گره است. آنچه در اینجا انجام می‌شود تعامل با متدها در کلاس بلاک چین است. در این نقطه، کار تمام شده و می‌توان با بلاک چین جدید تعامل کرد.

گام ۳: تعامل با بلاک چین

می‌توان از cURL یا Postman برای تعامل کردن با API جدید در شبکه استفاده کرد.

راه‌اندازی سرور:

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

اکنون برای ماین کردن یک بلوک با استفاده از درخواست GET تلاش می‌شود:

1http://localhost:5000/mine
تعامل با بلاک چین
استفاده از Postman برای ایجاد دستور GET

با استفاده از یک درخواست POST به http://localhost:5000/transactions/new با بدنه دربرگیرنده ساختار تراکنش ارائه شده در این مطلب، یک تراکنش جدید ساخته می‌شود.

استفاده از Postman برای ایجاد درخواست POST

افرادی که از Postman استفاده نمی‌کنند می‌توانند درخواست مشابهی را با استفاده از cURL انجام دهند:

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

سرور ریست شد و دو بلوک را ماین کرد تا ۳ تا در کل بدهد. اکنون کل زنجیره بلوک با درخواست http://localhost:5000/chain بازرسی (inspect) می‌شود:

{
"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
}

گام ۴: اجماع

این گام بسیار جالب توجه محسوب می‌شود. اکنون یک بلاک چین پایه موجود است که تراکنش‌ها را می‌پذیرد و امکان ماین کردن بلوک‌های جدید را به کاربران می‌دهد. اما نکته اصلی بلاک چین‌ها آن است که باید غیر متمرکز باشند. اگر بلاک چین (زنجیره بلوکی) غیر متمرکز است، چطور می‌توان اطمینان حاصل کرد که همه آن‌ها یک زنجیره یکسان را منعکس می‌کنند؟ به این موضوع «مساله اجماع» (Consensus Problem) گفته می‌شود و در صورت تمایل به داشتن بیش از یک گره در شبکه باید یک الگوریتم Consensus پیاده‌سازی شود.

ثبت گره‌های جدید

پیش از آنکه بتوان یک الگوریتم Consensus را پیاده‌سازی کرد نیاز به راهی برای آن است که یک گره درباره گره‌های همسایگی خودش در شبکه مطلع شود. هر گره در شبکه باید ثبتی از دیگر شبکه‌ها در شبکه داشته باشد. بنابراین نیاز به نقاط پایانی بیشتری است.

  1. nodes/register/ برای پذیرش لیستی از گره‌های جدید به شکل URL‌ها
  2. nodes/resolve/ برای پیاده‌سازی الگوریتم Consensus، که هرگونه ناسازگاری را رفع می‌کند (برای اطمینان از اینکه یک گره دارای زنجیره صحیحی است).

نیاز به تغییر سازنده بلاک چین و فراهم کردن روشی برای ثبت گره‌ها است:

1...
2from urllib.parse import urlparse
3...
4
5
6class Blockchain(object):
7    def __init__(self):
8        ...
9        self.nodes = set()
10        ...
11
12    def register_node(self, address):
13        """
14        Add a new node to the list of nodes
15        :param address: <str> Address of node. Eg. 'http://192.168.0.5:5000'
16        :return: None
17        """
18
19        parsed_url = urlparse(address)
20        self.nodes.add(parsed_url.netloc)

روشی برای افزودن گره‌های همسایگی به شبکه

شایان توجه است که از ()set برای نگه داشتن لیست گره‌ها استفاده شده است. این یک راهکار ارزان برای حصول اطمینان از این امر است که افزودن گره‌های جدید خنثی تکراری است، بدین معنا که اهمیتی ندارد چند بار یک گره مشخص اضافه می‌شود، زیرا دقیقا یکبار ظاهر خواهد شد.

پیاده‌سازی الگوریتم Consensus

همانطور که اشاره شد، یک ناسازگاری هنگامی که یک گره دارای زنجیره متفاوتی از دیگر گره‌ها است به وقوع می‌پیوندد. برای حل این مساله، قاعده‌ای ساخته خواهد شد که بر اساس آن طولانی‌ترین زنجیره صحیح، معتبر است. به عبارت دیگر، طولانی‌ترین زنجیره در شبکه بالفعل است.

با استفاده از این الگوریتم، به اجماع در میان گره‌های شبکه دست یافته می‌شود.

1...
2import requests
3
4
5class Blockchain(object)
6    ...
7    
8    def valid_chain(self, chain):
9        """
10        Determine if a given blockchain is valid
11        :param chain: <list> A blockchain
12        :return: <bool> True if valid, False if not
13        """
14
15        last_block = chain[0]
16        current_index = 1
17
18        while current_index < len(chain):
19            block = chain[current_index]
20            print(f'{last_block}')
21            print(f'{block}')
22            print("\n-----------\n")
23            # Check that the hash of the block is correct
24            if block['previous_hash'] != self.hash(last_block):
25                return False
26
27            # Check that the Proof of Work is correct
28            if not self.valid_proof(last_block['proof'], block['proof']):
29                return False
30
31            last_block = block
32            current_index += 1
33
34        return True
35
36    def resolve_conflicts(self):
37        """
38        This is our Consensus Algorithm, it resolves conflicts
39        by replacing our chain with the longest one in the network.
40        :return: <bool> True if our chain was replaced, False if not
41        """
42
43        neighbours = self.nodes
44        new_chain = None
45
46        # We're only looking for chains longer than ours
47        max_length = len(self.chain)
48
49        # Grab and verify the chains from all the nodes in our network
50        for node in neighbours:
51            response = requests.get(f'http://{node}/chain')
52
53            if response.status_code == 200:
54                length = response.json()['length']
55                chain = response.json()['chain']
56
57                # Check if the length is longer and the chain is valid
58                if length > max_length and self.valid_chain(chain):
59                    max_length = length
60                    new_chain = chain
61
62        # Replace our chain if we discovered a new, valid chain longer than ours
63        if new_chain:
64            self.chain = new_chain
65            return True
66
67        return False

اولین متد ()valid_chain، با حلقه زدن در هر بلوک و اعتبارسنجی هش و Proof مسئول بررسی این است که آیا یک زنجیره معتبر است یا خیر. ()resolve_conflicts متدی است که در میان همه گره‌های همسایگی حلقه می‌زند، زنجیرهای آن را دانلود می‌کند و آن‌ها را با استفاده از روش بالا تایید می‌کند.

اگر یک زنجیره معتبر پیدا شد که طول آن بیشتر از زنجیره ساخته شده است، با زنجیره موجود جایگزین می‌شود. اکنون، دو نقطه پایانی رابط کاربردی برنامه‌نویسی (Application Programming Interface | API) ثبت می‌شوند، یکی برای افزودن گره‌های همسایگی و دیگری برای حل ناسازگاری.

1@app.route('/nodes/register', methods=['POST'])
2def register_nodes():
3    values = request.get_json()
4
5    nodes = values.get('nodes')
6    if nodes is None:
7        return "Error: Please supply a valid list of nodes", 400
8
9    for node in nodes:
10        blockchain.register_node(node)
11
12    response = {
13        'message': 'New nodes have been added',
14        'total_nodes': list(blockchain.nodes),
15    }
16    return jsonify(response), 201
17
18
19@app.route('/nodes/resolve', methods=['GET'])
20def consensus():
21    replaced = blockchain.resolve_conflicts()
22
23    if replaced:
24        response = {
25            'message': 'Our chain was replaced',
26            'new_chain': blockchain.chain
27        }
28    else:
29        response = {
30            'message': 'Our chain is authoritative',
31            'chain': blockchain.chain
32        }
33
34    return jsonify(response), 200

در این نقطه می‌توان در صورت تمایل یک ماشین متفاوت را دریافت کرد و گره‌های مختلفی را به شبکه افزود و یا فرآیندها را با استفاده از پورت‌های گوناگون در ماشینی یکسان چرخاند. اکنون گره دیگری در ماشین موجود در پورت دیگری افزوده می‌شود و با گره کنونی ثبت می‌شود. بنابراین اکنون دو گره http://localhost:5000 و http://localhost:5001 وجود دارد.

ثبت یک گره جدید

سپس، برخی از بلوک‌های جدید در گره ۲ ماین شده‌اند تا اطمینان حاصل شود که زنجیره طولانی‌تر است. پس از آن، GET /nodes/resolve در گره ۱ فراخوانی می‌شود که زنجیره با الگوریتم Consensus جایگزین شده است.

الگوریتم Consensus

اگر مطلب بالا برای شما مفید بوده، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

^^

بر اساس رای ۴۲ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
Hackernoon
۲۱ دیدگاه برای «آموزش ساخت بلاک چین (Blockchain) با پایتون — راهنمای کاربردی»

سلام، ممنون از آموزش خوبتون
یه سوال دارم… ترنزکشن های جدید به نود های مختلف ارسال میشه. پس اون نودی که موفق میشه proof را به دست بیاره چطوری همه ترنزکشن ها را در بلاکچین خودش اضافه می‌کنه؟

سلام .با تشکر از اموزش خوبتون.
ایا میشه شبکه بلاکچینی خودمون بنویسیم و برای زیر ساخت یه کارخونه معمولی ازش استفاده کرد؟؟ برای ماین کردن همچین بلاکچینی چ سیستم یا انرژی ای نیاز هست؟؟
لطفا راهنماییم کنید

سلام وقت بخیر
سوالی از خدمتتون داشتم.آیا این کدها و کل متد بکار رفته در مجموعه این دستورات، دقیقا به همین شکل توی نرم افزارهای ماینر که با پایتون نوشته شده هست؟
و اینکه اگه این مجموعه رو بصورت یک فایل اجرایی در بیاریم، میتونه مثل یک نرم افزار ماینینگ عمل کنه و اگر نه به چه مواردی نیاز داره؟
با تشکر

سلام.متشکرم از شما.من متوجه یم خطا در متد
new_transaction
شدم.لطفا خط آخر متد رو به صورت زیر تغییر بدید تا مشکل حل شود.
return self.last_block()[‘index’] + 1

صمیمانه از همراهی شما با مجله فرادرس و ارائه بازخورد سپاس‌گزاریم.

کد مربوطه به همان شکلی که نوشته شده، صحیح است و نباید از پرانتز استفاده شود. زیرا پیش از متُد last_block، از آرایه‌‏گر خصوصیت یا همان Decorator Property استفاده شده است. بنابراین last_block درست مثل یک متغیر عمل می‌کند و نمی‌توان آن را مانند یک تابع فراخوانی کرد.

برای شما آرزوی سلامتی و موفقیت داریم.‌

چجوری پایتون و pip رو نصب کنیم

سلام، وقت شما بخیر؛

از همراهی شما با مجله فرادرس بسیار سپاسگزاریم. برای یادگیری نصب پایتون روی سیستم عامل‌ها و پلتفرم‌های گوناگون می‌توانید از این مطلب مجله فرادرس با عنوان «آموزش نصب پایتون» استفاده کنید.

سلام و وقت بخیر.
شما برنامه نویسی در حوضه ی بلاکچین هم آموزش می دهید؟

سلام خسته نباشید ، پیشنهاد شما برای یک فرد ۲۳ ساله که میخواد یه مهارت برنامه نویسی داشته باشه و کسب درآمد بکنه و حتی بعداً به عنوان رزومه ازش استفاده کنه چیه؟و چه مراحلی رو باید طی کنه؟

با عرض سلام و وقت به خیر خدمت جنابعالی؛

اتفاقاً به تازگی مقاله‌ای دقیقاً با همین موضوع در مجله فرادرس منتشر شده است که در آن به طور جامع به نحوه کسب درآمد از برنامه‌نویسی پرداخته شده و شما می‌توانید با مطالعه آن کاملاً به پاسخ سوال خود برسید:
«چگونه از برنامه‌نویسی پول در بیاوریم‌؟ — کاربردی و اصولی‌ترین روش‌ها»
علاوه بر این، مطالعه مقاله دیگری هم برای شناخت مسیر یادگیری پایتون پیشنهاد می‌شود. چرا که پایتون یکی از محبوب‌ترین و پر استفاده‌ترین زبان‌های برنامه‌نویسی به حساب می‌آید. این زبان همه‌منظوره است و با یادگیری آن می‌توانید در حوزه‌های مختلف (مورد علاقه خود) به عنوان برنامه‌نویس پایتون مشغول به کار شوید:
«بهترین مسیر یادگیری پایتون چیست؟ — راهنمای شروع آموزش»

با تشکر از شما و با آرزوی موفقیت و سلامتی.

سلام خسته نباشید
من با یک یاهو دوتا بلاک چین دارم این مشکلی ایجاد نمیکنه؟؟؟

لطفا جواب بدید

با سلام
چطور میشه بلاک چین رو به تعداد انبوه و صنعتی تولید کرد

لطفا جواب بدید

سلام
میخواستم بدونم چطور میشه بلاک چین رو به طور انبوه تولید کرد

سلام
مطالب خوبی دارید .

سلام آیا ممکنه از بلاک چین رمز ارزهای دیگر مانند بیت کوین و غیره و یا هر بلاک چین دیگر ، جهت رمز ارز جدید استفاده کنیم؟ و اگر چنین چیزی ممکنه میشه توضیح بدید.

با سلام؛

از همراهی شما با مجله فرادرس سپاس‌گزاریم. بله، انشعاب (Fork) کردن بیت کوین برای ساخت رمزارزهای جدید کاری متداول است. بسیاری از آلت‌کوین‌ها بدین شکل تولید شده‌اند.

پیروز، شاد و تندرست باشید.

سلام.لطفن فیلم آموزشی این مقاله رو فراهم کنید….ممنون میشم

سلام خسته نباشید ، پیشنهاد شما برای یک فرد ۲۳ ساله که میخواد یه مهارت برنامه نویسی داشته باشه و کسب درآمد بکنه و حتی بعداً به عنوان رزومه ازش استفاده کنه چیه؟و چه مراحلی رو باید طی کنه؟

من دلم میخواد فیلم از این موضوع بسازم اما به هر کدوم از این سایتها پیام میدم جوابی نمیدن.
محمد صادق هستم.

نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *