Использование bitgo-utxo-lib для создания мультиподписного кошелька/адреса для Zcash, также известного как ZEC.

В этой статье будет показано, как создать функциональный адрес ZCash с мультиподписью, используя модуль Node.js NPM bitgo-utxo-lib. Кошельки на основе мультиподписи обеспечивают дополнительный уровень безопасности по сравнению с обычными кошельками на основе одной подписи. Функциональность гарантирует, что в подписании транзакции для расходования средств, хранящихся на счете, участвует как минимум более 1 стороны. В этом руководстве основное внимание уделяется разработке оффчейн-кошелька, в основном известного как управление внешним кошельком, чтобы избежать использования демонов полного узла для достижения этой цели. Мы расскажем, как создать учетную запись или адрес с мультиподписью 2 из 3, что подразумевает, что из 3 сторон как минимум 2 стороны должны подписать транзакцию, чтобы потратить средства, хранящиеся на этой учетной записи / адресе.

Предпосылки

Вам необходимо иметь базовые знания о запуске Node.js и использовании модулей npm. Итак, чтобы перечислить их, вам нужно:

  • Node.js (выше v8)
  • Редактор кода VS или, может быть, какой-нибудь редактор кода

Начиная

Предполагая, что вы выполнили вышеуказанные шаги, давайте двигаться дальше. Прежде всего создайте каталог, инициализируйте его проектом npm по умолчанию и установите модули bitgo-utxo-lib и bitcoinjs-lib в зависимостях проекта. Откройте окно терминала (у меня Ubuntu) и запустите:

$ mkdir multisig-zec/ && cd ./multisig-zec
$ npm init -y
$ npm install bitgo-utxo-lib bitcoinjs-lib --save

На момент написания этой статьи использовались следующие версии (package.json проекта):

"dependencies": {
"bitcoinjs-lib": "^4.0.2",
"bitgo-utxo-lib": "^1.2.1"
}

Затем создайте новый файл с именем index.js в текущем рабочем каталоге. Начните с импорта обоих модулей в код, как показано ниже:

let bitcoinjs = require('bitcoinjs-lib');
let bitgoUtxoLib = require('bitgo-utxo-lib');

bitgo-utxo-lib — это модуль npm, опубликованный командой Bitgo (большой их фанаткой), изначально являвшейся ответвлением bitcoinjs-lib. А bitcoinjs-lib — это библиотека с открытым исходным кодом, которая позволяет нам беспрепятственно работать с большинством криптовалют на основе UTXO. Возвращаясь к тому, где мы были, следующим шагом будет создание 3 случайных ECPair с использованием эталонного объекта bitgoUtxoLib, как показано ниже:

let ecPair1 = bitgoUtxoLib.ECPair.makeRandom({ network: bitgoUtxoLib.networks.zcash });
let ecPair2 = bitgoUtxoLib.ECPair.makeRandom({ network: bitgoUtxoLib.networks.zcash });
let ecPair3 = bitgoUtxoLib.ECPair.makeRandom({ network: bitgoUtxoLib.networks.zcash });

Здесь мы создали 3 случайных ECPair, используя эталонный объект, а сетевая часть в приведенном выше коде указывает сетевую совместимость ZEC созданных нами ECPair. В нашем случае мы создаем ECPair, совместимый с mainnet, если вы хотите создать ECPair, совместимый с testnet, просто замените bitgoUtxoLib.networks.zcashрасстаться сbitgoUtxoLib.networks.zcashTest

Теперь следующим шагом будет извлечение общедоступной части ECPair путем получения publicKey в формате буфера, как показано ниже:

const keyPairs = [
ecPair1.getPublicKeyBuffer(), 
ecPair2.getPublicKeyBuffer(),
ecPair3.getPublicKeyBuffer()
];

Это вернет нам массив publicKeyBuffer, соответствующий ECPair, который мы создали на предыдущих шагах. Теперь следующие 2 шага включают использование bitcoinjs-lib для создания экземпляра с несколькими подписями, а затем создание хэша скрипта поверх объекта экземпляра с несколькими подписями для дальнейшего извлечения общедоступного адреса, как показано ниже:

// Create a multisig script object
const p2ms = bitcoinjs.payments.p2ms({ m: 2, pubkeys: keyPairs, 
network: bitgoUtxoLib.networks.zcash });
const p2sh = bitcoinjs.payments.p2sh({ redeem: p2ms, network: bitgoUtxoLib.networks.zcash });

Теперь, когда у нас есть объект P2SH, совместимый с Zcash, мы извлечем необходимую информацию из экземпляра P2SH, такую ​​как публичный адрес, redeemScript (который необходим, когда вы создаете транзакцию, чтобы потратить средства, заблокированные в этой учетной записи) и сведения о подписавшемся (Очень важные данные). Ниже приведен код для извлечения публичного адреса и redeemScript:

const publicAddress = bitgoUtxoLib.address.fromOutputScript(p2sh.output, bitgoUtxoLib.networks.zcash);
const redeemScript = p2sh.redeem.output.toString('hex');
console.log('Multisig Address : ', publicAddress); //address starting with t
console.log('Redeem Script : ', redeemScript); 

Не забудьте сохранить вышеуказанные данные, так как без redeemScript вы не сможете потратить средства внутри (хотя их можно восстановить с помощью созаемщиков). Теперь важный шаг для сохранения данных, связанных с ECPair, которые мы создали выше, поскольку закрытые ключи, соответствующие созданным выше ECPair, будут использоваться для подписи транзакции с мультиподписью, и вы всегда можете сгенерировать тот же адрес с мультиподписью, когда у вас есть открытые ключи со-подписанты (мы создали выше или могут быть уже существующими) в том же порядке.

console.log('** Wallet 1 details : ', {
publicKey: ecPair1.getPublicKeyBuffer().toString('hex'),
privateKey: ecPair1.toWIF(),
publicAddress: ecPair1.getAddress()
});
console.log('** Wallet 2 details : ', {
publicKey: ecPair2.getPublicKeyBuffer().toString('hex'),
privateKey: ecPair2.toWIF(),
publicAddress: ecPair2.getAddress()
});
console.log('** Wallet 3 details : ', {
publicKey: ecPair3.getPublicKeyBuffer().toString('hex'),
privateKey: ecPair3.toWIF(),
publicAddress: ecPair3.getAddress()
});

Сохраните приведенный выше вывод в безопасном месте, о котором вы можете подумать (если вы используете адрес для хранения крупных средств). Весь код при установке будет выглядеть примерно так:

let bitcoinjs = require('bitcoinjs-lib');
let bitgoUtxoLib = require('bitgo-utxo-lib');
let ecPair1 = bitgoUtxoLib.ECPair.makeRandom({ network: bitgoUtxoLib.networks.zcash });
let ecPair2 = bitgoUtxoLib.ECPair.makeRandom({ network: bitgoUtxoLib.networks.zcash });
let ecPair3 = bitgoUtxoLib.ECPair.makeRandom({ network: bitgoUtxoLib.networks.zcash });
const keyPairs = [ecPair1.getPublicKeyBuffer(), ecPair2.getPublicKeyBuffer(), ecPair3.getPublicKeyBuffer()];
const p2ms = bitcoinjs.payments.p2ms({ m: 2, pubkeys: keyPairs, network: bitgoUtxoLib.networks.zcash });
const p2sh = bitcoinjs.payments.p2sh({ redeem: p2ms, network: bitgoUtxoLib.networks.zcash });
const publicAddress = bitgoUtxoLib.address.fromOutputScript(p2sh.output, bitgoUtxoLib.networks.zcash);
const redeemScript = p2sh.redeem.output.toString('hex');
console.log('Multisig Address : ', publicAddress);
console.log('Redeem Script : ', redeemScript);
console.log('** Wallet 1 details : ', {
publicKey: ecPair1.getPublicKeyBuffer().toString('hex'),
privateKey: ecPair1.toWIF(),
publicAddress: ecPair1.getAddress()
});
console.log('** Wallet 2 details : ', {
publicKey: ecPair2.getPublicKeyBuffer().toString('hex'),
privateKey: ecPair2.toWIF(),
publicAddress: ecPair2.getAddress()
});
console.log('** Wallet 3 details : ', {
publicKey: ecPair3.getPublicKeyBuffer().toString('hex'),
privateKey: ecPair3.toWIF(),
publicAddress: ecPair3.getAddress()
});

Лучшая часть этого кода заключается в том, что его можно использовать полностью в автономном режиме и выполнять изолированным методом, чтобы обеспечить максимальную конфиденциальность и безопасность вашей конфиденциальной информации. Вы также можете клонировать/форкнуть мой репозиторий github: https://github.com/mannutech/medium-learning/, где я также буду продолжать загружать новые уроки.

В следующей статье будет рассказано, как создать мультиподписной адрес из существующих строк publicKey в ZEC. Следите за новыми репортажами.

БОНУСНЫЕ СТАТЬИ:

Ссылки на изображения: