Глава 7

Интеграция Monero для разработчиков

В этой главе рассмотрены стандарты и протоколы, которые разработчики могут использовать для взаимодействия с Monero и создания новых инструментальных средств. Сначала предлагается ознакомиться с форматами OpenAlias и Monero URI как с эффективными способами представления адресов, а также другими ключевыми подробностями. Оставшаяся часть главы посвящена удалённым вызовам процедур и содержит примеры интеграции на языках C++ и Python.

7.1 OpenAlias: удобные адреса в текстовом формате (для чтения человеком)

Крайне непросто кому-либо, не обладающему фотографической памятью, интуитивно читать и запоминать криптографические адреса. Реальный адрес вроде «123 Main St» или электронный адрес «donate@masteringmonero.com» гораздо проще интерпретировать и запомнить в отличие от адреса Monero, такого как: “45ttEikQEZWN1m7VxaVN9rjQkpSdmpGZ82GwUps66neQ1PqbQM no4wMY8F5jiDt2GoHzCtMwa7PDPJUJYb1GYrMP4CwAwNp”.

Эти криптовалютные адреса содержат множество информации, но они слишком «громоздки» для человека. Фактически существует довольно известная трилемма, известная как Треугольник Зуко, описывающая сложность систем присвоения имён, которые должны соответствовать трём основным критериям: безопасность, децентрализованность, а также понятность для человека.

Адрес Monero, показанный выше, совсем «непонятен для человека», тем не менее он в полной мере соответствует двум остальным критериям. Адрес Monero должен иметь длину по крайней мере 95 символов, что довольно сложно прочитать и практически невозможно запомнить. Определённо, должны существовать способы упрощения написания адресов назначения платежей!

Командой ведущих разработчиков Monero (Monero Core Team) был выпущен стандарт OpenAlias, превращающий Треугольник Зуко в «квадрат» и позволяющий представлять адреса в читаемой человеком форме. Стандарт OpenAlias является текстовой записью DNS в полностью уточнённом имени домена (FQDN). Каждая текстовая запись должна содержать только две части информации: префикс и адрес получателя. Также может быть добавлена пара значений ключей recipient_name, однако это не обязательно.

Типовая текстовая запись OpenAlias выглядит так:

oa1:xmr

recipient_address=45ttEikQEZWN1m7VxaVN9rjQkpSdmpGZ82GwUps66neQ1PqbQMno4wMY8F5jiDt2GoHzCtMwa7PDPJUJYb1GYrMP4CwAwNp

recipient_name=MoneroFFS

Часть oa1:xmr указывает на то, что запись основана на первой версии OpenAlias, а также, что адресом назначения является адрес Monero. Опционально можно указать имя получателя, и в данном случае таким именем является MoneroFFS.

Имя | Размер | Описание – | – | – oa1: | 4 | Запись всегда начинается с oa1:, что означает, что запись соответствует первой версии OpenAlias. При отсутствии этого префикса запись игнорируется, так как она может быть записью SPF или чем-то ещё, до чего нам нет дела. symbol | 3 | Код криптовалюты. Код должен соответствовать правилам ISO 4217: в случае с криптовалютой Monero символом является xmr, а в случае с Bitcoin — btc. recipient_address = address; | 17 + адрес +1 | Адрес получателя. Формат будет следующим: recipient_address=your_address, где your_address будет вашим криптовалютным адресом. В случае с Monero это строка, состоящая из 95 символов. Пары значений ключей отделяются точкой с запятой и, как вариант, пробелом для удобочитаемости. Это ключевое значение ключей необходимо. OpenAlias существует для создания FQDN альтернативных имён для «адреса» любого типа, и это выражается в данном значении. recipient_name = description; | 14 + описание + 1 | Это необязательно, но полезно с точки зрения подтверждения правильного получателя пользователем или же для того, чтобы у пользователя была возможность добавить данные в адресную книгу.

Стандарт OpenAlias может быть расширен разработчиками. Он интуитивно понятен пользователям и обеспечивает возможность взаимодействия между централизованными и децентрализованными доменными системами. Стандарт может использоваться с любой криптовалютой и уже был реализован Monero, Bitcoin (Electrum) и HyperStake.

Рисунок 7.1 > Рисунок 7.1 - Читабельный для пользователя адрес donate.getmonero.org принимается DNS-сервером, который отправляет в ответ адрес для внесения пожертвований 44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A.

7.2 Monero_URI: удобное представление в текстовом формате (для компьютеров)

Стандарт унифицированных идентификаторов ресурса (URI) Monero описывает формат однозначной передачи полей ключевых данных для счетов и транзакций. Эти URI особо удобны с точки зрения торговли, например, для генерирования QR-кодов для проведения платежей.

Синтаксис URI Monero соответствует RFC 3986, и пробелы должны иметь кодировку x-www-urlencoded, то есть %20. Ниже приводится пример URI, где URL представляет собой пример строки, в которой зашифрован запрос платежа размером 0.0413 XMR, отправленный на адрес 4BKq…feW5 за «книгу Mastering Monero».

monero:4BKjy1uVRTPiz4pHyaXXawb82XpzLiowSDd8rEQJGqvN6AD6kWosLQ6VJXW9sghopxXgQSh1RTd54JdvvCRsXiF41xvfeW5?tx_amount=0.0413&tx_description=Mastering%20Monero%20Book

Параметр | Тип | Описание – | – | – address | Строка | Необработанный адрес tx_payment_id | Строка | Предлагаемый ID платежа транзакции (если упоминается) recipient_name | Строка | Предлагаемое контактное имя получателя (если упоминается) tx_amount | Float | Предлагаемая сумма транзакции в атомных единицах валюты tx_description | Строка | Описывает транзакцию, которую необходимо провести

7.3 Monero RPC

Разработчики, занимающиеся интеграцией Monero, могут использовать либо API Monero, написанный на языке C++ (C / C++), либо интерфейс удалённого вызова процедуры (RPC). Методы RPC доступны на любом языке программирования, обеспечивающем возможность создания HTTP запросов, так что мы воспользуемся такой гибкостью и включим пример кода для некоторых общих задач.

Демон-программа Monero (monerod) доступна через RPC и позволяет выполнять ключевые действия, такие как проверка баланса или отправка средств. RPC кошелька Monero (monero-wallet-RPC) позволяет управлять всеми функциями кошелька посредством JSON вызовов.

RPC выражает суммы Monero в «атомных единицах», которыми называют самую малую часть монеты Monero, распознаваемую текущей версией реализации monerod. Преобразование форматов происходит просто по формуле:

1 XMR = 1x10¹² атомных единиц

7.3.1 Инициализация и конфигурация (настройка и безопасность)

Сначала необходимо запустить RPC кошелька Monero. Для этого необходимо указать порт и местоположение файла вашего кошелька:

 $ ./monero-wallet-rpc --rpc-bind-port 18082 --disable-rpc-login --log-level 2 --wallet-file your-wallet-file --prompt-for-password

Если вы хотите использовать удалённый узел, просто необходимо добавить флаг –daemon-address, а за ним указать адрес узла, например:

 --daemon-address node.moneroworld.com:18089

Так как monero-wallet-rpc не связывает ваш IP-адрес с портом по умолчанию, для удалённого подсоединения вам необходимо указать –rpc-bind-ip yourip.

Рекомендуется предпринять несколько мер предосторожности, так как начало какой-либо деятельности с открытым RPC подобно поездке на сафари без каких-либо средств защиты! Перед тем как ваш узел будет открыт, следует убедиться в том, что были заданы имя пользователя и пароль. Если вы будете следовать этим правилам по обеспечению безопасности, ваш API будет защищён.

Флаг –restricted-rpc очень полезен с точки зрения ограничения привилегий RPC и помогает избежать потенциальных ошибок. Например, ограниченный режим гарантирует, что ваш узел не выведет ваших чувствительных для анонимности данных через RPC и не позволит внешним пользователям заниматься майнингом, используя ваши устройства.

7.3.2 Формат JSON RPC

JSON-RPC является лишённым состояний, лёгким протоколом RPC, использующим формат данных JSON RFC 4672. Спецификация, в первую очередь, определяет несколько структур данных, а также правила их обработки. Протокол не зависит от транспортного уровня, что означает, что его функция не связана с лежащим в основе механизмом передачи данных. Таким образом, та же концепция может быть использована в пределах заданного процесса, через сокеты, через HTTP соединения или любой другой канал связи.

Чтобы получить какую-либо информацию через RPC кошелька, необходимо отправить сообщение, используя метод POST. JSON-RPC API принимает сообщения следующего формата:

{ “jsonrpc” : version , “method” : method, “params”: params, “id”: id }

используя выходы, которые описываются:

Поле | Description version | версией протокола JSON-RPC (Monero поддерживает v2.0) method | аявлением функции, которая будет ds params | specify additional information needed for the desired method id | number for tracking responses (integers starting from 0)

7.3.3 Пример вызовов RPC

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

7.3.3.1 Запрос баланса

Баланс кошелька можно запросить, используя метод getbalance:

    $ curl -X POST 127.0.0.1:18082/json_rpc -d '{“jsonrpc”:”2.0”,”id”:”0”,”method”:”getbalance”}' -H 'Content-Type: application/json'

Будут получены два результата: [общий] баланс и unlocked_balance, который включает в себя только те транзакции, которые находятся достаточно «глубоко» в блокчейне, чтобы считаться «безопасными» для траты (например, подтверждённые как доступные после 6 блоков).

    {“id”: “0”,“jsonrpc”: “2.0”, “result”: {  “balance”: 140000000000, “unlocked_balance”: 84000000000} }

В этом случае в кошельке будет 0.14 XMR и только 0.084 XMR будут разблокированными.

7.3.3.2 Запрос адреса

Запрос адреса кошелька.

   $ curl -X POST 127.0.0.1:18082/json_rpc -d '{“jsonrpc”:”2.0”,”id”:”0”,”method”:”getaddress”}' -H 'Content-Type: application/json'

В ответ получаем:

    {“id”: 0,“jsonrpc”: “2.0”,“result”: {“address”: “42uMGYwvLuUGJzqdWZvr47CGCBz1qNNExZeegcjLPMbaFkBb3XG g6Y1bUwaMbovzGWDXtaASxSBYtaiBB4wuDmrAMCygexH”, “addresses”: [{ “address”:  “42uMGYwvLuUGJzqdWZvr47CGCBz1qNNExZeegcjLPMbaFkBb3XG g6Y1bUwaMbovzGWDXtaASxSBYtaiBB4wuDmrAMCygexH”, “address_index”: 0, “label”: “Primary account”,“used”: false
       },
       {
           “address”: “894PaGJyxRjZU8nP7Dh4FuAyzr2dK3VT9ZZX95MxdAGP3HoHEpA bNb8Htgp5LKzc1pXQ8zhpokTZtcUTnzeU823oUPUGSpv”,
           “address_index”: 1,
           “label”: “”,
           “used”: false
       },
                   ]}}

7.3.3.3 Создание адреса

Создание нового адреса для счёта. Опционально можно маркировать новый адрес.

    $ curl -X POST 127.0.0.1:18082/json_rpc -d '{“jsonrpc”:”2.0”,”id”:”0”,”method”:”create_address”, “params” : “{“account_index:0,”label”:”Secondary account”}}' -H 'Content-Type: application/json'

В ответ получаем:

{ “id”: 0, “jsonrpc”: “2.0”, “result”: {“address”: “86KoCQsZHQvSUnp9fFn92e5QGUiZtH1qZ1nNx1Jv5eJs94ywbLR2k 11CjZTq5o4v8j9bx3CEAturCheJqJR7cYdQKT4xE3w”, “address_index”: 9 }}

7.3.3.4 Создание счёта

Создание счёта.

    $ curl -X POST 127.0.0.1:18082/json_rpc -d '{“jsonrpc”:”2.0”,”id”:”0”,”method”:”create_account”,  “params”:{“label”:”Secondary account”}}' -H 'Content-Type: application/json'

В ответ получаем:

    { “id”: “0”, “jsonrpc”: “2.0”, “result”: {“account_index”: 1, “address”: “88bV1uo76AaKZaWD389kCf5EfPxKFYEKUQbs9ZRJm23E2X2oYgV9bQ54FiY6hAB83aDXMUSZF6KWyfeQqzLqaAeeFrk9iic” } }

7.3.3.5 Передача

Передача (отправка) некоторой суммы Monero, выраженной в атомных единицах.

    $ curl -X POST http://127.0.0.1:18082/json_rpc -d ' {“jsonrpc”:”2.0”, ”id”:”0”, ”method”:”transfer”, ”params”:{“destinations”: [{“amount”:100000000, ”address”:”9wNgSYy2F9qPZu7KBjvsFgZLTKE2TZgEpNFbGka9gA5 zPmAXS35QzzYaLKJRkYTnzgArGNX7TvSqZC87tBLwtaC5RQgJ8rm” }, {“amount”:200000000,  ”address”:”9vH5D7Fv47mbpCpdcthcjU34rqiiAYRCh1tYywmhqnE k9iwCE9yppgNCXAyVHG5qJt2kExa42TuhzQfJbmbpeGLkVbg8xit” }],”mixin”:4,”get_tx_key”: true}}' -H 'Content-Type: application/json'

В ответ получаем:

{ “id”: “0”, “jsonrpc”: “2.0”, “result”: { “fee”: 48958481211, “tx_hash”: “985180f468637bc6d2f72ee054e1e34b8d5097988bb29a2e0cb 763e4464db23c”, “tx_key”: “8d62e5637f1fcc9a8904057d6bed6c697618507b193e956f77c 31ce662b2ee07”, “amount”: 300000000, “tx_blob”: “”, “tx_metadata”: “”, “multisig_txset”: “” } }

7.4 Практическая интеграция Monero (руководство для языков Python и C++)

Выбор языка написания кода для этих примеров — дело непростое, так как каждому разработчику известно, что идеального универсального языка программирования просто не существует. Тем не менее Python вполне подходит для «Овладеваем Monero», так как это бесплатный и открытый язык написания сценариев, который относительно доступен и понятен для новичков.

В следующих примерах используется самая последняя версия, Python 3. Дистрибутивы Linux на базе Debian имеют предустановленные версии Python 2 и Python 3. Перед тем как начать, необходимо обновить своё программное обеспечение, чтобы необходимые ресурсы имели актуальную версию.

    $ sudo apt-get update && sudo apt-get -y upgrade

Код для следующих руководств выложен в свободный доступ на публичном репозитории. Вы можете напрямую загрузить учебные примеры, используя мощную систему управления версиями git при помощи команды:

Каждое руководство расположено в папке. Например, Руководство 1 (Tutorial 1) будет находиться в папке tutorial-1. Чтобы загрузить необходимые ресурсы через систему управления версиями Git, необходимо просто выполнить:

$ git clone https://github.com/monerobook/code

7.4.1 Руководство 1: Запрос вашего баланса

Эта программа соединяется с демоном через RPC, а затем запрашивает и выводит баланс счёта. Вы можете помнить функцию getbalance из раздела, посвящённого RPC (также отвечает на get_balance).

Мы начнём с импорта двух библиотек Python, которые очень полезны для запросов POST в версии Python: requests и json.

    # Mastering Monero Tutorial. This is a comment
    import requests
    import json

    ## Import Setup variables
    ## Url for JSON RPC interface. We assume that your RPC interface is running on localhost port 18082
    url = “http://localhost:18082/json_rpc”

    ## JSON headers . Required
    headers = {'content-type': 'application/json'}

    ## RPC input . Adding method name , at the moment we don't need variables.

    rpc_fields = {
        “method” : “get_balance”
    }

Повторно вызовите стандартные поля JSON, которые должны быть включены в вызов RPC:

    # Adding the JSON RPC version and id. Id is a int variable which should be incremented each request. First request is 0 , second is one and ...
rpc_fields.update({“jsonrpc”: “2.0”, “id”: “0”})

Теперь всё готово, и осталось сделать всего одну вещь! Отправить все переменные интерфейсу JSON RPC, используя метод POST HTTP:

    # execute the rpc request
    response = requests.post(url,data=json.dumps(rpc_input),headers=headers)
    # print the response as JSON
    print(json.dumps(response.json()))

Необходимо сохранить весь приведённый выше код как tutorial.py (или под другим выбранным вами именем) и выполнить:

    $ python tutorial.py

Ваш скрипт должен вывести вызов getbalances в вашу консоль:

    {
“id”: “0”,
“jsonrpc”: “2.0”,
“result”: {
    “balance”: 0,
    “multisig_import_needed”: false,
    “unlocked_balance”: 0 }}

Несмотря на то, что здесь содержится вся необходимая нам информация, RPC синтаксис результата не отформатирован для оптимального восприятия человеком. Через какое-то время обилие {} начинает дезориентировать!

Чтобы вычистить результат, можно добавить несколько строк кода снизу скрипта руководства, чтобы выводился только баланс (или незаблокированный баланс, если вам так захочется).

    # Get the balance from response array and convert to a string.
    balance = str(response.json().get('result').get('balance'))

    print(“Balance is “ + balance )

Теперь запускаем:

    $ python tutorial.py

И получаем:

    Balance is 426700000

Вы можете использовать методы RPC подобным образом, чтобы разработать свой собственный личный клиент для своего кошелька Monero!

7.4.2 Руководство 2: Как сгенерировать псевдослучайный адрес

В Главе 5 нами была представлена концепция генерирования псевдослучайного адреса. Чтобы дополнить математическое объяснения, мы предлагаем вам следующий вариант реализации на языке Python.

Сначала необходимо импортировать необходимые библиотеки и добавить их в последовательность.

# Import libraries. Hexlify for hex code, utils for the utility, etc.
import os, sys
from binascii import hexlify, unhexlify
sys.path.append('../libraries')
import utils
import ed25519
import base58

Чтобы создать код функции generate_random_address, необходимо выполнить несколько шагов:
1) Создать собственную мнемоническую фразу, псевдослучайным образом сгенерировав 32-байтовое (256-битное) случайное число. Использовать библиотеку hexlify, чтобы преобразовать мнемоническую фразу в шестнадцатеричную закодированную строку, сохраняемую в переменной мнемонической фразе.
2) Записать секретный ключ траты, сократив мнемоническую фразу до действительной скалярной величины для эллиптической кривой ed25519. Ваш секретный ключ траты является просто представлением вашей мнемонической фразы. При верификации функция sc_reduce32 будет запрошена из библиотеки utils.
3) Вычислить секретный ключ просмотра как сокращённый хеш вашего секретного ключа траты. Функция hash_to_scalar хеширует вход, а затем преобразует его в действительную скалярную величину для эллиптической кривой ed25519.
4) Вывести публичные ключи, используя функцию publickey_to_private_key, чтобы умножить ваши приватные ключи на точку-генератор. Ваш секретный ключ траты выдаст ваш публичный ключ траты, и подобным образом ваш секретный ключ просмотра будет использован для выведения вашего публичного ключа просмотра.
5) Начать построение вашего публичного адреса путём присоединения байта сети (0x12 для публичных адресов Monero) публичного ключа траты и публичного ключа просмотра. Это ключевые части информации, включаемой в каждый адрес Monero.
6) Вычислить контрольную сумму, которая будет присоединена к вышеуказанной строке, взяв первые 4 байта (8 шестнадцатеричных символов) хеша Keccak-256.
7) Закодировать информацию + контрольную сумму в представление в кодировке Base 58, чтобы это мог прочитать человек. Всё сделано! Как уже говорилось в Главе 5, адрес Monero состоит из:

[байта сети + публичного ключа траты + публичного ключа просмотра + контрольной суммы]

def generate_random_address():
        ## Generate 32 bytes (256 bits) of pseudo-random data
        seed = hexlify(os.urandom(32))

        ## Reduce random data to make it a valid ed25519 scalar
        secret_spend_key = utils.sc_reduce32(seed)

        ## Use a reduced hash of the secret spend key for the deterministic secret view key
        secret_view_key = utils.hash_to_scalar(secret_spend_key)

        ## multiply by the generator point to get public keys from private keys
        public_spend_key = utils.publickey_to_privatekey(secret_spend_key)
        public_view_key  = utils.publickey_to_privatekey(secret_ view_key)
        ## the network byte, public spend key, and public view key are all concatenated together
        ## 0x12 is the Monero mainnet network byte
        network_byte = “12”
        ## Concatenate the three strings
        data = network_byte + public_spend_key + public_view_key
        hash = utils.keccak_256(data)
        ## checksum is the first 4 bytes (8 hex characters) of the hash of the previous data
        checksum = hash[0:8]
        address = base58.encode(data + checksum)

        ## Printing the keys

        print(“Secret_spend_key : “ + secret_spend_key)
        print(“Secret_view_key : “ + secret_view_key)
        print(“Public_spend_key : “ + public_spend_key)
        print(“Public_view_key : “ + public_view_key)
        ## Returning address generated
    return address

7.4.3 Руководство 3: Генератор «красивого» адреса

Так называемый «красивый» адрес (vanity address) относится к криптовалютным адресам, генерируемым для какого-то определённого префикса, выбранного вами. Если вы хотите создать адрес с именем cat, вы можете использовать этот метод, чтобы сгенерировать публичные адреса, начинающиеся с 4cat. Из-за формата адреса Monero всё же существуют некоторые ограничения: вы не можете убрать 4 в начале названия (шестнадцатеричный байт сети 0x12), а кодировка base 58 исключает использование некоторых символов (I, l, 0, O).

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

Вот небольшой скрипт Python, который вы можете написать и верифицировать самостоятельно, чтобы безопасно сгенерировать собственный красивый адрес. Подход прост: необходимо раз за разом генерировать адреса, пока вы не получите тот, который будет соответствовать вашим критериям. Рекомендуется использовать короткие строки, так как время, необходимое для грубой верификации адресов, повышается с увеличением длины строки.

Большая часть кода, содержащегося в while(1), является бесконечным циклом, который не будет прерван до тех пор, пока не будет найден адрес, соответствующий критериям. При каждой итерации цикла вызывается функция generate_random_address из предыдущего примера создания нового адреса.

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

import sys
sys.path.append('../libraries')
import address

if (len(sys.argv) != 2):
        print(“usage: python vanity_address.py [desired_prefix]”)
        exit()

if (sys.argv[1][0] != “4”):
        print “Monero addresses must start with the character 4”
        exit()

## create random addresses until one of them matches the desired prefix
## bruteforcing takes a while
while(1):
        rand_address = address.generate_random_address()
        if (rand_address[0:len(sys.argv[1])] == sys.argv[1]):
            print(rand_address)
        exit()
    else:
        print(“searching”)

7.4.4 Руководство 4: Как создать скрытый адрес

Метод создания скрытого адреса, о котором было рассказано в Главе 5, немного сложен, поэтому мы приводим вспомогательный вариант реализации на языке Python. Поэтапное написание нового кода может помочь с точки зрения интерпретации и усвоения математической части.

Целью данного руководства является создание скрытого адреса с использованием публичного ключа просмотра, публичного ключа траты и произвольного приватного ключа транзакции (256-битной скалярной величины).

Сначала из папки библиотек следует импортировать необходимые зависимости.

import os, sys
# library for hex
from binascii import hexlify, unhexlify
sys.path.append('../libraries')
# utils and ed25519 libraries
import utils
import ed25519

Функция generate_stealth_address определяется путём выполнения необходимых математических операций для создания несвязываемого адреса на основе публичных ключей и некоторой случайной информации.

def generate_stealth_address(publicViewKey, privateTxKey,  publicSpendKey, index):

## multiply r*A
derivation = utils.generate_key_derivation(publicViewKey, privateTxKey)

## concatenate index to derivation then hash and reduce
## Hs(rA|i)
scalar = utils.derivation_to_scalar(derivation, index)

## multiply by base point
## Hs(rA|i)G
sG = ed25519.scalarmultbase(utils.hex2int(scalar))
## interpret the public spend key as a point on the curve
pubPoint  = ed25519.decodepoint(unhexlify(publicSpendKey))

## add the public spend key to the previously calculated point
## Hs(rA|i)G + B
output = ed25519.edwards(pubPoint, sG)
## convert the point to a hex encoded public key
return hexlify(ed25519.encodepoint(output))

Код может быть вызван подобным образом:

