برنامه نویسی، کامپیوتر ۱۷۱۸۹ بازدید

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

پیش از آغاز

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

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

 pip install Flask==0.12.2 requests==2.18.4

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

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

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

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

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

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

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

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

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

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

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

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

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

class Blockchain(object):
    ...
    
    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> 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

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

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

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

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):
        """
        Create a new Block in the Blockchain
        :param proof: <int> The proof given by the Proof of Work algorithm
        :param previous_hash: (Optional) <str> Hash of previous Block
        :return: <dict> 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):
        """
        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> 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):
        """
        Creates a SHA-256 hash of a Block
        :param block: <dict> Block
        :return: <str>
        """

        # 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()

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

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

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

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

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}')

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

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

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

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

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

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

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 Algorithm:
         - Find a number p' such that hash(pp') contains leading 4 zeroes, where p is the previous p'
         - p is the previous proof, and p' is the new proof
        :param last_proof: <int>
        :return: <int>
        """

        proof = 0
        while self.valid_proof(last_proof, proof) is False:
            proof += 1

        return proof

    @staticmethod
    def valid_proof(last_proof, proof):
        """
        Validates the Proof: Does hash(last_proof, proof) contain 4 leading zeroes?
        :param last_proof: <int> Previous Proof
        :param proof: <int> Current Proof
        :return: <bool> True if correct, False if not.
        """

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

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

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

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

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

راه‌اندازی Flask

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

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)

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

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

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

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

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

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

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

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

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

  1. محاسبه Proof of Work
  2. پاداش دادن به ماینر با افزودن تراکنشی که ۱ سکه به کاربر می‌دهد.
  3. Forge کردن بلوک جدید با افزودن آن به زنجیره
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)

    # 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
    previous_hash = blockchain.hash(last_block)
    block = blockchain.new_block(proof, previous_hash)

    response = {
        'message': "New Block Forged",
        'index': block['index'],
        'transactions': block['transactions'],
        'proof': block['proof'],
        'previous_hash': block['previous_hash'],
    }
    return jsonify(response), 200

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

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

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

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

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

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

http://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، که هرگونه ناسازگاری را رفع می‌کند (برای اطمینان از اینکه یک گره دارای زنجیره صحیحی است).

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

...
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: <str> Address of node. Eg. 'http://192.168.0.5:5000'
        :return: None
        """

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

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

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

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

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

...
import requests


class Blockchain(object)
    ...
    
    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 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):
        """
        This is our Consensus Algorithm, it resolves conflicts
        by replacing our chain with the longest one in the network.
        :return: <bool> True if our chain was replaced, False if not
        """

        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'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 we discovered a new, valid chain longer than ours
        if new_chain:
            self.chain = new_chain
            return True

        return False

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

@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

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

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

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

الگوریتم Consensus

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

^^

بر اساس رای ۳۶ نفر
آیا این مطلب برای شما مفید بود؟
شما قبلا رای داده‌اید!
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.

«الهام حصارکی»، فارغ‌التحصیل مقطع کارشناسی ارشد مهندسی فناوری اطلاعات، گرایش سیستم‌های اطلاعات مدیریت است. او در زمینه هوش مصنوعی و داده‌کاوی، به ویژه تحلیل شبکه‌های اجتماعی، فعالیت می‌کند.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    1. با سلام؛

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

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

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

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

نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد.