PBFT的数学证明 在实际的拜占庭容错中,如果N = 3F + 1,N个节点的系统可以容忍F个故障节点。 实际拜占庭容错系统中的每个决策都需要2F + 1批准,其中Fare是故障节点。 我们现在将在数学上证明上述两个定义,它们是彼此的推论。以下计算是斯坦福大学笔记中数学的简化。 分布式系统的两个重要特性是活跃性和安全性。 活跃性 活跃性是系统继续运行时在分布式系统环境中使用的术语。这意味着即使出现一些错误,系统也不会停止运行。在区块链的情况下,活跃意味着系统将继续向链中添加新的区块,并且在任何时候系统都不会停止工作。 安全性 当系统收敛于单个决策时,安全性是分布式系统环境中使用的术语。在分布式系统中,节点可能会分成两个决策或进一步拆分,分布式系统的安全性确保了即使存在故障节点,网络也会在所有可靠节点上以单个决策结束。 证明 非拜占庭式故障 给定网络中的N个节点,具有f个故障节点,保证活跃性和安全性所需的仲裁大小Q是多少? 仲裁定义为网络正常运行和做出有效决策所需的最小节点数。仲裁由诚实的节点组成。 活跃度 为了避免网络停止,必须至少存在一个非故障节点。因此,为了活跃度: Q <= N - f 安全度 为了避免网络分裂成多个决策,大多数决策者应该在线。我们需要一个诚实的多数,仲裁大小应该大于节点总数的一半,以便我们做出有利于我们的决定。 因此,为了安全: Q > N/2 2Q - N > 0 通过梳理我们得到的两个条件, N < 2Q <=2(N-f) f < N/2 N > 2f
因此,对于非拜占庭式故障
拜占庭式故障
// EDDSA allows us to create keypairs
// It is collection of cryptographic algorithms that are used to create keypairs
const EDDSA = require("elliptic").eddsa;
// ed25519 allows us to create key pair from secret
const eddsa = new EDDSA("ed25519");
// uuid/v1 creates timestamp dependent ids
const uuidV1 = require("uuid/v1");
// used for hashing data to 256 bits string
const SHA256 = require("crypto-js/sha256");
class ChainUtil {
// a static function to return keypair generated using a secret phrase
static genKeyPair(secret) {
return eddsa.keyFromSecret(secret);
}
// returns ids used in transactions
static id() {
return uuidV1();
}
// hashes any data using SHA256
static hash(data) {
return SHA256(JSON.stringify(data)).toString();
}
// verifies the signed hash by decrypting it with public key
// and matching it with the hash
static verifySignature(publicKey, signature, dataHash) {
return eddsa.keyFromPublic(publicKey).verify(dataHash, signature);
}
}
module.exports = ChainUtil;
pbft_chain_util.js
事务类 接下来,我们将创建一个事务类。在项目文件夹中创建文件transaction.js。此项目中的事务将包含以下属性: · id - 用于识别 · from - 发件人的地址 · input - 一个进一步包含要存储的数据和时间戳的对象 · hash - 输入的SHA256 · signature - 发件人签名的哈希 在文件中创建一个类Transaction并将其导出。 // Import the ChainUtil class used for hashing and verification const ChainUtil = require("./chain-util"); class Transaction { // the wallet instance will be passed as a parameter to the constructor // along with the data to be stored. constructor(data, wallet) { this.id = ChainUtil.id(); this.from = wallet.publicKey; this.input = { data: data, timestamp: Date.now() }; this.hash = ChainUtil.hash(this.input); this.signature = wallet.sign(this.hash); } // this method verifies wether the transaction is valid static verifyTransaction(transaction) { return ChainUtil.verifySignature( transaction.from, transaction.signature, ChainUtil.hash(transaction.input) ); } } module.exports = Transaction; pbft-transaction.js 钱包类 接下来是钱包。钱包持有公钥和密钥对。它还负责签署数据哈希并创建签名事务。 在项目目录中创建文件wallet.js。添加一个类Wallet并将其导出。 // Import the ChainUtil class used for hashing and verification const ChainUtil = require("./chain-util"); // Import transaction class used for creating transactions const Transaction = require("./transaction"); class Wallet { // The secret phase is passed an argument when creating a wallet // The keypair generated for a secret phrase is always the same constructor(secret) { this.keyPair = ChainUtil.genKeyPair(secret); this.publicKey = this.keyPair.getPublic("hex"); } // Used for prining the wallet details toString() { return `Wallet - publicKey: ${this.publicKey.toString()}`; } // Used for signing data hashes sign(dataHash) { return this.keyPair.sign(dataHash).toHex(); } // Creates and returns transactions createTransaction(data) { return new Transaction(data, this); } // Return public key getPublicKey() { return this.publicKey; } } module.exports = Wallet; pbft-wallet.js 验证者类 由于PBFT是一种许可的区块链一致性算法,我们需要存储每个节点系统中所有节点的地址。我们可以通过选择一个密钥,创建一个钱包,获取其公钥并将该密钥存储到一个文件中来手动执行此操作。当我们运行我们的项目时,它会读取此文件以获取密钥。 但是,不是手动执行此操作,我们可以通过创建类并添加可以返回N个节点的公钥列表的函数来自动执行此操作。 我们将创建一个Validator类,它将生成每个节点都知道的公钥列表。在这个项目中,我们使用了每个节点的密码短语 NODE1,NODE2,NODE3 ...... 这样,我们就可以更容易地创建公钥列表,并使用相同的公钥从命令行创建节点。 // Import the wallet class const Wallet = require("./wallet"); class Validators { // constructor will take an argument which is the number of nodes in the network constructor(numberOfValidators) { this.list = this.generateAddresses(numberOfValidators); } // This function generates wallets and their public key // The secret key has been known for demonstration purposes // Secret will be passed from command line to generate the same wallet again // As a result the same public key will be generatedd generateAddresses(numberOfValidators) { let list = []; for (let i = 0; i < numberOfValidators; i++) { list.push(new Wallet("NODE" + i).getPublicKey()); } return list; } // This function verfies if the passed public key is a known validator or not isValidValidator(validator) { return this.list.includes(validator); } } module.exports = Validators; 注意:密钥不应该公开。只有在演示中我们才使用这样的密钥。在实际项目中,发送注册请求以使节点成为验证者。如果整个网络批准此请求,则该节点将成为验证者,并将公钥添加到列表中。 Config.js文件 网络中的验证者数量可以通过命令行传递,但更容易将其存储在文件中并在需要的地方导入。 创建一个文件config.js并创建三个变量NUMBER_OF_NODES,MIN_APPROVALS和TRANSACTION_THRESHOLD
// Maximum number of transactions that can be present in a block and transaction pool
const TRANSACTION_THRESHOLD = 5;
// total number of nodes in the network
const NUMBER_OF_NODES = 3;
// Minmu number of positive votes required for the message/block to be valid
const MIN_APPROVALS = 2 * (NUMBER_OF_NODES / 3) + 1;
module.exports = {
TRANSACTION_THRESHOLD,
NUMBER_OF_NODES,
MIN_APPROVALS
};
PBFT-config.js
好。本章教程已经结束,下一章节将会展示如何创建区块类内容。 —- 编译者/作者:不详 玩币族申明:玩币族作为开放的资讯翻译/分享平台,所提供的所有资讯仅代表作者个人观点,与玩币族平台立场无关,且不构成任何投资理财建议。文章版权归原作者所有。 |
如何使用node.js语言实现PBFT协议 part2
2019-08-09 不详 来源:网络
相关阅读:
- 【跟着勇哥柒学知识119】DEFI还会不会再次呈现一种爆发式的增长,可能2020-10-26
- 纵览波卡9大热门DeFi , 谁更有潜力?谁可能是坑?2020-10-26
- NFT在DeFi中的未来:与Aavegotchi的Jesse Johnson的对话2020-10-26
- 动画:共享安全(四)2020-10-26
- 光伏新能源板块迎来爆发BVI光伏链借势东风全网为之侧目2020-10-26