区块链概念
狭义:区块链是一种按照时间顺序将数据区块以顺序相连的方式组合成的一种链式数据结构,并以密码方式保证的不可篡改和不可伪造的分布式账本。
一、挖矿(产生新区块)
首先,区块链是由每一个区块联系而形成的,在产生新区块之前必须先有一个最初始的区块,这个区块也叫创世区块。通过这个创世区块,不停地通过变化随机数(nonce)来计算出符合条件的区块。以下是创世区块基本信息:
const initBlock = { index: 0, data: 'hey,this is a block chain', previousHash: '0', timestamp: '1551806536961', nonce: 80490, hash: '0000352fb27dd1141fa7265833190a53e5776b1111e275db0d9a77bf840081e6' };
index:是指每个区块的序号
data: 这里存放着区块中所有的信息,例如转账,余额等数据
previousHash: 指的是上一个区块的hash值,创世区块没有上一个,显示0即可
timestamp:指的是创建这个区块的时间
nonce:这个是随机数,挖矿就是通过不停变换这个nonce来计算出符合条件的哈希。
hash: 本区块的hash值,通过前面5个字段的信息进行hash运算得出的值。
接着,通过不停的hash运算计算出符合条件的哈希,即挖矿。挖矿也可以调节难度的大小,例如算出的哈希值必须前3位数必须为1或者末3位数必须为1等等,这个可以自行的去定义,只要最后留一个控制的开关,方便控制即可。可以在定义一个变量
哈希的计算:
.createHash('sha256') .update(index + data + previousHash + timestamp + nonce) .digest('hex')
_that.difficulty = 3 // 即前3位或者末3位数必须为1,数量越多难度越大
生成了符合条件的hash之后,则产生了新的区块,但是还要对这个区块进行校验看看是否有效,因为可能这是一个被篡改的非法的区块,也有可能和这个链没有任何关系的区块而仅仅只是符合上述哈希的规则而已。所以,需要进行一下校验,,前后区块的有效性。
isValidaBlock(newBlock,lastBlock) { if (newBlock.index !== lastBlock.index+1) return false if (newBlock.previousHash !== lastBlock.hash) return false if (newBlock.timestamp <= lastBlock.timestamp) return false if (newBlock.hash.slice(1 ,_that.difficulty) !== '1'.repeat(_that.difficulty)) return false if (newBlock.hash !== this.computeHashForBlock(newBlock)) return false //确保随机数正确 // 都满足则返回true return true }
除了上面的校验之外,还需要使用上面这个函数对整一个chain进行一个每一个块的校验,以保证每一个块的信息是正确的,是没有被篡改过的是合法的。
二、构建P2P网络区块链的网络是去中心化的,即没有中心服务器的网络,客户端不需要依赖中心服务器来获取或者处理数据。区块链网络中,有这许许多多的节点,每个节点都是一个独立的成员,他们既是客户端也是服务器,节点与节点直接都是点对点进行连接(peer-to-peer),不需要通过某一个中心服务器进行中转,所以,信息安全的角度来说,点对点的连接方式对信息私密性是非常可靠的。
虽然,区块链是通过点对点的连接方式进行数据传输,但是,在这之前还需要一个东西作为引导,这个就是种子节点。因为,两个节点之间他们可能不是处在同一个域下,他们之间想要联系,必须有一方知道对方的ip和端口,这样才能和对方联系上。节点ip和端口号,在这个节点创建出来之后,种子节点就会发给它在这个区块链中所有节点的ip和端口号同时记录下这个新伙伴的ip和端口号。
那么,新的节点拿到了这一份"通讯录"之后,就会给这个"通讯录"中的所有小伙伴发个消息,告诉他们有一位新的小伙伴加入,之后,其他节点收到了这个信息,也会在自己的"通讯录"中加上新伙伴的ip和端口号,相当于加入了白名单。这样新的节点接下来就可以和任意的的节点进行通信了。
下面用代码演示一下:
(res)=>{ _that.remotePeerInfo = res.data.data //1 _that.addPeersList(res.peersList) //2 _that.boardCast(_that.remotePeerInfo) //3 _that.blockChainUpdate(blockChain,blockData) //4 } addPeersList(peers) { peers.forEach(peer => { if (!_that.peers.find(v => _that.isEqualPeer(peer, v))) { _that.peers.push(peer) } }) } boardCast(remotePeerInfo) { this.peers.forEach(v => { this.send(action, v.port, v.address) }) } blockChainUpdate(blockChain,blockData){ if(newChain.length === 1 ){ return } if(_that.isValidaChain(newChain) && newChain.length>_that.blockchain.length){ _that.blockchain = Object.assign({}, newChain) }else{ console.log('error') return } if (trans.every(v => _that.isValidTransfer(v))) { _that.data = trans } }
1.保存种子节点传来的此新节点的信息包括ip和端口号,因为,新节点的ip和端口号是会有改变的情况。
2.接受种子节点传来的节点列表,将列表的节点遍历检查一下,没有相同的就写进列表中。
3.将新节点的信息广播到所有的节点上,同时接受到信息的节点更新一下节点列表
4.将区块链上信息同步一份都本地,同时对种子节点传来的blockchain进行每个区块的信息
三、转账交易BTC的交易模型是使用的是UTXO
而这个小型区块链的交易模型使用的是最简单的方法。