print(generate_stealth_address(“be90718b250a06b4bcffca6af948240ad6d8951b730a9711f78d4c9decefb4bd”, “12b793b002ed168f36c9dc8d13c0e820546359452f67136f03087eb18208710e”, “6b48d1c30a640b0b33d0062188df2edd4e6acac7282b215e86701a644a9f70ba”, “01”))

Скрытые адреса генерируются не детерминировано, так как примешиваются некоторые случайные данные. Результат может выглядеть так:

a2bd788a63555e0847800b56051072db3558ac2f97b58b8021e57c67125b4411

7.5 API Monero на C++

Взаимодействие с Monero через интерфейс RPC не сложно и легко в реализации, но у него есть и оборотная сторона. Вы можете генерировать адреса и подадреса и даже переводить средства, однако методы RPC не обеспечивают эффективного масштабирования и могут вызвать проблемы, связанные с понижением производительности в случае с большими приложениями.

Есть ли альтернатива? Да! API Monero на C++ справляется со всеми функциями, включая управление кошельками и проведение транзакций.

C++ API немного сложнее использовать, чем RPC интерфейс, поэтому вы можете не захотеть заниматься его начальными настройками, если только вы не знакомы с процессом интеграции Monero. Любые ошибки или проблемы, с которыми вы столкнётесь, могут нарушить вашу безопасность и анонимность.

7.5.1 Библиотеки Monero

Monero Core представляет собой собрание нескольких простых библиотек, необходимых или полезных для механизмов Monero, таких как Boost, Ed2559 и алгоритм CryptoNight.

Они были собраны воедино, чтобы упростить общие процессы, используемые разработчиками; например, разработчик, пишущий код, может просто вызвать base58_decode из библиотек Monero Core, а не вручную создавать функцию с нуля.

Сначала необходимо скомпилировать библиотеки из Monero Core. Как только библиотека будет скомпилирована, создаётся файл с расширением .a или .so.

7.5.2 Начало работы с C++

Чтобы интегрировать код Monero Core, сначала необходимо скомпилировать соответствующие библиотеки. Просто следуйте инструкциям, приведённым выше, проверьте таблицу зависимостей, которая приводится в Главе 6. Знание C++ (особенно основ стандарта C++11) очень поможет при реализации следующего руководства.

7.5.3 Руководство 5: Восстановление всех ключей на основе приватного ключа траты

Данное руководство позволяет восстановить все ключи Monero на основе приватного ключа траты при помощи C++ API и метода CMake. Это руководство предназначено для платформ на базе Linux, так как Apple и Windows имеют собственные библиотеки (например, OpenSSL или Boost)

Сначала необходимо задать все внешние переменные и библиотеки в файле с названием CmakeLists.txt. В данном руководстве мы скомпилируем Monero Core в папку /opt/monero.

cmake_minimum_required(VERSION 3.5)

set(PROJECT_NAME tutorial-5)

project(${PROJECT_NAME})

set(CMAKE_CXX_FLAGS “${CMAKE_CXX_FLAGS} -std=c++11 -ldl”)

if (NOT MONERO_DIR)
        # Path of Monero source code
        set(MONERO_DIR ~/monero)
endif()

message(STATUS MONERO_DIR “: ${MONERO_DIR}”)

set(MONERO_SOURCE_DIR ${MONERO_DIR} CACHE PATH “Path to the root directory for Monero”)

# set location of Monero build tree
set(MONERO_BUILD_DIR ${MONERO_SOURCE_DIR}/build/Linux/master/release/ CACHE PATH “Path to the build directory for Monero”)

set(MY_CMAKE_DIR “${CMAKE_CURRENT_LIST_DIR}/cmake” CACHE PATH “The path to the cmake directory of the current project”)
list(APPEND CMAKE_MODULE_PATH “${MY_CMAKE_DIR}”)

set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} “${MONERO_BUILD_DIR}” CACHE PATH “Add Monero directory for library searching”)

# find boost
find_package(Boost COMPONENTS
    system
    filesystem
    thread
    date_time
    chrono
    regex
    serialization
    program_options
    date_time
    REQUIRED)

# include boost headers
include_directories(
    ${Boost_INCLUDE_DIRS}
)

