typesScript 制作一个简易的区块链(2)

pow 机制

1.哈希函数的特点

说到 pow 机制,就离不开哈希函数,哈希函数具有以下特点:

  • 输入长度不固定,输出长度固定
  • 输入不同,输出不同
  • 输入相同,输出相同
  • 不可逆
  • 雪崩效应

    雪崩效应:输入变量中只要有一点变化,输出就会发生巨大变化

const CryptoJS = require("crypto-js");
let mseeage1 = "heibaihui";
let mseeage2 = "heibaihu1";
console.log("mseeage1的哈希:" + CryptoJS.SHA256(mseeage1));
console.log("mseeage2的哈希:" + CryptoJS.SHA256(mseeage2));

运行结果如下:
在这里插入图片描述

我们可以看到我们只是修改了 mseeage2 的最后一个字符,但是哈希值却发生了巨大变化,这就是哈希函数的雪崩效应

2.实现 pow 机制

pow 机制就是通过哈希函数来生成一个哈希值,这个哈希值需要满足以下条件:

  • 哈希值的前 n 位为 0
  • 哈希值需要通过不断尝试来生成,直到满足条件为止

注意:哈希函数的输入是任意的,所以我们可以通过改变输入来生成不同的哈希值,直到满足条件为止
同时,比特币的 pow 机制中,n 的值是动态变化的,真正的挖矿就是通过不断尝试来生成满足条件的哈希值,然后通过这个哈希值来生成新的区块,而我们为了简化,n 的值是固定的

现在我们有一个需求,我们需要生成一个哈希值,这个哈希值的前 n 位为 0,n 的值为 3,计算出来的就可以获得计账权.

const CryptoJS = require("crypto-js");

const message = "heibaihui";
const logo = "0000";

const pow = (logo, message) => {
  let nonce = 0;
  const start = Date.now();
  while (true) {
    const hash = CryptoJS.SHA256(message + nonce).toString();
    if (hash.startsWith(logo)) {
      const end = Date.now();
      console.log(`找到满足条件的 nonce:${nonce}`);
      console.log(`对应的哈希值:${hash}`);
      console.log(`耗时:${(end - start) / 1000}`);
      break;
    }
    nonce++;
  }
};

pow(logo, message);

运行结果如下:

在这里插入图片描述

在这里我们通过不断尝试来生成满足条件的哈希值,直到找到满足条件的哈希值为止,然后输出这个哈希值和对应的 nonce 值,以及计算出来的时间,这就是 pow 机制的基本原理.
在比特币中,平均每 10 分钟产生一个新区块。
比特币网络通过调整挖矿难度来维持这个平均出块时间。如果全网算力增加,挖矿难度会相应提高,使得找到有效区块的时间仍然保持在大约 10 分钟左右;如果算力减少,难度会降低,以确保出块时间不会过长。
这个相对稳定的出块时间对于比特币网络的安全性和一致性非常重要。它既保证了交易的确认速度不会太慢,又使得攻击者难以篡改区块链,因为要重新计算一个区块以及后续的所有区块需要巨大的算力和时间。

接下来,我们就要修改 Block 类和 BlockChain 类,让他们可以保证新区块的创建有条件.确保出块时间.

修改 Block 类和 BlockChain 类

Block 类

// 定义一个区块类
export class Block {
  public data: string;
  public previousHash: string;
  public hash: string;
  public nonce: number;

  constructor(data: string, previousHash: string) {
    this.data = data;
    this.previousHash = previousHash;
    this.nonce = 0;
    this.hash = this.calculateHash();
  }

  // 计算哈希
  calculateHash(): string {
    return CryptoJS.SHA256(
      this.previousHash + this.data + this.nonce
    ).toString();
  }

  getAnswer(difficulty: number): string {
    let answer = "";
    for (let i = 0; i < difficulty; i++) {
      answer += "0";
    }
    return answer;
  }

  mine(difficulty: number): void {
    const start = Date.now();
    while (true) {
      this.hash = this.calculateHash();
      if (this.hash.substring(0, difficulty) !== this.getAnswer(difficulty)) {
        this.nonce++;
        this.hash = this.calculateHash();
      } else {
        const end = Date.now();
        console.log("挖矿成功,区块哈希值为:" + this.hash);
        console.log(`一共计算了: ${this.nonce}`);
        console.log(`耗时:${(end - start) / 1000}`);
        break;
      }
    }
  }
}

BlockChain 类

// 定义一个区块链类
export class Blockchain {
  public chain: Block[];
  public difficulty: number;

  constructor() {
    this.chain = [this.createGenesisBlock()];
    // 设置挖矿难度
    this.difficulty = 4;
  }

  // 创世区块的创建
  createGenesisBlock(): Block {
    return new Block("创世区块", "");
  }

  // 获取最后一个区块
  getLastBlock(): Block {
    return this.chain[this.chain.length - 1];
  }

  // 区块的追加
  pushLatestBlock(newBlock: Block): void {
    newBlock.previousHash = this.getLastBlock().hash;
    // newBlock.hash = newBlock.calculateHash();
    newBlock.mine(this.difficulty);
    this.chain.push(newBlock);
  }

  // 链的校验
  isChainValid(): boolean {
    for (let i = 1; i < this.chain.length; i++) {
      const currentBlock = this.chain[i];
      const previousBlock = this.chain[i - 1];

      // 校验区块的 hash 值
      if (currentBlock.hash !== currentBlock.calculateHash()) {
        console.log("当前区块的哈希值与计算出的哈希值不一致");
        return false;
      }

      // 校验区块链接是否正常
      if (currentBlock.previousHash !== previousBlock.hash) {
        console.log("当前区块的 previousHash 与前一个区块的 hash 不一致");
        return false;
      }
    }
    return true;
  }
}

main.ts

// 创建一个区块
const block1 = new Block("转账10个代币给张三", "1");
// 创建一个区块链
const blockchain1 = new Blockchain();
// 将区块添加到区块链中
blockchain1.pushLatestBlock(block1);
console.log(blockchain1.isChainValid());
console.log(blockchain1);

运行结果如下:
在这里插入图片描述

如图所示,我们成功创建了一个区块,并将其添加到区块链中,同时校验了区块链的完整性。并且,我们还实现了简易区块的哈希值计算和pow机制,使得区块链更加安全可靠。

好的,下面是一个简单的影片管理系统的 MySQL 数据库设计: ### 数据库设计 #### 影片表 | 列名 | 数据类型 | 描述 | | --- | --- | --- | | id | int | 影片ID,自增 | | title | varchar | 影片标题 | | director | varchar | 导演 | | actor | varchar | 演员 | | description | text | 影片简介 | | release_date | date | 上映日期 | | duration | int | 持续时间(分钟) | | rating | decimal | 评分 | | poster_url | varchar | 海报图片URL | #### 影片类型表 | 列名 | 数据类型 | 描述 | | --- | --- | --- | | id | int | 类型ID,自增 | | name | varchar | 类型名称 | #### 影片-类型关联表 | 列名 | 数据类型 | 描述 | | --- | --- | --- | | id | int | 关联ID,自增 | | film_id | int | 影片ID | | type_id | int | 类型ID | ### 数据库操作 #### 创建数据库 首先需要创建一个名为 `film_management_system` 的数据库: ``` CREATE DATABASE film_management_system; ``` #### 创建表 接着,我们可以使用以下 SQL 语句来创建上述三个表: ``` USE film_management_system; CREATE TABLE films ( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(255) NOT NULL, director VARCHAR(255), actor VARCHAR(255), description TEXT, release_date DATE, duration INT, rating DECIMAL(2,1), poster_url VARCHAR(255) ); CREATE TABLE film_types ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255) NOT NULL ); CREATE TABLE film_type_relations ( id INT PRIMARY KEY AUTO_INCREMENT, film_id INT NOT NULL, type_id INT NOT NULL, FOREIGN KEY (film_id) REFERENCES films(id), FOREIGN KEY (type_id) REFERENCES film_types(id) ); ``` #### 插入数据 接下来,我们可以向表中插入一些示例数据: ``` INSERT INTO films (title, director, actor, description, release_date, duration, rating, poster_url) VALUES ('肖申克的救赎', '弗兰克·德拉邦特', '蒂姆·罗宾斯,摩根·弗里曼', '本片根据斯蒂芬·金的同名小说改编', '1994-09-10', 142, 9.7, 'http://example.com/shawshank_redemption.jpg'), ('白日梦想家', '史蒂文·斯皮尔伯格', '莱昂纳多·迪卡普里奥,汤姆·汉克斯', '根据弗兰克·阿巴涅尔的小说《生命中不能承受之轻》改编', '2002-12-25', 141, 9.5, 'http://example.com/catch_me_if_you_can.jpg'); INSERT INTO film_types (name) VALUES ('剧情'), ('犯罪'); INSERT INTO film_type_relations (film_id, type_id) VALUES (1, 1), (1, 2), (2, 1), (2, 2); ``` #### 查询数据 最后,我们可以使用 SELECT 语句来查询数据: ``` SELECT f.title, f.director, f.actor, f.description, f.release_date, f.duration, f.rating, f.poster_url, GROUP_CONCAT(t.name) as types FROM films f LEFT JOIN film_type_relations r ON f.id = r.film_id LEFT JOIN film_types t ON r.type_id = t.id GROUP BY f.id; ``` 这将返回所有影片的标题、导演、演员、简介、上映日期、持续时间、评分、海报图片URL以及所属类型名称(多个类型名称用逗号分隔)。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值