В этом руководстве мы собираемся создать упрощенную версию блокчейна Биткойн. В качестве справочника мы будем использовать Руководство разработчика ядра биткойнов. Цель состоит в том, чтобы начать с чего-то сверхпростого и постепенно наращивать и реорганизовывать наш путь до чего-то сверхсложного, напоминающего блокчейн Биткойн. Я решил использовать блокчейн Биткойн, потому что он наиболее широко используется и хорошо известен из всех. Я использую node версии 8.9.3 и npm версии 5.5.1. Не стесняйтесь оставлять комментарии или вопросы обо всем в этом руководстве.

Цепочка блоков обеспечивает публичный реестр Биткойна, упорядоченную запись транзакций с указанием времени. Эта система используется для защиты от двойной траты и изменения предыдущих записей транзакций.

Давайте запустим эти команды в нашем терминале:

  • mkdir BitcoinBlockchain
  • cd BitcoinBlockchain
  • npm install --save crypto-js
  • touch block.js

Итак, мы создали наш каталог BitcoinBlockchain и добавили каталог node_modules, который включает только крипто-js-библиотеку, которая является библиотекой криптостандартов JavaScript. Теперь давайте создадим наш класс блока внутри block.js

const SHA256 = require('crypto-js/sha256');
class Block {
  constructor(index, previousBlockHeader = '', transactions, timestamp) {
    this.index               = index;
    this.header              = this.calculateHash();
    this.previousBlockHeader = previousBlockHeader;
    this.transactions        = transactions;
    this.timestamp           = timestamp;
  }
  calculateHash() {
    return SHA256(this.index  +
                  this.previousBlockHeader +
                  JSON.stringify(this.transactions)).toString() +
                  this.timestamp;
  }
}
module.exports = Block;

Биткойн использует алгоритм криптографического хеширования SHA-256, который создает строку текста, называемую подписью, из любого фрагмента данных. Поскольку каждый из наших блоков будет уникальным, каждый блок будет генерировать свой собственный уникальный хэш, используя свою функцию calculateHash(). Функция calculateHash() будет брать каждое свойство нового блока, объединять их в одну строку и возвращать хеш SHA-256 этой строки. Каждый блок также должен ссылаться на хэш предыдущего блока (заголовок). Это гарантирует, что транзакция не может быть изменена без изменения блока, в котором она записана, и всех последующих блоков. Давайте перейдем к нашему терминалу и быстро проверим это, выполнив следующие команды:

  • node
  • const Block = require(‘./block’)
  • new Block(0, “previous block’s header”, {coinAmount : 10}, Date())

И вы должны получить этот вывод

Block {
  index: 0,
  header: 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855undefined',
  previousBlockHeader: 'previous block\'s header',
  transactions: { coinAmount: 10 },
  timestamp: 'Fri Dec 29 2017 11:37:33 GMT-0700 (MST)'
}

Чтобы не усложнять задачу, сейчас мы просто добавим по одной простой транзакции в каждый блок {coinAmount:10}.. В будущем у нас будет набор (массив) транзакций в каждом блоке. Давайте создадим файл blockchain.js и начнем строить наш класс блокчейна.

const Block = require('./block');
class Blockchain {
  constructor() {
    this.chain = [this.createGenesisBlock()];
  }
createGenesisBlock() {
    return new Block(0, "This Is The Genesis Block", {coinAmount : 10}, Date());
  }
getLastBlock() {
    return this.chain[this.chain.length - 1];
  }
addBlock(newBlock) {
    newBlock.previousBlockHeader = this.getLastBlock().header;
    newBlock.header              = newBlock.calculateHash();
    this.chain.push(newBlock);
  }
}
module.exports = Blockchain

Итак, каждый раз, когда мы создаем новый блокчейн, он будет комплектоваться блоком Genesis. Вернитесь в терминал и запустите эти команды

  • const Blockchain = require(“./blockchain”);
  • const Block = require(‘./block’);
  • let newBlockchain = new Blockchain();
  • newBlockchain.addBlock(new Block(1, “previous block header data”, {coinAmount : 5}, Date()));
  • newBlockchain.addBlock(new Block(2, “previous block header data”, {coinAmount : 3.55}, Date()));

Обратите внимание, как хэш previousBlockHeader каждого блока совпадает с хешем previousBlockHeader предыдущего блока. Чувак, это умная шайба, ты понимаешь;)

Blockchain {
  chain:
   [ Block {
       index: 0,
       header: 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855undefined',
       previousBlockHeader: 'This Is The Genesis Block',
       transactions: [Object],
       timestamp: 'Fri Dec 29 2017 12:02:33 GMT-0700 (MST)' },
     Block {
       index: 1,
       header: '35f87048396bd3386a35dc4ddf5fdb2c07c628ae510d00afda3714002a34b8a7Fri Dec 29 2017 12:13:46 GMT-0700 (MST)',
       previousBlockHeader: 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855undefined',
       transactions: [Object],
       timestamp: 'Fri Dec 29 2017 12:13:46 GMT-0700 (MST)' },
     Block {
       index: 2,
       header: 'c2bd3f90136364832f43f87499888c6284f53deb9573c47fddd60c3d7e2313f5Fri Dec 29 2017 12:28:00 GMT-0700 (MST)',
       previousBlockHeader: '35f87048396bd3386a35dc4ddf5fdb2c07c628ae510d00afda3714002a34b8a7Fri Dec 29 2017 12:13:46 GMT-0700 (MST)',
       transactions: [Object],
       timestamp: 'Fri Dec 29 2017 12:28:00 GMT-0700 (MST)' }
    ]
}

Надеюсь, это имело смысл! Кричите в разделе комментариев, если нет. Во второй части мы собираемся добавить функцию проверки блокчейна, чтобы убедиться, что никто не вмешивается в наш блокчейн. Мы также собираемся приступить к созданию класса Transaction. И если все станет действительно интересным, мы поговорим о Merkle Roots; корень Меркла - это, по сути, просто хэш кучи хешированных транзакций, я знаю, что происходит много хеширования!