发帖  主题  评论  推荐  标签 用户 查搜   用户 密码 自动 注册  
 
面向对象 设计模式 领域驱动设计 企业架构 框架 开发教程 微服务 大数据 扩展性 并发编程 事件驱动 分布式 CQRS

什么是区块链blockchain

  本文试图用简单200行代码来解析区块链的基本原理。

区块链基本概念很简单:它其实是一个分布式数据库,维护一个不断增长的有序的记录列表。“区块链”术语通常与诸如交易,智能合约或加密货币等概念密切相关。涉及这么多概念使得理解区块链变成一个艰巨的任务。这里将通过一个称为NaiveChain库包使用200行的Javascript实现超简单的blockchain。

块结构

第一个逻辑步骤是决定块结构。为了使事情尽可能简单,我们仅包含最必要的:index,timestamp,data,hash和previous hash。

区块链

必须在块中找到前一个块的Hash,以保持链的完整性,代码如下:

class Block {
constructor(index, previousHash, timestamp, data, hash) {
this.index = index;
this.previousHash = previousHash.toString();
this.timestamp = timestamp;
this.data = data;
this.hash = hash.toString();
}
}

块Hash散列

块需要实行Hash以保持数据的完整性。算法使用SHA-256。应该注意,这个Hash与“ 挖掘 ” 无关,因为不需要解决Proof Of Work工作证明问题。

var calculateHash = (index, previousHash, timestamp, data) => {
return CryptoJS.SHA256(index + previousHash + timestamp + data).toString();
};

生成块

为了生成一个块,我们必须知道前一个块的哈希,并创建所需内容的其余部分(=索引,散列,数据和时间戳),块数据是由最终用户提供的。

var generateNextBlock = (blockData) => {
var previousBlock = getLatestBlock();
var nextIndex = previousBlock.index + 1;
var nextTimestamp = new Date().getTime() / 1000;
var nextHash = calculateHash(nextIndex, previousBlock.hash, nextTimestamp, blockData);
return new Block(nextIndex, previousBlock.hash, nextTimestamp, blockData, nextHash);
};

 

存储块

内存中的Javascript数组用于存储区块链。区块链的第一块总是一个所谓的“基因块genesis-block”,它是硬编码的。

var getGenesisBlock = () => {
return new Block(0, "0", 1465154705, "my genesis block!!", "816534932c2b7154836da6afc367695e6337db8a921823784c14378abed4f7d7");
};
var blockchain = [getGenesisBlock()];

 

验证块的完整性

在任何指定时间,我们必须能够验证块或块链在完整性方面是否有效。特别是当我们从其他节点接收新块,并必须决定是否接受他们时。

var isValidNewBlock = (newBlock, previousBlock) => {
if (previousBlock.index + 1 !== newBlock.index) {
console.log('invalid index');
return false;
} else if (previousBlock.hash !== newBlock.previousHash) {
console.log('invalid previoushash');
return false;
} else if (calculateHashForBlock(newBlock) !== newBlock.hash) {
console.log('invalid hash: ' + calculateHashForBlock(newBlock) + ' ' + newBlock.hash);
return false;
}
return true;
};

 

选择最长的链

在指定时间链中应该总是只有一个显式块。在冲突的情况下(例如,两个节点都生成块号72),我们选择具有最长块数的链。

区块链选择长链

 

var replaceChain = (newBlocks) => {
if (isValidChain(newBlocks) && newBlocks.length > blockchain.length) {
console.log('Received blockchain is valid. Replacing current blockchain with received blockchain');
blockchain = newBlocks;
broadcast(responseLatestMsg());
} else {
console.log('Received blockchain invalid');
}
};

 

 

与其他节点通信

节点的一个重要部分是与其他节点共享和同步区块链。以下规则用于保持网络同步。

  • 当节点生成新块时,它将其广播到网络
  • 当节点连接到新的对等体时,它查询最新的块
  • 当节点遇到具有大于当前已知块的索引的块时,它将块添加到其当前链或查询整个区块链。

控制区块链

上图是当节点服从所描述的协议时遵循的一些典型的通信场景

不使用自动对等体发现。对等体的位置(= URL)就必须手动添加。

控制节点

用户必须能够以某种方式控制节点。这是通过设置HTTP服务器来完成的。

var initHttpServer = () => {
var app = express();
app.use(bodyParser.json());
app.get('/blocks', (req, res) => res.send(JSON.stringify(blockchain)));
app.post('/mineBlock', (req, res) => {
var newBlock = generateNextBlock(req.body.data);
addBlock(newBlock);
broadcast(responseLatestMsg());
console.log('block added: ' + JSON.stringify(newBlock));
res.send();
});
app.get('/peers', (req, res) => {
res.send(sockets.map(s => s._socket.remoteAddress + ':' + s._socket.remotePort));
});
app.post('/addPeer', (req, res) => {
connectToPeers([req.body.peer]);
res.send();
});
app.listen(http_port, () => console.log('Listening http on port: ' + http_port));
};

如代码所示,用户能够以以下方式与节点交互:

  • 列出所有块
  • 创建由用户提供内容的新块
  • 列出或添加对等体

控制节点的最直接的方法是例如使用Curl:

#get所有节点的块
curl http://localhost:3001/blocks

架构

应该注意,一个节点实际上暴露了两个Web服务器:一个用于用户控制节点(HTTP服务器),一个用于节点之间的对等通信(Websocket HTTP服务器)

区块链
NaiveChain的主要组件

结论

NaiveChain是为了演示和学习区块链而创建的。由于它没有“ 挖掘 ”算法(PoSPoW),它不能在公共网络中使用。它仍然实现了功能区块链的基本特征。

您可以检查G ithub存储库以获取更多技术详细信息。

 

更多区块链专题

 

解道移动版 | 关注解道 | 联系解道 | 关于解道 | 广告联系 | 网站地图 | 设为首页

沪ICP证12033263 如有意见请与我们联系 Powered by JdonFramework
返回顶部