使用 NodeJS 实现一个简单区块链

35岁的程序员 2018-08-01 14:43:14 ⋅ 504 阅读

每天我们都会听说发现新的数字货币的消息,或者有人说它们是一个很快就会爆炸的大泡沫,其中只有区块链会留下。但是,什么是区块链?

Blocks是一个不断增长的记录列表,这些记录是通过加密技术链接和保护的。

因此,区块链是一个名为Blocks 的不可变的连续记录链。每个块都可以包含事务,文件或您喜欢的任何数据。重要的是他们用哈希链接在一起。

区块链是设计安全的,是具有高拜占庭容错能力的分布式计算系统的一个例子。这使得区块链可能适用于记录事件,医疗记录和其他记录管理活动,例如身份管理,交易处理或投票。

区块链在技术上如何运作?

1.创建徽标

创建新项目的第一步是创建徽标。它使一切都变得真实。为此,我使用了Squarespace徽标创建器,结果如下:

image.png

现在我们可以从我们的项目开始。

2.从Express开始

为了便于创建API以与区块链交互,我使用包npm express-generator直接使用ExpressJS启动了项目

npm install -g express-generator 
express ./chiccocoin 
cd chiccocoin 
yarn

完整的代码在github--chiccocoin

3.创建区块链

现在我们要创建我们的区块链。
重读区块链的定义我们可以总结出绝对必要的功能是:

1. newBlock:创建新块的函数
2. newTransaction:创建事务并将其排队以在下次创建块时保存的函数
3. hash:加密块的函数
4. lastBlock:将返回链的最后一个块的函数

因此我们可以使用以下结构创建blockchain.js文件:

class Blockchain {
  constructor () {
    // Create chain and transaction
    this.chain = []
    this.current_transactions = []

    // Binding of this
    this.newBlock = this.newBlock.bind(this)
    this.newTransaction = this.newTransaction.bind(this)
    this.lastBlock = this.lastBlock.bind(this)
    this.proofOfWork = this.proofOfWork.bind(this)
  }

  newBlock () { /* Create the new block */ }

  newTransaction () { /* Store a new transaction */ }

  hash (block) { /* hash the block */ }

  lastBlock () { /* return the last block */}
}

module.exports = Blockchain

我们的构造函数将创建两个重要的变量,chain和current_transaction。链将按顺序包含我们所有的块。Current_transactions将包含将在下一次挖掘时添加到块的所有事务

3.1创建一个块

但什么是块?将使用块的表示是一个javascript对象,它将包含:

1. 指数
2. 时间戳
3. 交易清单
4. 证明
5. 上一个块的哈希
const block = {
    'index'1,
    'timestamp'1506057125.900785,
    'transactions': [
        {
            'sender'"8527147fe1f5426f9dd545de4b27ee00",
            'recipient'"a77f5cdfa2934df3954a5c7c7da5df1f",
            'amount'5,
        }
    ],
    'proof'324984774000,
    'previous_hash'"2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
}

通过这种方式,区块链的想法变得更加清晰。是一组连接到前一个的顺序块(索引),并使用加密(previous_hash)进行保护。区块内的previous_hash是整个区块链的关键。它使我们能够保证整个链条的安全性和不变性。如果攻击者可以在该块之后立即修改链的块,则所有哈希都是错误的。显然,它可能会尝试重新计算整个链条的哈希值,这就是为什么更多的区块更多的区块链是安全的。此外,在每个节点中都存在(相同的)区块链副本(在这种情况下,NodeJS的实例)这使得黑客几乎不可能同时修改所有副本。

所以在我们的例子中创建一个新块非常简单。我们只需要将一个新对象推送到链中。该函数将接收证明(然后我们将讨论它是什么)和前一个块哈希并将返回块。该函数还将向块中添加尚未保存的所有事务并清理变量current_transactions

3.1.1哈希函数

用于我们的Chiccocoin的哈希函数是一个简单的SHA256,但您可以使用您喜欢的哈希函数。重要的是要执行前一个块的哈希,为此我们将执行序列化对象的哈希

3.2创建交易

添加新事务的功能非常简单。是添加到current_transaction数组的事务。交易是由发件人,收件人和金额组成的对象。它将是在块内存储事务的挖掘功能。对于实用程序,我们将确保该函数向我们返回将保存它的块的索引

class Blockchain {
  constructor () {
    // Create chain and transaction
    this.chain = []
    this.current_transactions = []

    // Binding of this
    this.newBlock = this.newBlock.bind(this)
    this.newTransaction = this.newTransaction.bind(this)
    this.lastBlock = this.lastBlock.bind(this)
    this.proofOfWork = this.proofOfWork.bind(this)
  }

  newBlock (proof, previousHash) {
    const block = {
      index: this.chain.length + 1,
      timestamp: new Date(),
      transactions: this.current_transactions,
      proof: proof,
      previous_hash: previousHash
    }
    this.current_transactions = []
    this.chain.push(block)
    return block
  }

  newTransaction (sender, recipient, amount) {
    this.current_transactions.push({
      sender: sender,
      recipient: recipient,
      amount: amount
    })
    return this.lastBlock()['index'] + 1
  }

  hash (block) {
    const blockString = JSON.stringify(block)
    const hash = crypto.createHmac(process.env.HASH_TYPE, process.env.CRYPTO_SECRET)
    .update(blockString)
    .digest('hex')

    return hash
  }

  lastBlock () {
    return this.chain.slice(-1)[0]
  }
}

module.exports = Blockchain

4.工作证明

通常,工作证明是发明并用于阻止拒绝服务攻击的功能或协议,但区块链使用它来确定如何在自己上创建或挖掘新块。POW的目标是发现一个解决问题的数字。这个数字一定很难找到 但很容易验证,就像素数的计算一样,我们发现的数字越多,找到一个就越困难,但是理解它是否是非常平庸的努力。

为了挖掘Chiccocoin,我们决定创建一个c4ff3。我们的POW将是这样的:

c4ff3e9373e...5e3600155e860

我们来编码吧。必要的功能是两个:

1. validProof:给出之前的POW和ap编号检查问题的解决方案是否正确
2. proofOfWork:循环直到找到解决方案
validProof (lastProof, proof) {
    const guessHash = crypto.createHmac(process.env.HASH_TYPE, process.env.CRYPTO_SECRET)
    .update(`${lastProof}${proof}`)
    .digest('hex')
    return guessHash.substr(05) === process.env.RESOLUTION_HASH
  }

  proofOfWork (lastProof) {
    let proof = 0
    while (true) {
      if (!this.validProof(lastProof, proof)) {
        proof++
      } else {
        break
      }
    }
    return proof
  }

5.通过API服务

通过API为expressjs服务我们的区块链开始项目将非常简单。

我们将创建三个API:

1. /transactions/new 为块创建新事务
2. /mine 告诉我们的服务器挖掘一个新块。
3. /chain 返回完整的区块链。

我在里面创建了一个Chiccocoin支持类,/middleware/chiccocoin.js其中包含API的所有必要中间件并实例化一个新的区块链

5.1链端点

这个端点非常简单。只需返回存储在区块链内的链数组

5.2交易终点

事务端点将检查传递的数据,并将调用区块链的newTransaction函数。将来我们可以使用这个中间件来检查实际的发件人和收件人是否正确和/或交易是否可以完成。我们将使用newTransaction函数返回的信息来通知用户将保存事务的块。

5.3采矿终点

我们的采矿终点是chiccocoin成为现实的地方。它必须做四件事:

计算工作证明
通过添加授予我们1个硬币的交易来奖励矿工(我们)
添加所有待处理的交易
通过将新块添加到链中来构造新块
const Blockchain = require('./blockchain')
const { validationResult } = require('express-validator/check')

class Chiccocoin {
  constructor () {
    this.blockchain = new Blockchain()
    this.getChain = this.getChain.bind(this)
    this.mine = this.mine.bind(this)
    this.newTransaction = this.newTransaction.bind(this)
  }
  getChain (req, res, next) {
    req.responseValue = {
      message'Get Chain',
      chainthis.blockchain.chain
    }
    return next()
  }

  mine (req, res, next) {
    const lastBlock = this.blockchain.lastBlock()
    const lastProof = lastBlock.proof
    const proof = this.blockchain.proofOfWork(lastProof)
        // Create a new transaction with from 0 (this node) to our node (NODE_NAME) of 1 Chiccocoin
    this.blockchain.newTransaction('0', process.env.NODE_NAME, 1)

    // Forge the new Block by adding it to the chain
    const previousHash = this.blockchain.hash(lastProof)
    const newBlock = this.blockchain.newBlock(proof, previousHash)

    const responseValue = Object.assign({
      message'New Block mined'
    }, newBlock)
    req.responseValue = responseValue
    return next()
  }

  newTransaction (req, res, next) {
    const errors = validationResult(req)
    if (!errors.isEmpty()) {
      return res.status(422).json({ errors: errors.mapped() })
    }
    const trans = req.body
    const index = this.blockchain.newTransaction(trans['sender'], trans['recipient'], trans['amount'])
    const responseValue = {
      message`Transaction will be added to Block ${index}`
    }
    req.responseValue = responseValue
    return next()
  }
}

module.exports = new Chiccocoin()

我们可以通过curl或Postman测试我们所有的API。我在存储库中添加了postman_collection.json,以简化邮递员的使用。

牛逼的blockchain他背后的想法是什么新的或复杂的,因为我们都看到了。Banally开发人员每天使用区块链而没有意识到它(git)。然而,这是一个非常古老的概念,在新的观点下重新焕发生机,正在改变对经济的思考方式,创造泡沫(在我看来)和从“金融时代”开始的“更安全”经济的新可能性。常识观。有能力控制交易的时间和方式,这种情况正在悄然发生,但具有巨大的潜力。

我们创建的是一个简单的区块链,它只与一个节点一起工作,只有一个节点可以制作它(有基于此的加密货币)。当然,关于这个主题的多节点和所有问题的管理同样有趣。

我希望这篇文章能让你超越比特币交易本身,并让你对区块链真正做的事感兴趣。

---------------END---------------

IT



全部评论: 0

    我有话说:

    Node实战篇:Nodejs 接 Mariadb 实例

    MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可 MariaDB的目的是完全兼容MySQL

    Nodejs 接 Mariadb 实例

    是时候关联数据库了

    Node实战篇:使用joi来验证数据模型 (十)

    Joi 是 hapijs 自带的数据校验模块,他已经高度封装常用的校验功能,本文就是介绍如何优雅地使用 joi 对数据进行校验......

    Node 模块之 util URL queryString path(八)

    第一部分 util util是一个Node.js核心模块,util模块设计的主要目的是为了满足Node内部API的需求。其中包括:格式化字符串、对象的序列化、实现对象继承等常用方法。要使用util

    Node实战篇:Express--jade模板引擎(七)

    Jade(Pug) — Node Template Engine,一个高性能的模板引擎,专为 Node 而做......

    Node实战篇:Express路由(三)

    Express 是一个基于 Node.js 平台的极简、灵活的 web 应用开发框架,它提供一系列强大的特性,帮助你创建各种 Web 和移动设备应用。

    Nodejs实用技巧之-Exceljs

    今天我们就在此介绍下exceljs的基本使用,应该可以满足我们大部分的需求。

    Node实战篇:Express 中间件-body-parser(五)

    body-parser是什么?body-parser是一个HTTP请求体解析中间件,使用这个模块可以解析JS

    NodeJS 10.5.0 中的线程:实用介绍

    几天前,Node.js版本10.5.0发布,其中包含的主要功能之一是添加了线程支持。

    Node实战篇:Express-session解析(八)

    Session和HTTP协议属于不同层面的事物,HTTP属于ISO七层模型的最高层应用层,前者Session不属于后者,前者HTTP是具体的动态页面技术来实现的,但同时它又是基于后者的。

    为什么要使用 Node.js?这几点你必须知道!

    经过这几年的发展,前端普遍进入了技术深水区,只会Web页面开发已经难以满足企业的需求,Node逐渐成为了刚性技能。 但Node在业务上的使用还没有那么普及,有的时候想用老板还不同意,本文将从4个角度

    Nodejs视频服务器 切片ffmpeg

    Node 视频服务器 切片ffmpeg

    你想更好的理解Node.js中的Buffer吗?看一下这个。

    不论是否是科班出身,认真读完,想必会给你带去一些收获.

    Node实战篇:Express 中间件 cookie-parser(六)

    cookieParser()实际上是对http传入的cookie进行解析后赋值给req.cookies,使得中间件可用

    Node实战篇:Express中间件与request(四)

    Express 是一个路由和中间件 Web 框架,其自身只具有最低程度的功能:Express 应用程序基本上是一系列中间件函数调用。

    Node模块之Events模块(五)

    Node模块之Events模块(五)

    老板要我开发一个简单的工作流引擎

    第1关 一天,老板找到我,说要做个简单的工作流引擎。 我查了一天啥是工作流,然后做出了如下版本: 按顺序添加任意个审批人组成一个表,最后加一个结束节点 记录当前审批人,当审批完后,审批人向后

    Node初识与配置安装(一)

    JavaScript 发展的一个重要里程碑,标志了动态...

    MySql实战篇:写一个简单的存储过程,完成订单定时任务

    前言之前我们分享了MySql的性能优化、索引详解等内容,本篇文章主要是针对想要入门MySql存储过程的读者,主要实现的业务是订单库里面的超过30分钟没有支付的订单全部置为失效订单......