نحوه ایجاد یک بلاک چین ساده با استفاده از جاوا اسکریپت

[بلاک چین] بزرگترین فرصتی است که می توانیم در دهه آینده به آن فکر کنیم.

~ باب گریفلد

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

بلاک چین فناوری است که تمام داده‌های دیجیتال یا دارایی‌های مبادله شده در شبکه را ردیابی می‌کند و به این رکورد «دفتر کل» می‌گویند. هر داده رد و بدل شده "تراکنش" است و چندین تراکنش تایید شده به عنوان یک بلوک در دفتر کل اضافه می شود. بلوک‌ها را به‌عنوان جعبه‌ای در نظر بگیرید که حاوی داده‌هایی است و چندین مورد از این بلوک‌ها در کنار هم قرار می‌گیرند تا یک بلاک چین را تشکیل دهند. در همین قیاس، بلاک چین را می توان به عنوان فضایی تصور کرد که چندین جعبه را در خود جای می دهد.

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

چرا بلاکچین؟

بلاک چین در سال 2008 به عنوان راهی برای ذخیره و ایمن سازی ارز دیجیتال آغاز شد. این بخشی از پیشنهادی بود که توسط ساتوشی ناکاموتو برای بیت کوین ارائه شد. و بیت کوین اولین کاربرد شبکه بلاک چین بود. یکی از مزایای اصلی آن این است که اطلاعات ثبت شده را نمی توان بدون توافق بین همه طرف ها یا گره های درگیر تغییر داد.

[مترجم: سال 2008 اولین بار بود که بلاکچین برای ذخیره سازی غیر متمرکز اطلاعات مالی استفاده شد ، قبل از آن بلامچین برای ذخیره سازی ازلاعات استفاده میشده است]

مزایای دیگر عبارتند از:

غیرمتمرکز: تراکنش ها در شبکه ای از رایانه ها انجام می شود.
تغییرناپذیری: اگر تراکنش ایجاد شود، نمی توان آن را تغییر داد
باز: همه تراکنش ها برای همه گره ها قابل مشاهده است.
امنیت: با توجه به ویژگی رمزگذاری، بلاک چین تقریبا همیشه امن است

اکنون، ما در مورد ویژگی های آن می دانیم، بیایید ساخت بلاک چین خود را از ابتدا با استفاده از NodeJS شروع کنیم.

پیش نیازها:

برای دنبال کردن و درک این آموزش باید با موارد زیر آشنا باشید:

  • دانش کار کلاس ها و سایر ویژگی های ES6 در جاوا اسکریپت.
  • NodeJS روی دستگاه نصب شده باشد.

شروع کار با بلوک:

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

  • داده هایی برای ثبت در بلاک چین، به عنوان مثال، داده های تراکنش.
  • هش بلاک - که شناسه بلوک تولید شده با استفاده از تکنیک های رمزنگاری است.
  • هش بلوک قبلی در زنجیره. در هر بلوک ثبت می شود تا آن را به زنجیره پیوند دهد و امنیت آن را بهبود بخشد.
  • یک فیلدبری ذخیره تاریخ از زمان ایجاد و اضافه شدن بلوک به بلاک چین.
  • اثبات کار (PoW)، که مقدار تلاشی است که برای استخراج هش بلوک فعلی انجام می شود (ما از این اجماع استفاده خواهیم کرد زیرا اثبات سهام فراتر از این مقاله است).

تعریف کلاس Block با ویژگی های بالا:

class Block {
  constructor(data, previousHash) {
    this.data = data;
    this.hash = "";
    this.previousHash = previousHash;
    this.timestamp = new Date();
    this.pow = 0;
  }
}

محاسبه هش بلوک:

هش بلوک، شناسه ای است که با استفاده از تکنیک رمزنگاری تولید می شود. ما هش بلوک را با هش کردن هش بلوک قبلی، داده های بلوک فعلی، مهر زمانی و PoW با استفاده از الگوریتم SHA256 دریافت می کنیم. ما از رمزنگاری، یک کتابخانه داخلی NodeJS برای هش کردن داده ها استفاده خواهیم کرد.

