区块链:通过演示Demo理解区块链运行原理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wtdask/article/details/81903953

BlockChain Demo

打开比特币Demo演示网页区块链Demo演示地址,我们可以看到如下页面。

这里写图片描述

点击开始演示

这里写图片描述

接下来是BlockChain Demo 2.0的新功能介绍

这里写图片描述

关于Demo功能区的介绍

这里写图片描述

并附有JavaScript代码和gitHubDemo地址

显示每个区块存储的信息

这里写图片描述

介绍区块链中区块的索引

这里写图片描述

介绍创建区块时候的时间戳
这里写图片描述

介绍区块中hash散列加密

这里写图片描述

介绍区块hash散列中前导零也就是难度的介绍

这里写图片描述

// cosnt Block = reuqire("./Block.js");

// class Blockchain {
  // constructor() {
    // this.blockchain = [Block.genesis()];
    this.difficulty = 3;
  // }

  // get() { ... }
  // get latestBlock() { ... }

  isValidHashDifficulty(hash) {
    for (var i = 0; i < hash.length; i++) {
      if (hash[i] !== "0") {
        break;
      };
    }
    return i >= this.difficulty;
  }
// };

// module.exports = Blockchain;

介绍Hash散列的生成规则

(索引+上一个散列+时间戳+数据+随机数)=散列
(0 +“0”+ 1508270000000 +“欢迎使用Blockchain Demo 2.0!”+ 604)= 000dc75a315c77a1f9c98fb6247d03dd18ac52632d7dc6a9920261d8109b37cf

这里写图片描述

介绍关于上一个区块中的Hash值
这里写图片描述

关于区块中的数据,这也是我们关注的

这里写图片描述

关于数据的变化,数据的微小变化都可以给Hash值带来巨大的变化。Hash值的是否有效,是我们设置的前导零难度决定的,符合前导零难度的规则才算是有效的Hash

这里写图片描述

假如一个区块链中的某一个区块中Hash值失效,那么它后面的区块都会失效
这里写图片描述

生成有效Hash散列的唯二变量就是数据和随机数,当我们需要的数据固定时,只有挖掘匹配的前导零难度的随机数才能寻找到新的区块

这里写图片描述

// const Block = require("./Block.js");
// const crypto = require("crypto");

// class Blockchain {
  // constructor() { ... }
  // get() { ... }
  // get latestBlock() { ... }
  // isValidHashDifficulty(hash) { ... }
  // calculateHashForBlock(block) { ... }
  // calculateHash(...) { ... }

  mine(data) {
    const newBlock = this.generateNextBlock(data);
    try {
      this.addBlock(newBlock);
    } catch (err) {
      throw err;
    };
  }
// };

// module.exports = Blockchain;

匹配查找有效Hash的数字,从0开始找,直到找到。随着难度的不断增加,有效散列的数量减少,因此匹配的计算力也会逐渐增大

这里写图片描述

新增新的区块

这里写图片描述

// const Block = require("./Block.js");
// const crypto = require("crypto");

// class Blockchain {
  // constructor() { ... }
  // get() { ... }
  // get latestBlock() { ... }
  // isValidHashDifficulty(hash) { ... }
  // calculateHashForBlock(block) { ... }
  // calculateHash(...) { ... }
  // mine(data) { ... }
  // generateNextBlock(data) { ... }

  addBlock(newBlock) {
    if (this.isValidNewBlock(newBlock, this.latestBlock)) {
      this.blockchain.push(newBlock);
    } else {
      throw "Error: Invalid block";
    }
  }
// };

// module.exports = Blockchain;

新增区块需要满足的要求

  1. 上一个区块的索引+1等于新的索引
  2. 上一个区块的hash要等于下一个区块的前导hash
  3. hash要满足前导零难度要求
  4. 正确的hash值

这里写图片描述

// const Block = require("./Block.js");
// const crypto = require("crypto");

// class Blockchain {
  // constructor() { ... }
  // get() { ... }
  // get latestBlock() { ... }
  // isValidHashDifficulty(hash) { ... }
  // calculateHashForBlock(block) { ... }
  // calculateHash(...) { ... }
  // mine(data) { ... }
  // generateNextBlock(data) { ... }
  // addBlock(newBlock) { ... }

  isValidNextBlock(nextBlock, previousBlock) {
    const nextBlockHash = this.calculateHashForBlock(nextBlock);

    if (previousBlock.index + 1 !== nextBlock.index) {
      return false;
    } else if (previousBlock.hash !== nextBlock.previousHash) {
      return false;
    } else if (nextBlockHash !== nextBlock.hash) {
      return false;
    } else if (!this.isValidHashDifficulty(nextBlockHash)) {
      return false;
    } else {
      return true;
    }
  }
// };

// module.exports = Blockchain;

全球的计算机网络共同维护,因此要确保区块链的安全性正确性一致性

P2p.js

const wrtc = require('wrtc');
const Exchange = require('peer-exchange');
const p2p = new Exchange("Blockchain Demo 2.0", { wrtc: wrtc });
const net = require("net");

class PeerToPeer {
  constructor(blockchain) {
    this.peers = [];
    this.blockchain = blockchain;
  }

  startServer(port) {
    const server = net
      .createServer(socket =>
        p2p.accept(socket, (err, conn) => {
          if (err) {
            throw err;
          } else {
            this.initConnection.call(this, conn);
          }
        })
      )
      .listen(port);
  }
}

module.exports = PeerToPeer;

同伴消息:链接对等方添加到网络

// const wrtc = require('wrtc');
// const Exchange = require('peer-exchange');
// const p2p = new Exchange(...);
// const net = require("net");

// class PeerToPeer {
  // constructor(blockchain) { ... }
  // startServer(port) { ... }

  discoverPeers() {
    p2p.getNewPeer((err, conn) => {
      if (err) {
        throw err;
      } else {
        this.initConnection.call(this, conn);
      }
    });
  }
// }

// module.exports = PeerToPeer;

同伴消息:Demo的三种同伴消息的状态

  • 蓝色:当前有效的
  • 绿色:连接的
  • 红色:断开连接的

改变:直接点击头像
链接:在红色对等方单击加号的图标
查看:在绿色的对等体单击短信图标
断开:点击绿色对等方上面的加号图标

这里写图片描述

P2p.js

// const wrtc = require('wrtc');
// const Exchange = require('peer-exchange');
// const p2p = new Exchange(...);
// const net = require("net");

// class PeerToPeer {
  // constructor(blockchain) { ... }
  // startServer(port) { ... }
  // discoverPeers() { ... }

  connectToPeer(host, port) {
    const socket = net.connect(port, host, () =>
      p2p.connect(socket, (err, conn) => {
        if (err) {
          throw err;
        } else {
          this.initConnection.call(this, conn);
        }
      })
    );
  }

  closeConnection() {
    p2p.close(err => {
      throw err;
    })
  }
// }

// module.exports = PeerToPeer;

同伴消息:确定谁拥有最新的区块链

Blockchain.js

// const wrtc = require('wrtc');
// const Exchange = require('peer-exchange');
// const p2p = new Exchange(...);
// const net = require("net");
const messageType = {
  REQUEST_LATEST_BLOCK: 0,
  RECEIVE_LATEST_BLOCK: 1,
  REQUEST_BLOCKCHAIN: 2,
  RECEIVE_BLOCKCHAIN: 3,
};
const {
  REQUEST_LATEST_BLOCK,
  RECEIVE_LATEST_BLOCK,
  REQUEST_BLOCKCHAIN,
  RECEIVE_BLOCKCHAIN,
  REQUEST_TRANSACTIONS,
  RECEIVE_TRANSACTIONS
} = messageType;

// class PeerToPeer { ... }
// module.exports = PeerToPeer;

class Messages {
  static getLatestBlock() {
    return {
      type: REQUEST_LATEST_BLOCK
    };
  }

  static sendLatestBlock(block) {
    return {
      type: RECEIVE_LATEST_BLOCK,
      data: block
    };
  }

  static getBlockchain() {
    return {
      type: REQUEST_BLOCKCHAIN
    };
  }

  static sendBlockchain(blockchain) {
    return {
      type: RECEIVE_BLOCKCHAIN,
      data: blockchain
    };
  }
}

逻辑图

这里写图片描述

P2p.js

// const wrtc = require('wrtc');
// const Exchange = require('peer-exchange');
// const p2p = new Exchange(...);
// const net = require("net");
// const messageType = { ... };
// const { ... } = messageType;

// class PeerToPeer {
  // constructor(blockchain) { ... }
  // startServer(port) { ... }
  // discoverPeers() { ... }
  // connectToPeer(host, port) { ... }
  // closeConnection() { ... }

  broadcastLatest() {
    this.broadcast(Messages.sendLatestBlock(this.blockchain.latestBlock));
  }

  broadcast(message) {
    this.peers.forEach(peer => this.write(peer, message));
  }

  write(peer, message) {
    peer.write(JSON.stringify(message));
  }

  initConnection(connection) {
    this.peers.push(connection);
    this.initMessageHandler(connection);
    this.initErrorHandler(connection);
    this.write(connection, Messages.getLatestBlock());
  }

  initMessageHandler(connection) {
    connection.on("data", data => {
      const message = JSON.parse(data.toString("utf8"));
      this.handleMessage(connection, message);
    });
  }

  initErrorHandler(connection) {
    connection.on("error", err => {
      throw err;
    });
  }

  handleMessage(peer, message) {
    switch (message.type) {
      case REQUEST_LATEST_BLOCK:
        this.write(peer, Messages.sendLatestBlock(this.blockchain.latestBlock));
        break;
      case REQUEST_BLOCKCHAIN:
        this.write(peer, Messages.sendBlockchain(this.blockchain.get()));
        break;
      case RECEIVE_LATEST_BLOCK:
        this.handleReceivedLatestBlock(message, peer);
        break;
      case RECEIVE_BLOCKCHAIN:
        this.handleReceivedBlockchain(message);
        break;
      default:
        throw "Received invalid message.";
    }
  }
// }

// module.exports = PeerToPeer;
// class Messages { ... }

这里写图片描述

P2p.js

// const wrtc = require('wrtc');
// const Exchange = require('peer-exchange');
// const p2p = new Exchange(...);
// const net = require("net");
// const messageType = { ... };
// const { ... } = messageType;

// class PeerToPeer {
  // constructor(blockchain) { ... }
  // startServer(port) { ... }
  // discoverPeers() { ... }
  // connectToPeer(host, port) { ... }
  // closeConnection() { ... }
  // broadcastLatest() { ... }
  // broadcast(message) { ... }
  // write(peer, message) { ... }
  // initConnection(connection) { ... }
  // initMessageHandler(connection) { ... }
  // initErrorHandler(connection) { ... }
  // handleMessage(peer, message) { ... }

  handleReceivedLatestBlock(message, peer) {
    const receivedBlock = message.data;
    const latestBlock = this.blockchain.latestBlock;

    if (latestBlock.hash === receivedBlock.previousHash) {
      try {
        this.blockchain.addBlock(receivedBlock);
      } catch(err) {
        throw err;
      }
    } else if (receivedBlock.index > latestBlock.index) {
      this.write(peer, Messages.getBlockchain());
    } else {
      // Do nothing.
    }
  }
// }

// module.exports = PeerToPeer;
// class Messages { ... }

这里写图片描述

P2p.js

handleReceivedLatestBlock(message, peer) {
    // if (latestBlock.hash === receivedBlock.previousHash) {
    // ...
    } else if (receivedBlock.index > latestBlock.index) {
      this.write(peer, Messages.getBlockchain());
    } else {
      // Do nothing.
    }
  }

  handleReceivedBlockchain(message) {
    const receivedChain = message.data;

    try {
      this.blockchain.replaceChain(receivedChain);
    } catch(err) {
      throw err;
    }
  }

这里写图片描述

 isValidChain(chain) {
    if (JSON.stringify(chain[0]) !== JSON.stringify(Block.genesis)) {
      return false;
    }

    const tempChain = [chain[0]];
    for (let i = 1; i < chain.length; i = i + 1) {
      if (this.isValidNextBlock(chain[i], tempChain[i - 1])) {
        tempChain.push(chain[i]);
      } else {
        return false;
      }
    }
    return true;
  }

  isChainLonger(chain) {
    return chain.length > this.blockchain.length;
  }

  replaceChain(newChain) {
    if (this.isValidChain(newChain) && this.isChainLonger(newChain)) {
      this.blockchain = JSON.parse(JSON.stringify(newChain));
    } else {
      throw "Error: invalid chain";
    }
  }

这里写图片描述

这里写图片描述

终端演示

安装命令行工具

npm install blockchain-cli -g


blockchain


blockchian ->后面输入blockchain或者bc查看创始区块结构。

创世区块
这里写图片描述

  • Index (Block #): 第几个区块? (创世区块链的索引为0)
  • Hash: 当前区块的hash值
  • Previous Hash: 上一个区块的hash值
  • Timestamp: 当前区块创建时的时间戳
  • Data: 存储在当前区块上的交易信息
  • Nonce: 在找到有效区块之前,我们经历的迭代次数

mine data数据

这里写图片描述

创建好了第一个区块


Hash是怎么计算的?

Hash值是一个十六进制固定长度为64位的唯一的标识。

hash值是由index, previous block hash, timestamp, block data, 和 nonce 作为输入数据计算而得。

CryptoJS.SHA256(index + previousHash + timestamp + data + nonce)

四个前导0是有效散列的最低要求。 所需的前导0的数量称为难度

下面的方法验证hash难度是否有效。

function isValidHashDifficulty(hash, difficulty) {
  for (var i = 0, b = hash.length; i < b; i ++) {
      if (hash[i] !== '0') {
          break;
      }
  }
  return i >= difficulty;
}

nonce是一个用来找到满足条件的hash值的数字。

let nonce = 0;
let hash;
let input;
while(!isValidHashDifficulty(hash)) {     
  nonce = nonce + 1;
  input = index + previousHash + timestamp + data + nonce;
  hash = CryptoJS.SHA256(input)
}

nonce值一直迭代,直到hash值有效为止。在我们案例中一个有效的hash值是最少有4个前导0。找到nonce值以满足合适条件的hash值的过程就叫做挖矿

随着难度的增加,可能的有效散列数减少。 使用较少可能的有效散列,需要更多的处理能力才能找到有效的散列。

学习参考链接

猜你喜欢

转载自blog.csdn.net/wtdask/article/details/81903953