200行代码实现blockchain 区块链实例详解


Posted in Javascript onMarch 14, 2018

了解blockchain的概念很简单(区块链,交易链块):它是分布式的(即不是放置在同一台机器上,不同的网络设备上的)数据库支持主办记录日益增长的名单。但是,这也是容易混淆blockchain与我们试图帮他解决了目标 - 在人们心中的那一刻,这个词是相当强烈的交易,合同或智能cryptocurrency的概念有关。

只有在这里blockchain - 是不是一回事比特币,并理解链块的基本知识比它似乎更容易,尤其是在,它是基于源代码的情况下。在本文中,我们提出了建立与在JavaScript中200行代码的简单模型。这个项目,我们称之为NaiveChain的源代码,可以在GitHub上找到。第1部分和第2部分:如果您需要刷上它的功能,使用我们的备忘单,我们将使用标准的ECMAScript 6。
块结构

第一步 - 确定应包含块的元素。为简单起见,我们只包括最必要的:先前块的指数(指数),时间标记(时间戳),数据(数据),散列和散列,要录制,以保持电路的结构完整性。

200行代码实现blockchain 区块链实例详解

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(); 
  } 
}

 散列单元

哈希块需要保持数据的完整性。在我们的例子,这适用于算法SHA-256。这种类型的散列是不相关的开采,因为在这种情况下,我们并没有用表现证明实施保护。

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); 
};

存储单元

使用blockchain 存储阵列。第一个块总是硬编码“创世纪块”。

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(typeof (newBlock.hash) + ' ' + typeof calculateHashForBlock(newBlock)); 
    console.log('invalid hash: ' + calculateHashForBlock(newBlock) + ' ' + newBlock.hash); 
    return false; 
  } 
  return true; 
};

选择链最长的

在电路块的顺序必须被明确指定,但是在发生冲突的情况下(例如,两个节点同时在同一生成的块和相同数量),我们选择电路,其中包含的块的数量较多。

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'); 
  } 
};

消息到其它网络节点

该网站的一个组成部分 - 与其他节点的数据交换。下列规则用于维护网络同步:
当一个节点产生新的单元,它会报告给网络;
当本机连接到新的盛宴,他要求有关最后生成的块信息;
当一个节点正面临着一个块,其中有一个指标比他还大,他增加了一个块到电路或请求的完整链条的信息。
自动搜索同龄人不执行,所有环节都手动添加。

单元的控制

用户应该能够以某种方式控制节点,通过将HTTP服务器解决。当与节点相互作用有以下功能:
打印所有单元的列表;
创建用户生成内容的新单元;
打印列表,或添加的节日。
互动的最直接的方式 - 通过卷曲:

200行代码实现blockchain 区块链实例详解

一个节点上的所有块#名单

curl http://localhost:3001/blocks

架构

值得注意的是,该网站是指两个Web服务器:HTTP进行用户控制的装置和向所述的WebSocket HTTP来安装节点之间的P2P连接。

如下为js 200行代码

<span style="font-family:Arial, Helvetica, sans-serif;">'use strict';</span> 
var CryptoJS = require("crypto-js"); 
var express = require("express"); 
var bodyParser = require('body-parser'); 
var WebSocket = require("ws"); 
var http_port = process.env.HTTP_PORT || 3001; 
var p2p_port = process.env.P2P_PORT || 6001; 
var initialPeers = process.env.PEERS ? process.env.PEERS.split(',') : []; 
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(); 
  } 
} 
var sockets = []; 
var MessageType = { 
  QUERY_LATEST: 0, 
  QUERY_ALL: 1, 
  RESPONSE_BLOCKCHAIN: 2 
}; 
var getGenesisBlock = () => { 
  return new Block(0, "0", 1465154705, "my genesis block!!", "816534932c2b7154836da6afc367695e6337db8a921823784c14378abed4f7d7"); 
}; 
var blockchain = [getGenesisBlock()]; 
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)); 
}; 
var initP2PServer = () => { 
  var server = new WebSocket.Server({port: p2p_port}); 
  server.on('connection', ws => initConnection(ws)); 
  console.log('listening websocket p2p port on: ' + p2p_port); 
}; 
var initConnection = (ws) => { 
  sockets.push(ws); 
  initMessageHandler(ws); 
  initErrorHandler(ws); 
  write(ws, queryChainLengthMsg()); 
}; 
var initMessageHandler = (ws) => { 
  ws.on('message', (data) => { 
    var message = JSON.parse(data); 
    console.log('Received message' + JSON.stringify(message)); 
    switch (message.type) { 
      case MessageType.QUERY_LATEST: 
        write(ws, responseLatestMsg()); 
        break; 
      case MessageType.QUERY_ALL: 
        write(ws, responseChainMsg()); 
        break; 
      case MessageType.RESPONSE_BLOCKCHAIN: 
        handleBlockchainResponse(message); 
        break; 
    } 
  }); 
}; 
var initErrorHandler = (ws) => { 
  var closeConnection = (ws) => { 
    console.log('connection failed to peer: ' + ws.url); 
    sockets.splice(sockets.indexOf(ws), 1); 
  }; 
  ws.on('close', () => closeConnection(ws)); 
  ws.on('error', () => closeConnection(ws)); 
}; 
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); 
}; 
var calculateHashForBlock = (block) => { 
  return calculateHash(block.index, block.previousHash, block.timestamp, block.data); 
}; 
var calculateHash = (index, previousHash, timestamp, data) => { 
  return CryptoJS.SHA256(index + previousHash + timestamp + data).toString(); 
}; 
var addBlock = (newBlock) => { 
  if (isValidNewBlock(newBlock, getLatestBlock())) { 
    blockchain.push(newBlock); 
  } 
}; 
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(typeof (newBlock.hash) + ' ' + typeof calculateHashForBlock(newBlock)); 
    console.log('invalid hash: ' + calculateHashForBlock(newBlock) + ' ' + newBlock.hash); 
    return false; 
  } 
  return true; 
}; 
var connectToPeers = (newPeers) => { 
  newPeers.forEach((peer) => { 
    var ws = new WebSocket(peer); 
    ws.on('open', () => initConnection(ws)); 
    ws.on('error', () => { 
      console.log('connection failed') 
    }); 
  }); 
}; 
var handleBlockchainResponse = (message) => { 
  var receivedBlocks = JSON.parse(message.data).sort((b1, b2) => (b1.index - b2.index)); 
  var latestBlockReceived = receivedBlocks[receivedBlocks.length - 1]; 
  var latestBlockHeld = getLatestBlock(); 
  if (latestBlockReceived.index > latestBlockHeld.index) { 
    console.log('blockchain possibly behind. We got: ' + latestBlockHeld.index + ' Peer got: ' + latestBlockReceived.index); 
    if (latestBlockHeld.hash === latestBlockReceived.previousHash) { 
      console.log("We can append the received block to our chain"); 
      blockchain.push(latestBlockReceived); 
      broadcast(responseLatestMsg()); 
    } else if (receivedBlocks.length === 1) { 
      console.log("We have to query the chain from our peer"); 
      broadcast(queryAllMsg()); 
    } else { 
      console.log("Received blockchain is longer than current blockchain"); 
      replaceChain(receivedBlocks); 
    } 
  } else { 
    console.log('received blockchain is not longer than received blockchain. Do nothing'); 
  } 
}; 
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'); 
  } 
}; 
var isValidChain = (blockchainToValidate) => { 
  if (JSON.stringify(blockchainToValidate[0]) !== JSON.stringify(getGenesisBlock())) { 
    return false; 
  } 
  var tempBlocks = [blockchainToValidate[0]]; 
  for (var i = 1; i < blockchainToValidate.length; i++) { 
    if (isValidNewBlock(blockchainToValidate[i], tempBlocks[i - 1])) { 
      tempBlocks.push(blockchainToValidate[i]); 
    } else { 
      return false; 
    } 
  } 
  return true; 
}; 
var getLatestBlock = () => blockchain[blockchain.length - 1]; 
var queryChainLengthMsg = () => ({'type': MessageType.QUERY_LATEST}); 
var queryAllMsg = () => ({'type': MessageType.QUERY_ALL}); 
var responseChainMsg = () =>({ 
  'type': MessageType.RESPONSE_BLOCKCHAIN, 'data': JSON.stringify(blockchain) 
}); 
var responseLatestMsg = () => ({ 
  'type': MessageType.RESPONSE_BLOCKCHAIN, 
  'data': JSON.stringify([getLatestBlock()]) 
}); 
var write = (ws, message) => ws.send(JSON.stringify(message)); 
var broadcast = (message) => sockets.forEach(socket => write(socket, message)); 
connectToPeers(initialPeers); 
initHttpServer(); 
initP2PServer();

总结

以上所述是小编给大家介绍的200行代码实现blockchain 区块链实例详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
理解Javascript_03_javascript全局观
Oct 11 Javascript
菜鸟javascript基础整理1
Dec 06 Javascript
JS仿iGoogle自定义首页模块拖拽特效的方法
Feb 13 Javascript
require.js的用法详解
Oct 20 Javascript
Node.js开发者必须了解的4个JS要点
Feb 21 Javascript
Jquery ui datepicker设置日期范围,如只能隔3天【实现代码】
May 04 Javascript
在node中如何使用 ES6
Apr 22 Javascript
原生JS实现移动端web轮播图详解(结合Tween算法造轮子)
Sep 10 Javascript
详解vue-router 初始化时做了什么
Jun 11 Javascript
layui中table表头样式修改方法
Aug 15 Javascript
基于游标的分页接口实现代码示例
Nov 12 Javascript
vue+elementui实现点击table中的单元格触发事件--弹框
Jul 18 Javascript
vue使用iframe嵌入网页的示例代码
Jun 09 #Javascript
JavaScript实现区块链
Mar 14 #Javascript
iview table render集成switch开关的实例
Mar 14 #Javascript
解决Vue.js 2.0 有时双向绑定img src属性失败的问题
Mar 14 #Javascript
Vue.js 动态为img的src赋值方法
Mar 14 #Javascript
基于datepicker定义自己的angular时间组件的示例
Mar 14 #Javascript
vue 过滤器filter实例详解
Mar 14 #Javascript
You might like
echo(),print(),print_r()之间的区别?
2006/11/19 PHP
php实现多张图片上传加水印技巧
2013/04/18 PHP
PHP创建word文档的方法(平台无关)
2016/03/29 PHP
详谈PHP面向对象中常用的关键字和魔术方法
2017/02/04 PHP
推荐一些非常不错的javascript学习资源站点
2007/08/29 Javascript
jquery.boxy弹出框(后隔N秒后自动隐藏/自动跳转)
2013/01/15 Javascript
JS图片自动轮换效果实现思路附截图
2014/04/30 Javascript
JavaScript限定图片显示大小的方法
2015/03/11 Javascript
JS自动倒计时30秒后按钮才可用(两种场景)
2015/08/31 Javascript
JavaScript的MVVM库Vue.js入门学习笔记
2016/05/03 Javascript
JavaScript+Java实现HTML页面转为PDF文件保存的方法
2016/05/30 Javascript
node.js爬虫爬取拉勾网职位信息
2017/03/14 Javascript
JavaScript中正则表达式使数字、中文或指定字符高亮显示
2017/10/31 Javascript
ReactNative中使用Redux架构总结
2017/12/15 Javascript
原生js实现公告滚动效果
2021/01/10 Javascript
微信小程序实现通过双向滑动缩放图片大小的方法
2018/12/30 Javascript
超简单的微信小程序轮播图
2019/11/22 Javascript
[01:40]2014DOTA2国际邀请赛 三冰SOLO赛后采访恶搞
2014/07/09 DOTA
python中os模块详解
2016/10/14 Python
python导入时小括号大作用
2017/01/10 Python
在python里从协程返回一个值的示例
2019/02/19 Python
python全栈知识点总结
2019/07/01 Python
Python实现遗传算法(二进制编码)求函数最优值方式
2020/02/11 Python
Python中的面向接口编程示例详解
2021/01/17 Python
pandas apply使用多列计算生成新的列实现示例
2021/02/24 Python
使用CSS3编写类似iOS中的复选框及带开关的按钮
2016/04/11 HTML / CSS
英国领先的男士美容护发用品公司:Mankind
2016/08/31 全球购物
史上最全面的Java面试题汇总!
2015/02/03 面试题
《一件运动衫》教学反思
2014/02/19 职场文书
小组口号大全
2014/06/09 职场文书
应届大学生自荐书
2014/06/17 职场文书
村长党的群众路线教育实践活动个人对照检查材料
2014/09/23 职场文书
民主生活会批评与自我批评总结
2014/10/17 职场文书
2014年保险业务员工作总结
2014/12/23 职场文书
读书笔记怎么写
2015/07/01 职场文书
用Python创建简易网站图文教程
2021/06/11 Python