const calculateHash = (block) => {
  const data = JSON.stringify(block.data);
  const blockData =
    data +
    block.previousHash +
    block.timestamp.toISOString() +
    block.pow.toString();
  return createHash("sha256").update(blockData).digest("hex");
};

در کد بالا موارد زیر را انجام دادیم:

  • داده‌های بلوک را به فرمت JSON تبدیل کردیم تا بتوانیم آن را با اطلاعات دیگر به عنوان یک رشته پیوند دهیم.
  • هش قبلی بلوک، داده، مُهر زمان و اثبات کار (PoW) را به هم متصل کردیم.
  • ایجاد هش برای الحاق قبلی با الگوریتم SHA256.
  • نتیجه هش را در مبنای 16 با حروف کوچک برای A-F برگرداند.

استخراج بلوک های جدید:

استخراج بلوک های جدید شامل تولید هش بلوک با تعداد معینی از صفرها در شروع هش (0s) است. تعداد صفرهای ابتدایی توسط سختی شبکه بلاک چین فعلی ارائه می شود. این به این معنی است که اگر بلاک چین دارای سختی 3 باشد، باید بلوکی ایجاد کنیم که با سه صفر "000" شروع می شود. “000f34abad….”.

از آنجایی که ما هش را از محتوای بلوک گرفته‌ایم، نمی‌توانیم محتوا را تغییر دهیم، اما مطمئناً می‌توانیم ارزش اثبات کار (PoW) را تا زمانی که شرایط استخراج را برآورده کنیم، افزایش دهیم.

برای پیاده‌سازی این، یک متد mine() برای کلاس theBlock ایجاد می‌کنیم که مقدار PoW را افزایش می‌دهد و هش بلوک را محاسبه می‌کند تا زمانی که یک هش معتبر دریافت کنیم.

class Block {
  // constructor we used earlier
  mine(difficulty) {
    const regex = new RegExp(`^(0){${difficulty}}.*`);
    while (!this.hash.match(regex)) {
      this.pow++;
      this.hash = calculateHash(this);
    }
  }
}

//alternatively we can do this:

// Block.prototype.mine = (difficulty) => {
//   const regex = new RegExp(`^(0){${difficulty}}.*`);
//   while (!this.hash.match(regex)) {
//     this.pow++;
//     this.hash = calculateHash(this);
//   }
// };

کلاس بلاک چین را تعریف کنید:

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

class Blockchain {
  constructor(genesisBlock, chain, difficulty) {
    this.genesisBlock = genesisBlock;
    this.chain = chain;
    this.difficulty = difficulty;
  }
  static create(difficulty) {
    const genesisBlock = new Block(null); //the genesis block has no data i.e. null
    return new Blockchain(genesisBlock, [genesisBlock], difficulty);
  }
}

ما همچنین یک روش استاتیک را در داخل بلاک چین اعلام کرده‌ایم تا بتوانیم یک بلاک چین را مستقیماً با استفاده از مشکلی مانند const blockchain = Blockchain.create(2) مقداردهی اولیه کنیم - یک نمونه Blockchain با دشواری 2 به همراه یک بلوک پیدایش ایجاد می‌کند.

اضافه کردن بلوک های جدید به بلاک چین:

ما با موفقیت عملکردهای بلوک های خود را برای محاسبه هش و استخراج خود پیاده سازی کرده ایم. حال بیایید روشی را در داخل کلاس Blockchain تعریف کنیم تا بلاک های جدید را به ویژگی chain اضافه کنیم.

Blockchain.prototype.addBlock = (from, to, amount) => {
  const blockData = { from, to, amount };
  const lastBlock = this.chain[this.chain.length - 1];
  const newBlock = new Block(blockData, lastBlock.hash);
  newBlock.mine(this.difficulty);
  this.chain.push(newBlock);
}

در اینجا ما addBlockmethod را به نمونه اولیه کلاس Blockchain اضافه کردیم. این شبیه به تعریف متد addBlock مستقیماً در داخل کلاس است.

توضیح متد addBlock:

  • جزئیات یک تراکنش (فرستنده، گیرنده و مبلغ انتقال) را از پارامتر جمع آوری می کند.
  • یک بلوک جدید با جزئیات تراکنش ایجاد می کند.
  • بلوک جدید را با متد mine کلاس Block استخراج می کند.
  • بلوک جدید ایجاد شده را به خاصیت chain بلاک چین اضافه میکند.

