Рубрики
Без рубрики

Как построить блокчан с помощью JavaScript (часть 1)

Автор оригинала: Xavier Decuyper.

Создание блокчан с JavaScript часть 1

В этом руководстве мы напишем очень крошечный блокчан в JavaScript. Это не будет слишком модно, но это будет достаточно, чтобы дать вам понимание того, как работает блокчан.

Мы назовем этот блокчан Savjeecoin. Давайте начнем!

Начнем с создания нового файла JavaScript для хранения всего нашего кода. Мы назовем это main.js И давайте начнем с определения того, как должен выглядеть блокчан и блоки.

Давайте начнем с создания Блок класс и давая ему конструктор. Когда вы создаете новый блок, вам нужно пройти его временной компьютер, некоторые данные и хеш блок, которые пошли до него:

class Block{
  constructor(timestamp, data, previousHash = '') {
    this.previousHash = previousHash;
    this.timestamp = timestamp;
    this.data = data;
  }
}

Вот что означает каждое свойство:

  • Timestamp рассказывает нам, когда блок был создан. Вы можете использовать любой формат, который вам нравится (в этом примере мы будем использовать Timestamp Unix)

  • данные Параметр может включать в себя любой тип данных, которые вы хотите связать с этим блоком. Если вы хотите создать криптовалюту, вы можете хранить данные транзакции здесь, как отправитель/получатель и сумма, которые были переданы.

  • предыдущийhash это строка, которая содержит хеш предыдущего блока. Это то, что создаст цепочку блоков и будет очень важно, чтобы обеспечить целостность нашего блокчана позже.

Каждый блок указывает на предыдущий блок (вот почему у нас есть предыдущийhash атрибут). Это означает, что каждый блок нуждается в хеш.

Хеш в основном как отпечаток пальца. Это уникально для каждого блока. Вы можете рассчитать хеш блок, взяв все его содержимое и пробегая его через хеш-функцию.

Итак, начнем с написания метода, который может рассчитать хеш текущего блока. Итак, внутри Блок Класс, мы создаем Calcultinghash Функция:

calculateHash() {
    return SHA256(this.previousHash + this.timestamp + JSON.stringify(this.data)).toString();
}

Обратите внимание, что я выбираю использовать хеш-функцию SHA256. Тем не менее, хеш SHA256 недоступен в JavaScript и требует, чтобы вы использовали внешнюю библиотеку. Я нашел это Crypto-JS Это отличная библиотека и содержит безопасные реализации для разных хэш-функций. Установите его с НПМ, как это:

npm install crypto-js

Затем мы можем импортировать его в нашу main.js файл так:

const SHA256 = require("crypto-js/sha256");

Теперь, когда у нас есть наш Calcultinghash () Метод, давайте использовать его в конструкторе наших Блок :

class Block{
  constructor(timestamp, data, previousHash = '') {
    this.previousHash = previousHash;
    this.timestamp = timestamp;
    this.data = data;
        
        // When creating a new Block, automatically calculate its hash.
    this.hash = this.calculateHash();
  }
}

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

class Blockchain{
  constructor() {
    this.chain = [];
  }
}

В этом случае блокчан является очень простым объектом, который содержит свойство цепь Отказ Это массив, содержащий все блоки на цепочке.

Прежде чем мы сможем добавлять новые блоки, мы должны добавить то, что называется «блок Genesis». Это первый блок на цепочке, и это немного особенное, потому что он не может указывать на предыдущий блок (это первый!)

Так что создать блок Genesis, я добавлю метод нашего класса под названием CreategeneseSeStlock () :

createGenesisBlock()
  return new Block("01/01/2017", "Genesis block", "0");
}

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

