区块链入门学习(1)

什么是区块链

生活中区块链小栗子

现在家里有三口人,爸爸,妈妈和儿子。他们开始约定由爸爸记账,妈妈买菜了花了20元,爸爸加了一升油花了50元,这些都会被爸爸记在本子上(集中式)。有一天,爸爸突然想私自买包烟抽,于是在本子上做了手脚,妈妈没有发现,却被儿子发现了,妈妈却无可奈何,因为账本在爸爸手上,没有纰漏。于是,妈妈提议,三口人每个人都要做账本,当发现异常时,校对一下就知道哪个是错误的了,于是,家里就有了三份账本(分布式),每个人的资金有变动,都要广播一下,让另外的人记账。那么问题来了,这样每次都要每个人记账,是不是很费力啊,要是我,肯定觉得麻烦。但是,如果妈妈说,每记一笔都会有金币奖励,且只给第一个记完的人。那大家都会踊跃记账,又有问题出现了,儿子为了得到奖励去买喜爱的零食,就写得很潦草,完全看不懂(医生们的笔记,哈哈),妈妈发现了,提出,我们需要达成共识,我们要用格子纸写,每格一个字,每行空两格,要用正楷。同时,为了保证数据同步,我们要把前一个人的消费和时间,签名进行核对,没有错误以后,我们才能写进去,一直按规范做到最新的状态。
这样,要想做假账的话,除非贿赂一个人和你一起篡改一模一样的账本,否则是就是做不到的。

栗子?小结

那以上的账本,我们就可以说是一条区块链。每一笔交易就是一个区块。记账的人,我们称之为旷工,为了获取奖励,我们采用格子纸和正楷规范地记账过程就是挖矿。最后,我们引用共识机制保证数据同步和正确地持续链接下去。

简单来说,区块链就是由一个一个的包含着信息的区块连接起来的信息链。其中,包含的信息主要包括主体信息data、时间戳timestamp、前hash,本身hash,随机值nonce和本身的序号index等。用js代码表示即为:

const firstBlock = {
    timestamp: 1550155109024,//时间戳
    prevHash: '0',//前一个hash
    nonce:0,  //随机值
    hash: 'b788ba63a91f9fcbae92154679da5df7551939518e81aca280745c9eadb51fbd',//本身hash
    index: 0,  //序号
    data: {
		info:'I am a firstBlock in BlockChain'
	},//信息主体
}

那么,我们可以对区块做一个简单的分解,分为区块头和区块体。区块头(时间戳timestamp、前hash,本身hash)和区块体(主体信息data)
区块分解
每一个区块会根据自身区块里的其他值生成本身hash,后面的区块依据preHash来链接。一个一个地向前追溯,那么第一个就没有preHash,也就是我们常说的创世区块。
在这里插入图片描述
这里就会有了区块链的几个重要的特点,其本身不可被篡改、存储数据。那么,我们现在可以说,区块链是由一个个任何人都可以访问的区块构成的分布式的,且不可变的数据库。一旦一个区块被添加或者被篡改,除非让剩余的其余区块失效,否则它是不会再被改变的。但这是不可能的。对于要制作虚假交易,除非你说服了全网里超过51%的矿工都更改某一笔账目,否则你的篡改都是无效的。网络中参与人数越多,实现造假可能性越低。

hash

为了验证链的正确性,我们需要比对链中每个区块的信息,最后一一比对完,这样的工作量是非常大的。因此我们在区块链中,用到的hash算法是SHA256。为什么用hash算法呢?
因为hash有以下特点:

  • 可以根据相同信息生成一组相同的串
  • 根据串无法倒推出生成该串的信息
  • 信息方发生细微变化,得到的值将会变得面目全非。

这里用到的Hash算法不仅起到了验证链的正确性以外,还提供了合理的工作量证明(pow)。这里的pow方式我们发放到第二章,用代码给大家讲解。

说到代码,额。该到正题了,我们就用js来实现下简单的区块链的成链及相关验证

js实现简单的区块链的成链及相关验证

首先我们要创建一个区块类,来表示区块:

class EasyBlock {
    constructor(index, timestamp, data, prevHash = '') {
        this.index = index;
        this.prevHash = prevHash;
        this.timestamp = timestamp;
        this.data = data;
        this.hash = this.calHash();
    }

    calHash() {
        return crypto
            .createHash('sha256')
            .update(this.index + this.timestamp + this.data + this.prevHash)
            .digest('hex')
    }
}

其中我们有五个基本的属性和一个方法calHash(),来计算当前区块的hash值。引入了node里的crypto库。

走起!!再来定义一个链的类,进行链的表示:

class EasyChain {
    constructor() {
        this.blockchain = [
            this.getInitBlock()
        ];
    }

    getInitBlock() {
        return new EasyBlock(0, 1550155109024, 'Hi,I am initBlock in EasyChain!', 0)
    }
}

首先我们是设计了一个创世区块,给了初始值。俗话说的好,独木不成林,独块不成链?。那么我们接下来就需要在这个链里加方法addBlock()来增加区块。同时,我们需要知道上一区块的相关信息,以链起来。我们就需要getLastBlock()这个方法了。

addBlock(newblock) {
   newblock.prevHash = this.getLastBlock().hash;
   newblock.hash = newblock.calHash();
   this.blockchain.push(newblock)
}
getLastBlock() {
   return this.blockchain[this.blockchain.length - 1]
}

简单的成链我们算是做完了!Give Me Five!
对了,还有一点我们不能忘了。还要校验区块和整个区块链的正确性。那我们再加一个验证方法,我们从最后一个区块开始逐个验证。

isValid(chain = this.blockchain) {
        for (let i = 1; i < chain.length; i++) {//从最后一个区块开始逐个验证
            const currentBlock = chain[i];
            const previousBlock = chain[i - 1];

            if (currentBlock.hash !== currentBlock.calHash()) { //验证当前区块的合法性
                return false;
            }
            if (currentBlock.prevHash !== previousBlock.hash) {//验证是否可以成链
                return false;
            }
        }
        if (JSON.stringify(this.getInitBlock()) !== JSON.stringify(chain[0])) {//验证创世区块
            return false
        }
        return true
    }

当然,我们写完这个校验后,可以在增加区块的方法里进行优化改造,若修改的东西不合法的话,不符合校验规范,那么我们会抛错!!
可以简单的写成这样:

 addBlock(newblock) {
   newblock.prevHash = this.getLastBlock().hash;
   newblock.hash = newblock.calHash();
   if(newblock.isValid()){
		this.blockchain.push(newblock)
	}else{
		console.log('添加的区块异常!')
	}
}
   

最后我们再加一个展示区块链的方法。

 showChain() {
        console.log('当前区块链为:' + JSON.stringify(this.blockchain))
 }

这样我们就可以试试,我们自己的简单区块链easy-chain了。

let easyChain = new EasyChain();
easyChain.addBlock(new EasyBlock(1, new Date('2019/01/01').getTime(), '我是第二块'))
easyChain.addBlock(new EasyBlock(2, new Date('2019/01/02').getTime(), '我是第三块'))
easyChain.addBlock(new EasyBlock(3, new Date('2019/01/03').getTime(), '我是第四块'))
easyChain.showChain()

我们可看到成链了:

当前区块链为:[
{"index":0,"prevHash":0,"timestamp":1550155109024,"data":"Hi,I am initBlock in EasyChain!","hash":"ef38230827465f53e65f1f9af2f55abd7519939fdd5b5423e9d7e0c7eb58513a"},
{"index":1,"prevHash":"ef38230827465f53e65f1f9af2f55abd7519939fdd5b5423e9d7e0c7eb58513a","timestamp":1546272000000,"data":"我是第二块","hash":"6e2e15b10664e92f840839302843fc1fda80f24be1caf9ac09935ce307c0d37d"},
{"index":2,"prevHash":"6e2e15b10664e92f840839302843fc1fda80f24be1caf9ac09935ce307c0d37d","timestamp":1546358400000,"data":"我是第三块","hash":"0e5ac9045df3a433c2708db9ccc53a2277e47cf40df6a64a21860dd87dfb7309"},
{"index":3,"prevHash":"0e5ac9045df3a433c2708db9ccc53a2277e47cf40df6a64a21860dd87dfb7309","timestamp":1546444800000,"data":"我是第四块","hash":"6533a0d95a6d510b4e5cc0ca0e8523a46ce0417c91a6934351028d574bcca7b5"}
]

现在我们改变一下当前的区块值,

console.log('改变前校验结果为:' + easyChain.isValid())
easyChain.blockchain[1].index = 4
console.log('改变后校验结果为:' + easyChain.isValid())

输出给的是:

当前区块链为:[
{"index":0,"prevHash":0,"timestamp":1550155109024,"data":"Hi,I am initBlock in EasyChain!","hash":"ef38230827465f53e65f1f9af2f55abd7519939fdd5b5423e9d7e0c7eb58513a"},{"index":1,"prevHash":"ef38230827465f53e65f1f9af2f55abd7519939fdd5b5423e9d7e0c7eb58513a","timestamp":1546272000000,"data":"我是第二块","hash":"6e2e15b10664e92f840839302843fc1fda80f24be1caf9ac09935ce307c0d37d"},{"index":2,"prevHash":"6e2e15b10664e92f840839302843fc1fda80f24be1caf9ac09935ce307c0d37d","timestamp":1546358400000,"data":"我是第三块","hash":"0e5ac9045df3a433c2708db9ccc53a2277e47cf40df6a64a21860dd87dfb7309"},{"index":3,"prevHash":"0e5ac9045df3a433c2708db9ccc53a2277e47cf40df6a64a21860dd87dfb7309","timestamp":1546444800000,"data":"我是第四块","hash":"6533a0d95a6d510b4e5cc0ca0e8523a46ce0417c91a6934351028d574bcca7b5"}
]
改变前校验结果为:true
改变后校验结果为:false

校验成功啦!!这一篇暂时先分享自己学的这么多了,接下来会给大家分享下挖矿原理

发布了15 篇原创文章 · 获赞 2 · 访问量 8923
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览