用js写一个区块链的原型

时间:2022-11-29 20:01:48

Hash

主要是用于消息摘要和签名。开发中经常使用的MD5和SHA都是历史悠久的Hash算法。

特点

  • 从hash值不可以反向推导出原始的数据
  • 输入数据的微小变化会得到完全不同的hash值
  • 相同的数据会得到相同的值
  • 执行效率要高效,长的文本也能快速地计算出哈希值
  • hash算法的冲突概率要小

用md5做个测试

~ md5 -s "hello World"
MD5 ("hello World") = 39d11ab1c3c6c9eab3f5b3675f438dbf
~ md5 -s "hello world"
MD5 ("hello world") = 5eb63bbbe01eeed093cb22bb8f5acdc3

可以看到我们只改了一个字母“W”,但是得到的hash值却产生了非常大的变化。

区块的概念

比如每天要生成一个账本

1.给账本编上序号

2.将账本进行hash加密

3.将序号hash值时间戳和交易记录进行打包,最终形成的结构我们称之为区块

序号

时间戳

hash值

交易记录

4.我们做第二天账本的hash运算时,会加入第一天的hash值放到第二天的hash运算中生成新的hash,最终也形成一个新的区块

以此类推,形成最终的形态:

用js写一个区块链的原型

大家知道为什么我要把图做成竖的,因为在区块链中有一个区块高度的概念,序号的大小代表了区块的高度,区块高度作用就是为了缩小查询范围方便检索。类似于数据库分页一样的道理。

账本验证

账本数据依照时刻分块存储,这每个存储单元即称之为“区块”。而每一个区块的头部会记录这一数据块的序号、时间戳和Hash摘要数据。

比较巧妙的点在于,区块头部中的Hash摘要数据是由上一个区块的摘要数据和本区块的买卖账本数据叠加后经过Hash函数得到的,即:

第n块的Hash值 = Hash(第n-1块的Hash值 + 第n块的账本数据)

能够看到,虽然每一个区块内的账本数据是独立的,可是区块头部的Hash值却是依赖于上一区块的Hash值,从而形成了一条链式的结构。这就是是“区块链”名字的由来。

链上的任何一个区块中的数据受到的篡改,都将反映到最新的一个区块的Hash值上,因此,要想验证某个节点的账本数据是否正确,只需要比对最新一个区块的Hash值就可以证明整个链条是正确的,由此可以完成高效的账本验证。


1.定义​​transactions​​数组,表示这个区块链

2.写一个 ​​addTransaction​​ 方法向数组中添加​​transaction​​对象,对象中包括:订单号、金额、手续费、备注、hash 签名。

然后调用​​addTransaction​​方法,我们将每一次交易参数中的 hash 设为上一次交易记录返回的 hash 值。

const Web3 = require("web3")

let transactions = []

// let transaction = {
// orderNo: "",
// content: "",
// price: 0,
// fee: ""
// }

function addTransaction(orderNo, content, price, fee, hash) {
let transaction = {
hash, orderNo, content, price, fee
}
hash = Web3.utils.soliditySha3(transaction);
transactions.push(transaction)
return hash
}

function getTransactions() {
return transactions
}

let hash1 = addTransaction("1", 'content1', 10, 1, '0x000000000000000000000000000000000000000000000000')
let hash2 = addTransaction("2", 'content2', 10, 1, hash1);
let hash3 = addTransaction("3", 'content3', 10, 1, hash2)
let hash4 = addTransaction("3", 'content4', 10, 1, hash3)
console.log(getTransactions())
console.log(hash4)

然后输出一下结果,可以看到,下面这样的数据,每个 对象中 hash 值都是不一样的,我们试着修改第二个对象中的属性值,最终会影响后面全部属性的值。

(base) ➜  my-node git:(master) ✗ node src/assets/block.js
[
{
hash: '0x000000000000000000000000000000000000000000000000',
orderNo: '1',
content: 'content3',
price: 10,
fee: 1
},
{
hash: '0xd52d2b78624cc158cb9ffd08978e6123bfed12d6e50ff745b00d0261353897d6',
orderNo: '2',
content: 'content2',
price: 10,
fee: 1
},
{
hash: '0xb2d72e8f395d5e2e3c76dc8d17ca5c6017738ac0a73b76f6276b133dbdb6b7cd',
orderNo: '3',
content: 'content1',
price: 10,
fee: 1
},
{
hash: '0xade25042819fb38166e6631ff07ef85d2024c399f6f9a99bad2680fe0689bd5e',
orderNo: '3',
content: 'content',
price: 10,
fee: 1
}
]

通过这个例子我们对区块链的模型应该有一个初步了解了。