class Blockchain{
  constructor() {
    this.chain = [this.createGenesisBlock()];
  }

Теперь давайте добавим некоторые методы в нашу класс Blockchain, чтобы позволить нам делать базовые вещи, такие как добавление новых блоков и получения новейшего блока.

getlatestblock Метод самый простой. Это просто возвращает последний элемент на цепь множество:

getLatestBlock(){
  return this.chain[this.chain.length - 1];
}

AddBlock Метод немного сложен. Прежде чем мы сможем добавить новый блок в нашу цепочку, мы должны правильно установить предыдущийhash свойство этого блока. Он должен быть установлен в хэш последнего блока на нашей цепи. И мы также должны рассчитать хэш нового блока:

addBlock(newBlock){

    // The new block needs to point to the hash of the latest block on the chain.
  newBlock.previousHash = this.getLatestBlock().hash;
    
    // Calculate the hash of the new block
  newBlock.hash = newBlock.calculateHash();

    // Now the block is ready and can be added to chain!
    this.chain.push(newBlock);
}

Только сбоку Примечание. На самом деле добавление блоков в блокчану требует от вас «Мой». Это то, что мы добавим в часть 2 этого поста (так что держите чтение!)

Давайте проверим это. Для этого создайте экземпляр блокчана:

let savjeeCoin = new Blockchain();

И давайте добавим несколько блоков:

savjeeCoin.addBlock(new Block("20/07/2017", { amount: 4 }));
savjeeCoin.addBlock(new Block("22/07/2017", { amount: 10 }));

Там – мы создали два новых блока. Посмотрим, как наш блокчан теперь выглядит. Мы сделаем Savjeecoin и используем четыре пространства для его форматирования:

console.log(JSON.stringify(savjeeCoin, null, 4));

Вывод – это то, что наша блокчан выглядит прямо сейчас. Наш объект Blockchain содержит цепочку свойств (массив), которая содержит все наши блоки.

Большой! Теперь, когда мы знаем, что это работает, давайте постараемся сделать что-то другое. Blockchates отлично, потому что после добавления блока его нельзя изменить без исключения остальной части цепи.

В этой реализации, однако, для меня нет никакого способа проверить целостность нашего блокчана. Давайте добавим новый метод нашу блокчану, называемый исчервал Отказ Это вернется правдой, если цепочка действительна или ложна, если что-то неверно:

isChainValid(){
}

Чтобы проверить целостность, мы должны верить всю цепочку (не глядя на блок Genesis). Внутри этой петли мы собираемся проверить две вещи:

  • Это хеш блок до сих пор действителен? Чтобы убедиться, что мы пересчитаем хеш каждого блока. Если что-то изменилось внутри блока, он изменит хеш этого блока.

  • Указывает ли каждый блок на правильный предыдущий блок? Чтобы проверить это, мы увидим, если предыдущийhash блока равен хеш Свойство блока, которое пошло до него.

  • Это блок Genesis до сих пор не поврежден или он был подделан?

Вот полный метод:

isChainValid(){
  for (let i = 1; i < this.chain.length; i++){
    const currentBlock = this.chain[i];
    const previousBlock = this.chain[i - 1];}

    // Recalculate the hash of the block and see if it matches up.
        // This allows us to detect changes to a single block
    if (currentBlock.hash !== currentBlock.calculateHash()) {
      return false;
    }

    // Check if this block actually points to the previous block (hash)
    if (currentBlock.previousHash !== previousBlock.hash) {
        	return false;
        }
  }
    
    // Check the genesis block
    if(this.chain[0] !== this.createGenesisBlock()){
    	return false;
    }
    
    // If we managed to get here, the chain is valid!
    return true;
}

Теперь мы можем проверить целостность нашего блокчана бегом:

console.log('Blockchain valid? ' + savjeeCoin.isChainValid());

Если мы запустим его сейчас, это скажет, что да, наша цепочка действительно действительна (мы не добрались до него).

Теперь давайте попробуем и вмешиваемся с нашим блокчан. Давайте изменим блок 2 и перезаписываю свои данные (скажем, мы хотим притворяться, что мы передали 100 монет вместо 4):

// Tamper with the chain!
savjeeCoin.chain[1].data = { amount: 100 };

// Check if it's valid again
console.log('Blockchain valid? ' + savjeeCoin.isChainValid()); // will return false!

Когда мы запускаем это, обратите внимание, что программа обнаружила нашу попытку вмешиваться в цепочку!

Тем не менее, вы можете подумать, что есть другой способ, которым я могу вмешаться этим. Я изменил данные блока, но я не пересчитал хеш. Таким образом, вы можете попытаться быть умным, возьмите этот же блок и пересчитывают его хеш.

// Tamper with the chain!
savjeeCoin.chain[1].data = { amount: 100 };

// Recalculate its hash, to make everything appear to be in order!
savjeeCoin.chain[1].hash = savjeeCoin.chain[1].calculateHash():

Однако, когда мы запускаем это снова, он пока не обнаружит, что мы подделаны цепочкой. Это потому, что блок 2 теперь имеет предыдущийhash атрибут, который не соответствует хэш блоке 1.

Так что это было для нашей простой реализации блокчан! Это позволяет нам добавлять новые блоки и обнаруживать, когда кто-то вмешивается в данные внутри цепочки.

Тем не менее, это далеко не завершено!

В следующей части этой серии мы посмотрим на то, как мы можем реализовать доказательство алгоритма работы, поэтому мы можем помешать людям добавлять множество спам-блоков в нашу цепочку и сделать вмешательство еще сложнее:

Продолжить чтение: «Реализация доказательства работы (блокчан в JavaScript, часть 2)»

Исходный код доступен на Github И есть Видеоуправление Если вы хотите следить по пошаговым шагам.