include_directories(
    ${MONERO_SOURCE_DIR}/src
    ${MONERO_SOURCE_DIR}/external
    ${MONERO_SOURCE_DIR}/build
    ${MONERO_SOURCE_DIR}/external/easylogging++
    ${MONERO_SOURCE_DIR}/contrib/epee/include
    ${MONERO_SOURCE_DIR}/version
    ${MONERO_SOURCE_DIR}/external/db_drivers/liblmdb)
# Specify source files
set(SOURCE_FILES main.cpp)

# Make executable
add_executable(${PROJECT_NAME} ${SOURCE_FILES})

set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX)

set(LIBRARIES        
    wallet
    blockchain_db
    cryptonote_core
    cryptonote_protocol
    cryptonote_basic
    daemonizer
   cncrypto
    blocks
    lmdb
    ringct
    device
    common
    mnemonics
    epee
    easylogging
    device
    pcsclite
    sodium
    ${Boost_LIBRARIES}
    pthread
    unbound
    crypto
    ringct_basic)

if (Xmr_CHECKPOINTS_LIBRARIES)
 set(LIBRARIES ${LIBRARIES} checkpoints)
endif()

set(LIBS common; blocks; cryptonote_basic; cryptonote_core; cryptonote_protocol; daemonizer; mnemonics; epee; lmdb; device; blockchain_db; ringct; wallet; cncrypto; easylogging; version; checkpoints; ringct_basic; )

foreach (l ${LIBS})
    string(TOUPPER ${l} L)
    find_library(Xmr_${L}_LIBRARY
        NAMES ${l}
        PATHS ${CMAKE_LIBRARY_PATH}
        PATH_SUFFIXES “/src/${l}” “/src/ringct” “/src/” “/external/db_drivers/lib${l}” “/lib” “/src/crypto” “/contrib/epee/src” “/external/easylogging++/”
        NO_DEFAULT_PATH
        )

set(Xmr_${L}_LIBRARIES ${Xmr_${L}_LIBRARY})

message(STATUS “ Xmr_${L}_LIBRARIES ${Xmr_${L}_LIBRARY}”)
add_library(${l} STATIC IMPORTED)
set_property(TARGET ${l} PROPERTY IMPORTED_LOCATION ${Xmr_${L}_LIBRARIES})
endforeach()
target_link_libraries(${PROJECT_NAME} ${LIBRARIES})

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

Код Main.cpp

Чтобы скомпилировать код, необходимо перейти к его директории и запустить cmake. Если вы находитесь в корне репозитория с кодом руководства, выполнить:

$ cd tutorial-5 && cmake .

Результат должен выглядеть примерно так:

$ cd tutorial-5 && cmake .
-- The C compiler identification is GNU 6.3.0
-- The CXX compiler identification is GNU 6.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
.....

-- Configuring done
-- Generating done
-- Build files have been written to: /code/tutorial-5

и

$ make
Scanning dependencies of target tutorial-5
[ 50%] Building CXX object CMakeFiles/tutorial-5.dir/main.cpp.o
[100%] Linking CXX executable tutorial-5
[100%] Built target tutorial-5

Если вы столкнётесь с какими-либо ошибками, пожалуйста, сперва убедитесь в правильности версии Cmake (она должна быть v3.5.2 или выше) и GCC (v.5 и выше). Программа CMake создаст для вас makefile. После этого просто вызываем команду:

Наконец запускаем программу, используя ./tutorial-5

Private spend key : <f8f2fba1da00643bbf11ffec355a808d2d8ca4e4de14a10476e116abd8dd7f02>
Public spend key : <fffb624bd31dfafb015b01cbeaef28cbff3b2d77af01c54b77d6e1cef04d5f1e>
Private view key : <9227a05c665f684f5b8fef815cedd8a911b426c9fa07554c70daacf87757b302>
Public view key : <d79eaf3acfd1f7a93526d2eec5bec5b76b880177e2610b69716b4f0577950308>
Monero Address: 4BKjy1uVRTPiz4pHyaXXawb82XpzLiowSDd8rEQJGqvN6AD6kWosLQ6VJXW9sghopxXgQSh1RTd54JdvvCRsXiF41xvfeW5