Как создать собственную криптовалюту с помощью JavaScript

В настоящее время существует множество способов отправить кому-то деньги в цифровом виде. Большинство способов — через банк или несколько кошельков, но в последнее время стало популярным использование криптовалюты.

Криптовалюта — отличный способ анонимно отправлять деньги другим людям. Еще одним преимуществом криптовалют является то, что их сеть децентрализована, что означает, что никто не просматривает транзакцию и нет посредников. Некоторые люди думают, что это плохо, потому что большинство мошенников работают с криптовалютами, но некоторые думают, что это еще один шаг к конфиденциальности.

Сегодня мы собираемся создать криптовалюту с помощью 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 класса

Основными свойствами транзакции будут amountsenderPublicKey и 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, чтобы взглянуть на код.

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *