尝试使用JavaScript实现一个简单的区块链

本文使用JavaScript实现一个简单的区块链,主要在node.js环境中运行。使用crypto-js来为区块链中的块创建哈希加密,使用express.js来创建用于与区块链交互的API。

以下是实现区块链的步骤:

  1. 创建一个新的Node.js项目并安装必要的库:crypto-js、express。
  2. 定义区块链中的区块结构。每个块应该包含唯一的索引、时间戳和想要存储在块中的数据。
  3. 创建一个区块链类,包含一些操作区块的方法,例如向链中添加新块。
  4. 使用 express.js 创建api,可以使用postman查询区块链,添加交易,以及执行挖矿操作。
  5. 使用 postman 测试区块链。

1. 创建一个新的Node.js项目并安装必要的库:crypto-js、express。

首先初始化一个node项目:

npm init

在package.json文件中,添加type字段:

"type": "module"

安装crypto-js和express:

npm install crypto-js
npm install express
npm install body-parser

在index.js中写入:

import express from "express";
import bodyParser from "body-parser";

const app = express();
const port = 3000;

app.listen(port, () => {
    console.log(`Example app listening on port ${port}`);
});

在terminal中输入:

node index.js

你将看到:

Server running on port 3000.

到这里,基本的node.js设置搞定。

2. 定义区块链中的区块结构。每个块应该包含唯一的索引、时间戳和想要存储在块中的数据。

新建blockchain.js文件,定义我们的区块结构:

import crypto from "crypto-js";

class Block {
    constructor(index, timestamp, transactions = [], previousHash = "") {
        this.index = index;
        this.timestamp = timestamp;
        this.transactions = transactions;
        this.previousHash = previousHash;
        this.hash = "";
        this.nonce = 0;
    }

    calcHash() {
        return crypto
            .SHA256(
                this.index +
                    this.timestamp +
                    JSON.stringify(this.transactions).toString() +
                    this.previousHash +
                    this.nonce,
            )
            .toString();
    }

    mineBlock(difficulty) {
        while (!this.hash.startsWith("0".repeat(difficulty))) {
            this.nonce++;
            this.hash = crypto
                .SHA256(
                    this.index +
                        this.timestamp +
                        JSON.stringify(this.transactions).toString() +
                        this.previousHash +
                        this.nonce,
                )
                .toString();
        }
    }
}

Block类包含6个属性,2个方法。

  • index:数字,区块的索引。
  • timestamp:数字,时间戳。
  • transactions:数组,储存每一笔交易信息。
  • previousHash:哈希值,记录上一个区块的哈希值。
  • hash:哈希值,记录当前区块的哈希值。
  • nonce:数字,用于找到满足特定条件的哈希值的随机数,pow相关。
  • calcHash:函数,计算哈希值,将indextimestamptransactionspreviousHashnonce拼接在一起输出哈希值。
  • mineBlock:函数,用于工作量证明的方法,接受一个代表复杂度的数字。本文对于工作量证明的计算条件为:寻找前4位为0的哈希值。

3. 创建一个区块链类,包含一些操作区块的方法,例如向链中添加新块。

同样在blockchain.js文件中,定义一个区块链类:

export class Blockchain {
    constructor() {
        this.difficulty = 4;
        this.pendingTrasactions = [];
        this.chain = [this.createGenesisBlock()];
    }

    createGenesisBlock() {
        const genesisPreviousHash = "0".repeat(64);
        const genesisBlock = new Block(0, Date.now(), [], genesisPreviousHash);
        genesisBlock.mineBlock(this.difficulty);
        genesisBlock.transactions.push({
            sender: "",
            recipient: genesisBlock.hash,
            amount: 50,
        });
        return genesisBlock;
    }

    createBlock() {
        const minerReward = {
            sender: "",
            recipient: "miner_adress",
            amount: 50,
        };
        this.pendingTrasactions.push(minerReward);

        const block = new Block(
            this.getLatestBlock().index + 1,
            Date.now(),
            this.pendingTrasactions,
            this.getLatestBlock().hash,
        );
        block.mineBlock(this.difficulty);

        this.chain.push(block);

        this.pendingTrasactions = [];
    }

    getLatestBlock() {
        return this.chain[this.chain.length - 1];
    }

    createTransaction(transaction) {
        this.pendingTrasactions.push(transaction);
        return this.chain[this.chain.length - 1].index + 1;
    }
}

Blockchain类包含3个属性,4个方法。

  • difficulty:数字,代表复杂度的数字。
  • pendingTrasactions:数组,资源池,用于存储每一笔交易。当新的区块产生时,会将资源池中的交易信息存入新区块中。
  • chain:数组,储存每一个区块。
  • createGenesisBlock:函数,创建第一个区块(创世块)。
  • createBlock:函数,创建新区块。
  • getLatestBlock:函数,返回最后一个区块。
  • createTransaction:函数,创建一笔交易,返回将被写入区块的索引值。

4. 使用 express.js 创建api,可以使用postman查询区块链,添加交易,以及执行挖矿操作。

接下来需要实现三个api,分别是:

GET /chain                //查看区块链
GET /mine                 //执行挖矿,成功后增加一个区块
POST /transactions/new    //添加一笔交易

回到index.js中,导入blockchain.js,并添加route: 

import express from "express";
import bodyParser from "body-parser";

import { Blockchain } from "./blockchain.js";

const app = express();
const port = 3000;

app.listen(port, () => {
    console.log(`Example app listening on port ${port}`);
});

app.use(express.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

const blockchain = new Blockchain();

app.get("/mine", (req, res) => {
    blockchain.createBlock();
    res.status(200).send(blockchain.chain[blockchain.chain.length - 1]);
});

app.post("/transactions/new", (req, res) => {
    // const transaction = {
    //     sender: "sender_adress",
    //     recipient: "recipient_adress",
    //     amount: 50,
    // };
    const transaction = req.body;
    const blockNumber = blockchain.createTransaction(transaction);
    res.status(200).send(`will be added to block ${blockNumber}`);
});

app.get("/chain", (req, res) => {
    res.status(200).send(blockchain.chain);
});

5. 使用 postman 测试区块链。

测试 GET http://localhost:3000/chain

测试 GET http://localhost:3000/mine
 

mine.png


测试 POST http://localhost:3000/transactions/new
 

:transactions:new.png

 

文章不断跟新,欢迎长期关注,同时如有错误请评论区或私信纠正互相研究学习!

VX:LALAKO_2

社区:http://t.csdnimg.cn/CNPxZ

免责声明:我们研究和内容中提供的信息仅供参考,不应被视为财务或投资建议。投资或参与金融活动的任何决定完全由你负责。我们不认可或推荐任何特定的投资策略,个人在做出任何投资决策之前应进行自己的研究并寻求专业建议。我们不对因将我们的内容用于投资目的而导致的任何财务损失、损害或不便承担责任。请始终注意与金融市场相关的风险,并在做出任何投资选择之前仔细考虑你的财务状况和风险承受能力。 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HongYingClub

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值