В этом руководстве мы собираемся создать упрощенную версию блокчейна Биткойн. В качестве справочника мы будем использовать Руководство разработчика ядра биткойнов. Цель состоит в том, чтобы начать с чего-то сверхпростого и постепенно наращивать и реорганизовывать наш путь до чего-то сверхсложного, напоминающего блокчейн Биткойн. Я решил использовать блокчейн Биткойн, потому что он наиболее широко используется и хорошо известен из всех. Я использую 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; корень Меркла - это, по сути, просто хэш кучи хешированных транзакций, я знаю, что происходит много хеширования!