Как создать собственную криптовалюту с помощью JavaScript
Криптовалюта — отличный способ анонимно отправлять деньги другим людям. Еще одним преимуществом криптовалют является то, что их сеть децентрализована, а это означает, что никто не контролирует транзакцию и нет посредников. Одни люди думают, что это плохо, потому что большинство мошенников работают с криптовалютами, но для других — это очередной шаг к конфиденциальности.
Сегодня мы собираемся создать криптовалюту с помощью JavaScript. Надеюсь, эта статья даст вам общее представление о том, как создать собственную криптовалюту, и вы сможете продолжить работу над этими навыками для улучшения конфиденциальности своих финансов.
Требования:
Node.js установлен на вашем компьютере
JavaScript. Быстрый старт
Изучите основы JavaScript на практическом примере по созданию веб-приложения
Редактор кода (я предпочитаю Visual Studio Code)
Практическое знание Node
Вы всегда можете обратиться к репозиторию GitHub, если хотите взглянуть на код.
Давайте начнем с создания проекта Node. Перейдите в безопасный каталог и введите следующую команду, чтобы создать новый проект:
JavaScript npm init -y
1 | npm init -y |
Это должно сгенерировать файл package.json. Если файл создан, значит, создался и проект.
Теперь давайте создадим новый файл с именем index.js. Сначала импортируйте crypto пакет, чтобы мы могли иметь дело с хешами в проекте. Пакет crypto помогает нам работать с хешами, подписями и ключами. Он позволяет выполнять криптографическое преобразование в Node.
Это предустановленный пакет с Node, поэтому вам не нужно устанавливать его отдельно:
JavaScript const crypto = require(“crypto”);
1 | const crypto = require(“crypto”); |
Мы будем иметь дело с четырьмя классами. Их названия:
Transaction
Block
Chain
Wallet
Сначала давайте создадим класс Transaction.
Создание класса Transaction
Содержание статьи:
Основными свойствами транзакции будут amount, senderPublicKey и recieverPublicKey. Итак, давайте настроим конструктор, чтобы мы могли использовать этот класс позже:
JavaScript class Transaction { constructor(amount, senderPublicKey, recieverPublicKey) { this.amount = amount; this.senderPublicKey = senderPublicKey; this.recieverPublicKey = recieverPublicKey; } }
1234567 | class Transaction { constructor(amount, senderPublicKey, recieverPublicKey) { this.amount = amount; this.senderPublicKey = senderPublicKey; this.recieverPublicKey = recieverPublicKey; }} |
Нам также нужен метод для преобразования объекта класса в строку, чтобы преобразовать ее в хеш. Итак, создадим функцию для преобразования объекта в строку для дальнейшего использования:
JavaScript toString() { return JSON.stringify(this); }
123 | toString() { return JSON.stringify(this);} |
Ваш полный класс Transaction должен выглядеть следующим образом:
JavaScript 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); } }
123456789101112 | 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:
JavaScript class Block { constructor(previousHash, transaction, timestamp = Date.now()) { this.previousHash = previousHash; this.transaction = transaction; this.timestamp = timestamp; } }
1234567 | class Block { constructor(previousHash, transaction, timestamp = Date.now()) { this.previousHash = previousHash; this.transaction = transaction; this.timestamp = timestamp; }} |
В блоке у нас будет previousHash (хэш предыдущего блока в цепочке), transaction (объект класса Transaction) и timestamp (время создания блока). Теперь давайте создадим функцию для генерации хэша блока:
JavaScript getHash() { const json = JSON.stringify(this); const hash = crypto.createHash(“SHA256”); hash.update(json).end(); const hex = hash.digest(“hex”); return hex; }
1234567 | 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. Наконец, мы создаем hash.digest и возвращаем его. Теперь снова мы создаем функцию для преобразования объекта блока в JSON:
JavaScript. Быстрый старт
Изучите основы JavaScript на практическом примере по созданию веб-приложения
JavaScript toString() { JSON.stringify(this); }
123 | toString() { JSON.stringify(this);} |
Ваш полный класс Block теперь должен выглядеть так:
JavaScript 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); } }
1234567891011121314151617 | 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, чтобы все блоки были собраны в одном месте.
Поскольку нам нужно инициализировать цепочку только один раз, а не несколько, мы сразу же инициализируем ее в самом классе:
JavaScript class Chain { static instance = new Chain(); }
123 | class Chain { static instance = new Chain();} |
Давайте настроим конструктор так, чтобы у нас был готов первый блок в цепочке при каждом запуске программы. Также объявим массив, в котором будут размещены наши блоки.
Мы делаем так, чтобы устранить любые ошибки в проекте, потому что каждый блок зависит от предыдущего блока, и поэтому нам сначала нужно инициализировать фиктивный блок:
JavaScript constructor() { this.chain = [new Block(“”, new Transaction(100, “temp”, “temp”))]; }
123 | constructor() { this.chain = [new Block(“”, new Transaction(100, “temp”, “temp”))];} |
Теперь нам нужна функция для получения последнего хэша цепочки, чтобы использовать информацию в новых блоках:
JavaScript getPreviousBlockHash() { // sending the entire block itself return this.chain[this.chain.length – 1].getHash(); }
1234 | getPreviousBlockHash() { // sending the entire block itself return this.chain[this.chain.length – 1].getHash(); } |
Затем давайте создадим функцию, которая фактически создаст и вставит блок в наш цепочный массив:
JavaScript 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); } }
12345678910111213 | 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); }} |
Здесь мы сначала используем функцию createVerify из пакета crypto для проверки хэшей с открытыми ключами. Затем мы используем данные из JSON конкретной транзакции и, наконец, проверяем открытый ключ отправителя и подпись.
Это вернет логическое значение, которое мы можем использовать, чтобы проверить, была ли проверка успешной или неудачной. Если проверка прошла успешно, мы просто создаем новый блок и добавляем его в массив цепочки. Ваш класс Chain должен выглядеть так:
JavaScript 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); } } }
123456789101112131415161718192021222324 | 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
Давайте создадим кошельки, которые пользователи смогут использовать для отправки криптовалюты другим людям. У каждого криптокошелька есть пара ключей: открытый и закрытый ключи. Закрытые ключи используются для создания новых транзакций (например, для отправки криптовалюты), а открытый ключ используется для их проверки и получения криптовалют.
Давайте сначала настроим конструктор, чтобы мы могли сгенерировать пару ключей, как только кошелек будет инициализирован:
JavaScript 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; }
123456789 | 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 для ключей. Это хорошо известный формат, который может быть сохранен на компьютере пользователя. Алгоритм RSA позволяет создавать открытые и закрытые ключи. Теперь давайте создадим функцию, которая поможет нам отправлять криптовалюту на другие кошельки в сети:
JavaScript 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); }
12345678910111213 | 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.
Тестирование
Теперь, когда все готово, вы можете протестировать приложение, создав кошельки и транзакции:
JavaScript 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);
123456789 | 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); |
В приведенном выше коде я создал кошельки со случайными именами, а затем отправил деньги из одного кошелька в другой и, наконец, зарегистрировал цепочку, чтобы посмотреть, как она выглядит. Моя цепочка выглядела так (ваша может отличаться из-за разных хешей):
JavaScript 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 } ] }
123456789101112131415161718192021222324 | 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, чтобы взглянуть на код. Если вы хотите поэкспериментировать еще больше, я бы порекомендовал включить в этот проект систему баланса кошелька и систему майнинга.
Автор: Atharva Deosthale
Источник: webformyself.com