



В настоящее время существует множество способов отправить кому-то деньги в цифровом виде. Большинство способов — через банк или несколько кошельков, но в последнее время стало популярным использование криптовалюты.
Криптовалюта — отличный способ анонимно отправлять деньги другим людям. Еще одним преимуществом криптовалют является то, что их сеть децентрализована, что означает, что никто не просматривает транзакцию и нет посредников. Некоторые люди думают, что это плохо, потому что большинство мошенников работают с криптовалютами, но некоторые думают, что это еще один шаг к конфиденциальности.
Сегодня мы собираемся создать криптовалюту с помощью JavaScript. Надеюсь, эта статья даст вам общее представление о том, как создать свою собственную криптовалюту, и вы сможете продолжить работу над этими навыками для улучшения конфиденциальности в своих финансах.
Требования
- Node.js установлен на вашем компьютере
- Практическое знание Node
Вы всегда можете обратиться к репозиторию GitHub, если хотите взглянуть на код.
Погнали
Начнем с создания проекта Node. Перейдите в безопасный каталог и введите следующую команду, чтобы создать новый проект:
npm init - y
Это должно сгенерировать для вас файл. Если файл создан, то создается проект.package.json
Теперь давайте создадим новый файл с именем index.js
. Сначала импортируйте пакет crypto
, чтобы мы могли работать с хешами в нашем проекте. Пакет crypto
помогает нам работать с хэшей, подписи и ключей. Это позволяет нам выполнять криптографическое преобразование в Node.
Это предустановленный пакет с Node, поэтому вам не нужно устанавливать его отдельно:
const crypto = require("crypto");
В этих проектах мы будем иметь дело с четырьмя классами:
Transaction
Block
Chain
Wallet
Сначала создадим 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
дайджест для хеша и возвращаем его.
Теперь снова мы создаем функцию для преобразования объекта блока в 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);
}
}
Здесь мы сначала используем createVerify
функцию из crypto
пакета для проверки хэшей с открытыми ключами. Затем мы используем данные из 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
формат ключей. Это хорошо известный формат, который можно сохранить на ПК пользователя. 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, чтобы взглянуть на код.