如今,有很多方法可以以数字方式向他人汇款。大多数方法是通过银行或一些钱包,但最近,使用加密货币已经变得很流行。
加密货币是一种匿名向他人汇款的好方法。加密货币的另一个优点是其网络是去中心化的,这意味着没有人看管交易,也没有中间人。有些人认为这不是好事,因为大多数骗子都在加密货币上操作,但有些人认为这是向隐私迈出的又一步。
今天,我们将使用JavaScript创建一个加密货币。希望这篇文章能让你对如何创建自己的加密货币有一个基本的概念,你可以继续研究这些技能,以改善你财务方面的隐私。
要求
- 在你的机器上安装Node.js
- 一个代码编辑器--我更喜欢Visual Studio Code
- 对Node的工作知识
如果你想看一下代码,你可以随时参考GitHub仓库。
开始工作
让我们从创建一个Node项目开始。导航到一个安全的目录,并输入以下命令来创建一个新项目。
npm init -y
这应该为你生成一个package.json 文件。如果该文件被创建,那么该项目就被创建了。
现在让我们创建一个新的文件,名为index.js 。首先,导入 crypto包,这样我们就可以在我们的项目中处理哈希值了。crypto 包帮助我们处理哈希值、签名和密钥。它允许我们在Node中进行加密转换。
这是一个与Node一起预装的软件包,所以你不需要单独安装它。
const crypto = require("crypto");
我们将在这些项目中处理四个类。它们是。
TransactionBlockChainWallet
首先让我们创建Transaction 类。
创建Transaction 类
一个事务的基本属性将是amount ,senderPublicKey ,和recieverPublicKey 。因此,让我们为这些属性设置一个构造函数,以便我们以后可以使用这个类。
class Transaction {
constructor(amount, senderPublicKey, recieverPublicKey) {
this.amount = amount;
this.senderPublicKey = senderPublicKey;
this.recieverPublicKey = recieverPublicKey;
}
}
我们还需要一个方法将该类的对象转换为字符串,以便将其转换为哈希值。因此,我们将创建一个函数,将对象转换为字符串,以便以后使用。
toString() {
return JSON.stringify(this);
}
你的完整的Transaction 类应该如下所示。
class Transaction {
constructor(amount, senderPublicKey, recieverPublicKey) {
this.amount = amount;
this.senderPublicKey = senderPublicKey;
this.recieverPublicKey = recieverPublicKey;
}
// convert the data of the class to json so that
// it can be converted into a hash
toString() {
return JSON.stringify(this);
}
}
现在我们可以将这些事务存储在一个块内,接下来我们将创建这个块。
创建Block 类
术语 "区块链 "的意思和它听起来一样--一个区块链。区块链是区块(包含交易)的集合,它们彼此相连,这样我们就可以系统地访问它们。
为了开始工作,让我们来设置我们将在Block 类中使用的构造函数和属性。
class Block {
constructor(previousHash, transaction, timestamp = Date.now()) {
this.previousHash = previousHash;
this.transaction = transaction;
this.timestamp = timestamp;
}
}
在一个区块中,我们将有previousHash (链上前一个区块的哈希值),transaction (Transaction 类的对象),和timestamp (区块创建的时间)。
现在,让我们创建一个函数来生成区块的哈希值。
getHash() {
const json = JSON.stringify(this);
const hash = crypto.createHash("SHA256");
hash.update(json).end();
const hex = hash.digest("hex");
return hex;
}
首先,我们将该对象转换为JSON格式。然后,我们创建一个SHA256 散列,这是一种不能被解密的散列方法。我们以后使用哈希值来验证区块;一旦哈希值被验证,它就为区块提供了合法性。
接下来,我们添加JSON作为数据,使其被转换为SHA256 散列。最后,我们为哈希值创建一个HEX digest,并将其返回。
现在,我们再次创建一个函数,将块对象转换成JSON。
toString() {
JSON.stringify(this);
}
你的完整的Block 类现在应该看起来像这样。
class Block {
constructor(previousHash, transaction, timestamp = Date.now()) {
this.previousHash = previousHash;
this.transaction = transaction;
this.timestamp = timestamp;
}
getHash() {
const json = JSON.stringify(this);
const hash = crypto.createHash("SHA256");
hash.update(json).end();
const hex = hash.digest("hex");
return hex;
}
toString() {
return JSON.stringify(this);
}
}
现在让我们来创建Chain 类。
创建Chain 类
现在我们已经准备好了我们的Block 类,我们可以在一个Chain 中填写这些块。一条链保存着区块链上发生的每一个区块,或每一笔交易。正如之前所讨论的,区块链包含了所有相互链接的区块,我们的项目需要一个Chain 类,以便将所有的区块都放在一个地方。
因为我们只需要初始化一次链,而不是多次,所以我们将在类本身中立即初始化它。
class Chain {
static instance = new Chain();
}
让我们来设置我们的构造函数,以便在程序运行时,我们在链中准备好第一个块。这也将设置放置块的数组。
我们这样做是为了消除我们项目中的任何错误,因为我们在部分代码中依赖前一个块,所以我们需要一开始就初始化一个假块。
constructor() {
this.chain = [new Block("", new Transaction(100, "temp", "temp"))];
}
现在,我们需要一个函数来获取链的最后一个哈希值,以便在新的块中使用这些信息。
getPreviousBlockHash() {
// sending the entire block itself
return this.chain[this.chain.length - 1].getHash();
}
接下来,让我们创建一个函数,实际创建一个区块并将其插入我们的链数组中。
insertBlock(transaction, senderPublicKey, sig) {
// create verifier
const verify = crypto.createVerify("SHA256");
// add the transaction JSON
verify.update(transaction.toString());
// Verify it with the sender's public key
const isValid = verify.verify(senderPublicKey, sig);
if (isValid) {
const block = new Block(this.getPreviousBlockHash(), transaction);
console.log("Block added", block.toString());
this.chain.push(block);
}
}
在这里,我们首先使用crypto 包中的createVerify 函数来验证与公钥的哈希值。然后我们使用特定交易的JSON数据,最后通过提供发送者的公钥和签名来验证。
这将返回一个布尔值,我们可以用它来检查验证是否成功或失败。如果验证成功,我们只需用这些信息创建一个新的区块并将其添加到链数组中。
现在你的Chain 类应该看起来像这样。
class Chain {
static instance = new Chain();
// initializing our chain with no records
constructor() {
this.chain = [new Block("", new Transaction(100, "temp", "temp"))];
}
getPreviousBlockHash() {
// sending the entire block itself
return this.chain[this.chain.length - 1].getHash();
}
insertBlock(transaction, senderPublicKey, sig) {
// create verifier
const verify = crypto.createVerify("SHA256");
// add the transaction JSON
verify.update(transaction.toString());
// Verify it with the sender's public key
const isValid = verify.verify(senderPublicKey, sig);
if (isValid) {
const block = new Block(this.getPreviousBlockHash(), transaction);
console.log("Block added", block.toString());
this.chain.push(block);
}
}
}
创建Wallet 类
现在让我们来创建钱包,用户可以用它来发送加密货币给其他人。每个加密货币钱包都有一对密钥:一个公钥和一个私钥。私钥用于创建新的交易(例如,发送加密货币),公钥用于验证交易和接收加密货币。
让我们首先设置构造函数,这样我们就可以在钱包启动后立即生成一对密钥。
constructor() {
const keys = crypto.generateKeyPairSync("rsa", {
modulusLength: 2048,
publicKeyEncoding: { type: "spki", format: "pem" },
privateKeyEncoding: { type: "pkcs8", format: "pem" },
});
this.privateKey = keys.privateKey;
this.publicKey = keys.publicKey;
}
在这里,我们使用PEM 格式的钥匙。这是一种众所周知的格式,可以保存在用户的PC上。RSA 算法允许我们创建公钥和私钥。
现在让我们创建一个函数,它将帮助我们将加密货币发送到网络上的其他钱包。
send(amount, recieverPublicKey) {
const transaction = new Transaction(
amount,
this.publicKey,
recieverPublicKey
);
const shaSign = crypto.createSign("SHA256");
// add the transaction json
shaSign.update(transaction.toString()).end();
// sign the SHA with the private key
const signature = shaSign.sign(this.privateKey);
Chain.instance.insertBlock(transaction, this.publicKey, signature);
}
在上面的代码中,我们把amount 和recieverPublicKey 作为参数,并使用这些信息从Transaction 类中创建一个新对象。然后我们创建交易的哈希值,并用私钥签名。最后,我们使用insertBlock 函数将其添加到链中。
测试东西
现在一切都准备好了,你可以通过创建钱包和使用它们创建交易来进行测试。
const itachi = new Wallet();
const madara = new Wallet();
const orochimaru = new Wallet();
itachi.send(50, madara.publicKey);
madara.send(23, orochimaru.publicKey);
orochimaru.send(5, madara.publicKey);
console.log(Chain.instance);
在上面的代码中,我创建了名字随机的钱包(不完全是随机的,它们是火影忍者中的反派),然后从一个钱包向另一个钱包汇款,最后记录下链的情况。
对我来说,我的链看起来是这样的(你的可能会因为不同的哈希值而有所不同)。
Chain {
chain: [
Block {
previousHash: '',
transaction: [Transaction],
timestamp: 1634561976555
},
Block {
previousHash: 'c22300510c923a8ebf4d804f6edb4370731fcfd58f938d255852b4ea2744f20e',
transaction: [Transaction],
timestamp: 1634561976623
},
Block {
previousHash: '1799ab15685e086cdb539e1851a759c713b3f71205664286cd4024c9f74d2a69',
transaction: [Transaction],
timestamp: 1634561976628
},
Block {
previousHash: '1eb1f51c1b94a18f1c35e0cd81245ea6c69bac0100573cb76f3dac8026132597',
transaction: [Transaction],
timestamp: 1634561976629
}
]
}
接下来是什么?
这只是使用JavaScript创建加密货币的基础知识。你不应该在生产中使用这个,因为加密货币涉及很多不同的东西,比如挖矿,而且涉及很多安全问题。
如果你在什么地方卡住了,你可以随时访问我的GitHub仓库,看看代码。
如果你想做更多的实验,我建议在这个项目中加入一个钱包余额系统和挖矿系统。