اخبار و مقالاتمقالهپیشنهاد سردبیر

آموزش ساخت یک بلاکچین

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

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

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

مهارت‌های مورد نیاز: دانش خواندن و نوشتن اولیه‌ی کد‌های زبان پایتون(Python) و درک چگونگی عملکرد درخواست‌های HTTP برای ساختن شبکه‌ی بلاکچین بر اساس مطالب عنوان شده در این مقاله ضروری است.

نرم‌افزار‌های مورد نیاز: پایتون نسخه‌های بالاتر از ۳٫۶ (به همراه PIP)، نصب فلسک(Flask) به همراه کتابخانه‌ی توابع و نصب کلاینت HTTP همانند Postman و cURL.

pip install Flask==0.12.2 requests==2.18.4 

کد اصلی مطالب ارائه شده در این مقاله که برای ساخت بلاکچین استفاده شده است را می‎توانید از این آدرس به‌طور کامل دریافت کنید.

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

به کمک ویرایشگر متن یا IDE همانند PyCharm فایل جدیدی را ایجاد کنید(ما این فایل را blockchain.py نام‌گذاری کردیم). باید توجه داشته باشید که در این مقاله تنها از یک فایل استفاده می‌کنیم اما در صورتی‌که در پیگیری مراحل کُدنویسی دچار مشکل شدید، همواره می‌توانید به کُد اصلی(Source Code) مراجعه کنید.

معرفی بلاکچین

در ابتدا دو کلاس(Class) بلاکچین شامل لیست خالی اولیه(برای ذخیره‌سازی بلاکچین) و دیگری برای ذخیره‌سازی تراکنش‌ها ایجاد می‌کنیم. کد ایجاد کلاس بلاکچین را می‌توانید در این قسمت مشاهده کنید:

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

    @property
    def last_block(self):
        # Returns the last Block in the chain
        pass

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

منظور از بلاک چیست؟

هر بلاک دارای شاخص(Index)، جدول زمانی(در فُرم زمان Unix یا سیستمی برای توصیف نقطه‌ی زمانی)، لیست تراکنش‌ها(List Of Transactions)، اثبات(Proof) و هش بلاک قبلی است. نمونه‌ای از یک بلاک در کد زیر قابل مشاهده است.

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

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

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

باید با استفاده از روشی تراکنش‌ها را به بلاک اضافه کنیم. تابع 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() تراکنش را به لیست تراکنش‌ها اضافه می‌کند، شاخص بلاکی که تراکنش به آن اضافه خواهد شد را بر می‌گرداند(بلاک بعدی که استخراج خواهد شد). این فرآیند برای کاربری که تراکنش را ارسال کرده است مفید خواهد بود.

ایجاد بلاک‌های جدید

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

علاوه بر افزودن جنسیس بلاک در ساختار بلاکچین، توابع بیشتری را برای ایجاد بلاک‌های جدید 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()

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

آشنایی با الگوریتم اثبات کار

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

برای درک بهتر این مطلب، مثال بسیار ساده‌ای را مطرح می‌کنیم.

مساله‌ای را به این صورت مطرح می‌کنیم: هش عدد صحیح X که در Y ضرب می‌شود باید به صفر ختم شود. بنابراین می‌توان مساله را به این شکل نوشت:

hash(x * y) = ac23dc…0

برای ساده‌سازی مساله‌ مقدار x را یک عدد ثابت قرار می‌دهیم(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

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

پیاده‌سازی الگوریتم اثبات کار

در این قسمت الگوریتم مشابهی را برای شبکه‌ی بلاکچینی که ایجاد کردیم، پیاده‌سازی می‌کنیم. قوانین با مثالی که در قسمت قبلی ارائه شد، مشابهت دارد:

هدف مسئله یافتن عددی همانند P است که حاصل هش آن با پاسخ بلاک قبلی به چهار صفر ختم شود.
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 آماده‌ی آغاز تعامل با بلاکچین هستیم.

گام دوم: بلاکچین به عنوان رابط برنامه‌نویسی نرم‌افزار کاربردی(API)

در این بخش از فریم‌ورک فلسک(Flask) زبان برنامه‌نویسی پایتون استفاده می‌کنیم. فلسک چهارچوب کوچکی است که ترسیم نقاط پایانی توابع پایتون را ساده‌تر می‌کند. این ابزار امکان تعامل با بلاکچین را با استفاده از درخواست‌های HTTP امکان‌پذیر می‌سازد.

  • برای ایجاد تراکنش جدید در بلاک(/transactions/new)
  • اطلاع‌رسانی استخراج بلاک جدید به سرور(/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)

در این قسمت توضیح مختصری از کدهای نوشته شده را ارائه می‌کنیم:

  • خط ۱۵: گره را معرفی می‌کند.
  • خط ۱۸: یک نام تصادفی برای گره ایجاد می‌کند.
  • خط ۲۱: معرفی کلاس بلاکچین.
  • خط ۲۴-۲۶: بخشی از کانال ارتباطی(Endpoint) (/mine) را ایجاد می‌کند که به صورت « دریافت درخواست» است.
  • خط ۲۸-۳۰: بخشی از کانال ارتباطی (/transactions/new) را ایجاد می‌کند که به صورت «ارسال درخواست» است.
  • خط ۳۲-۳۸: بخشی از کانال ارتباطی (/chain) را اجرا می‌کند که بلاکچین کامل را حاصل می‌کند.
  • خط ۴۰-۴۱: سرور را بر روی پورت ۵۰۰۰ اجرا می‌کند.

کانال ارتباطی(Endpoint) تراکنش‌ها

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

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

کانال ارتباطی ماینینگ

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

  • محاسبات الگوریتم اثبات کار(آخرین بلاک و آخرین پاسخ مسئله)
  • پاداش‌دهی به ماینر‌ها(با افزودن تراکنشی که به ماینر‌ها سکه پاداش می‌دهد)
  • ساختن بلاک جدید(افزودن بلاک جدید به زنجیره‌ی بلاکچین)
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» استفاده کنیم.

$ 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 زنجیره‌ را به‌طور کامل بررسی می‌کنیم.

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

گام چهارم: اجماع

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

ثبت گره‌های جدید در شبکه‌ی بلاکچین

پیش از پیاده‌سازی الگوریتم اجماع باید به کمک روشی یک گره را از وجود گره‌های دیگر در همسایگی آن در شبکه‌ی بلاکچین مطلع کنیم. هر گره در شبکه باید ریجستری(مشخصات) گره‌های دیگر در شبکه را ذخیره کند. در نتیجه ایجاد کانال‌های ارتباطی بیشتر اجتناب ناپذیر است:

  • برای پذیرش فهرست گره‌های جدید به فُرم مجموعه‌ای از آدرس‌ها(/nodes/register)
  • پیاده‌سازی الگوریتم اجماع به منظور برطرف کردن تضاد‌ها و کسب اطمینان از درستی زنجیره‌ی(/nodes/resolve)

در این مرحله باید ساختار بلاکچینی که در بخش‌های قبلی ایجاد کردیم را اصلاح کنیم و روشی برای ثبت گره‌ها ارائه کنیم:

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

...
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() استفاده می‌کنیم که یک روش ساده برای کسب اطمینان از فهرست شدن گره‌های مختلف در شبکه است. این جمله به معنای این است که تعداد دفعات افزودن یک گره‌ی خاص اهمیت ندارد و این گره تنها یکبار در فهرست گره‌های شبکه ظاهر می‌شود.

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

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

...
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() وظیفه‌ی بررسی زنجیره‌های هر بلاک و تایید هش و اثبات را بر عهده دارد.
  • تابع resolve_conflicts() روشی است که در آن گره‌ها زنجیره‌ی تمامی گره‌های موجود در همسایگی خود را دریافت و سپس با استفاده از روشی که پیش‌تر به آن اشاره شده است، آن‌ها را تایید می‌کنند. درصورتی که زنجیره‌ی معتبری یافت شود که طول بیشتری نسبت به زنجیره‌ی ما داشته باشد، زنجیره‌ی ما توسط آن زنجیره جایگزین خواهد شد.

در این مرحله دو کانال ارتباطی که به منظور افزودن گره‌های همسایه و برطرف کردن تضاد ایجاد کردیم را در رابط کاربری(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

کد نویسی بلاکچین
(ثبت گره‌ی جدید)

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

کد نویسی بلاکچین
(نتیجه‌ی عملکرد الگوریتم اجماع)

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

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

[تعداد: 0   میانگین: 0/5]
برچسب ها

‫۴ نظرها

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

    1. سلام دوست گرامی
      بله شما میتونید پروژه‌های منبع باز(مثل بیت کوین) را در مخزن کد‌های Gitab مشاهده کنید و از اون‌ها برای ایجاد یک رمزارز جدید استفاده کنید. مثلا بخش بزرگی از پروژه‌ی لایت کوین از کد‌های بیت کوین استفاده شده و یا خیلی از پروژه‌های دیگه از روی هم کپی میشن اما این نوع از پروژه‌ها چون نوآوری خاصی ندارن غالبا مورد توجه قرار نمیگیرن.

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

دیدگاهتان را بنویسید

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

نوشته های مشابه

دکمه بازگشت به بالا
بستن
بستن