У меня есть следующий скрипт javascript.Я пытаюсь создать пример сценария, как работает блокчейн.Я храню все данные блока в уровне DB.
const SHA256 = require('crypto-js/sha256');
var levelDB = require('./levelSandbox');
class Block{
constructor(data){
this.hash = "",
this.height = 0,
this.body = data,
this.time = 0,
this.previousBlockHash = ""
}
}
class Blockchain{
constructor(levelDB){
this.levelDB = levelDB;
this.blocksInLevelDB = {};
this.chain = {};
this.getBlockHeight()
.then(height => {
if(!height){
this.addBlock(new Block("First block in the chain - Genesis block"));
}
})
}
// Method for adding new block
addBlock(newBlock){
this.getBlockHeight()
.then(height => {
console.log('block height is: ', height);
console.log('blocksInLevelDB: ', this.blocksInLevelDB);
// Set block hight
newBlock.height = height;
// Set UTC timestamp
newBlock.time = new Date().getTime().toString().slice(0,-3);
// Set previous block hash
if(height > 0){
let blockData = JSON.parse(this.blocksInLevelDB[height-1]);
newBlock.previousBlockHash = blockData.hash;
}
// Block hash with SHA256 using newBlock and converting to a string
newBlock.hash = SHA256(JSON.stringify(newBlock)).toString();
console.log('newBlock obj: ',newBlock);
// Adding block object to chain & save in level db
this.levelDB.addLevelDBData(height, JSON.stringify(newBlock))
.then(console.log('Block added to level db'))
.catch(function(err){console.log('Error in adding new block: ', err)})
})
}
// Get block height
getBlockHeight(){
return this.levelDB.getAllDataFromLevelDB()
.then(data => {
let blockHeight = data.length;
for (const elem of data){
this.blocksInLevelDB[elem.key] = elem.value;
}
return blockHeight;
})
.catch(function(err){
return err;
});
}
}
В нормальном случае все работает нормально, за исключением пары случаев, таких как -
Case.1 - Если у уровня DB нет данных (пусто), тогда, если я запускаю следующий код, в базу данных уровня вставляется только одна запись, а не две.
var blockChain = new Blockchain(levelDB);
blockChain.addBlock(new Block('Second block in the chain'));
Но, если я изменил приведенный выше код так, как это -
var blockChain = new Blockchain(levelDB);
setTimeout(function(){
blockChain.addBlock(new Block('Second block in the chain'));
}, 3000);
, то он работает нормально (вставляя две записи).
Case.2 - Когда на уровне DB имеется более одной записи, и если я пытаюсь добавить еще одну запись, она работает нормально.Пример.
var blockChain = new Blockchain(levelDB);
blockChain.addBlock(new Block('Third block in the chain'));
Но в тот момент, когда я пытаюсь добавить более одной записи, вставляется только одна запись (последняя).Пример.
var blockChain = new Blockchain(levelDB);
blockChain.addBlock(new Block('Third block in the chain'));
blockChain.addBlock(new Block('Fourth block in the chain'));
blockChain.addBlock(new Block('Fifth block in the chain'));
Я знаю, что это происходит из-за обещания (асинхронной природы), когда все мои вызовы getBlockHeight()
выполняются асинхронно и получают одинаковое количество записей (высота блокчейна).Из-за чего во время добавления нового блока все записи вставляются с одним и тем же ключом и перекрывают друг друга.Но не могу понять, как правильно управлять такой ситуацией.