Обзор

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

Если вы здесь впервые, обязательно посмотрите всю серию Блокчейн с самого начала, чтобы понять, что мы здесь делаем на самом деле.

Получение последнего сохраненного блока

Причина, по которой нам нужно получить последний блок, заключается в том, что нам нужно установить prevHash текущего блока, который будет добавлен в цепочку и сохранен в базе данных, на хеш последнего блока, поэтому мы должны запросить базу данных MongoDB, чтобы найти последний блок, сохраненный в базе данных, однако, если блока нет (новая цепочка еще не была добавлена), тогда он просто установит для него значение null, что в основном означает, что это первый блок в цепочке, и перед ним нет блока.

Давайте добавим новый метод getLastBlock в класс blockChain.

/* blockchain.js */
class BlockChain {
...
getLastBlock(callback) {
  //Get last block from Database
  return BlockChainModel.findOne(
    {},
    null,
    { sort: { _id: -1 }, limit: 1 },
    (err, block) => {
      //in case of err just log it and return (stop execution)
      if (err) return console.error("Cannot get last block ", err.message);
      //get out of the function and run callback passing it the lastBlock 
      return callback(block);
    }
  );
}
...
}

Метод getLastBlock отвечает за запрос к базе данных MongoDB, чтобы найти последний блок и запустить обратный вызов, передав ему найденный блок.

Мы сортируем MongoDB по _id, где указание отрицательного (сортировка: -1) значения означает, что база данных начнет поиск с конца, поэтому мы можем получить последний блок в цепочке, в случае, если блок не добавлен тем не менее, MongoDB вернет для нас null, поэтому позже нам придется дважды проверить его и обработать с сохранением блока.

Установить предыдущий хэш

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

...
if (validator.proofOfWork() == TARGET_HASH) {
            //Query for last block 
            this.getLastBlock((lastBlock) => {
              //only if the lastBlock exists (not null or undefined)
              if(lastBlock) {
                 //Link blocks together using hashes 
                 block.prevHash = lastBlock.hash;
              }
               //otherwise carry on with saving it into the DB.
               block.hash = hash(block);
               //Add it to the instance Save it on the DB Console Success
               let newBlock = new blockChainModel(block);
               newBlock.save((err) => {
                   if (err)
                       return console.log(chalk.red("Cannot save Block to DB ", err.message));
                   console.log(chalk.green("Block Saved on the DB"));
               });
               //Add to Chain
               this
                   .chain
                   .push(block);
               this.curr_transactions = [];
               return block;
       })
}
...

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

Мы также должны дважды проверить, что lastBlock действителен, потому что, когда MongoDB не находит, какой запрос (например, цепочка пуста, блоки еще не добавлены), он вернет null, поэтому мы должны убедиться, что он действителен, иначе просто продолжайте с сохранением и пусть prevHash будет нулевым, так как это первый блок в цепочке.

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

node ./main.js

Дождитесь завершения майнинга, затем откройте MongoDB Compass, чтобы просмотреть документы в базе данных. Вы должны заметить, что последний блок указывает (prevHash) на хэш блока прямо перед ним в цепочке.

Что дальше

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