اعتبارسنجی بلاک چین:

اکنون که همه عملکردهای بلاک چین خود را پیاده سازی کرده ایم، باید صحت بلاک چین را بررسی کنیم تا بتوانیم تایید کنیم که بلاک چین دستکاری نشده است. متد isValid را به نمونه اولیه Blockchain اضافه می کنیم.

Blockchain.prototype.isValid = () => {
  if (this.chain.length === 1) return true;
  for (let index = 1; index < this.chain.length; index++) {
  const currentBlock = this.chain[index];
  const previousBlock = this.chain[index - 1];
  if (
    currentBlock.hash !== calculateHash(currentBlock) ||
    previousBlock.hash !== currentBlock.previousHash
  )
    return false;
  }
  return true;
}

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

تست بلاک چین:

از آنجایی که ما یک بلاک چین کاملاً کارآمد داریم، بیایید تمام ویژگی هایی را که تا کنون پیاده سازی کرده ایم آزمایش کنیم. تابع تست را در فایل ها اضافه کنید و آن را با استفاده از گره <filename.js> از خط فرمان اجرا کنید.

(function () {
  const blockchain = Blockchain.create(2); // difficulty increases exponentially with each increase
  blockchain.addBlock("Alice", "Bob", 5);
  blockchain.addBlock("John", "Doe", 100);
  console.log(blockchain);
  console.log(blockchain.isValid()); // true - since we haven't tampered with it
  blockchain.chain[1].data.amount = 200; // tampering with the blockchain
  console.log(blockchain.isValid()); // false - tampered with the blockchain
})()

نتیجه باید مشابه تصویر زیر باشد، اما انتظار می‌رود که مقدار هش متفاوت باشد زیرا مهر زمانی متفاوت است.

پاداش: تنظیم زمان و سختی را مسدود کنید:

Block Time زمان تخمینی است که طول می کشد تا یک بلوک جدید پس از استخراج به زنجیره اضافه شود. یک مقدار ثابت است. زمان اضافه شدن بلاک جدید در برخی از پلتفرم های رایج مثل بیت کوین 10 دقیقه و برای اتریوم حدود 13 ثانیه است.

بیت کوین زمان بلاک خود را براساس زمان صرف شدخ برای استخراج 2016 بلاک جدید تنطیم میکند. با نرخ دلخواه یک بلوک در هر 10 دقیقه، یافتن 2016 بلاک دقیقاً دو هفته طول می کشد. اگر اضافه نمودن 2016 بلوک‌ قبلی بیش از دو هفته طول کشید، سختی شبکه کاهش می‌یابد و در غیر اینصورت افزایش می‌یابد. تغییر در سختی شبکه متناسب با مدت زمان بیش از دو هفته یا کمتر از دو هفته است که2016 بلوک قبلی برای یافتن آن صرف کردند. اینجوری میشه :

new difficulty = old difficulty * (2016 blocks * 10 minutes) / mining time of the previous 2016 blocks

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

زمان بلاک خود را 10 ثانیه یا 10000 میلی ثانیه اعلام می کنیم. ویژگی blockTime را در سازنده Blockchain اضافه کنید و به آن مقدار ثابتی مانند 10000 بدهید. سپس روش addBlock را ویرایش کنید تا بعد از هر تراکنش سختی را تنظیم کنید.

توجه: فراموش نکنید که ویژگی blockTime را به سازنده Blockchain اضافه کنید. در غیر این صورت کد با خطا مواجه می شود.

نتیجه:

امروز یاد گرفتیم که چگونه بلاک چین ها  کار می کنند و چگونه بلاک چین خود را از ابتدا با استفاده از جاوا اسکریپت ایجاد کنیم. کد منبع به صورت GitHub Gist شامل تنظیمات سختی در دسترس است. کد تعاملی بیشتری در مخزن GitHub موجود است و از برنامه TypeScript-run در ترمینال برای تعامل با بلاک چینی که امروز ایجاد کردیم استفاده می کند.

 

 

منبع: gitconnected.com