Использование биткоин-ноды в качестве API-шлюза

Знали ли вы, что у каждой биткойн-ноды есть встроенное API, которым можно пользоваться как локально, так и через Web?

А нет, стойте, начну с другой стороны.

Своя биткойн-нода – что это и зачем

Давным-давно я писал статью, в которой перечислял способы завести свой биткойн кошелек. Одним из способов была установка своей полной ноды. Пришло время добавить подробностей и понять, чем нода может быть полезной.

Хранение денег – вопрос очень сложный, и многогранный, а хранение биткойнов еще и технически усложнен. Если обычные деньги можно хранить дома (где их могут украсть) или в банке (который может обанкротиться), то биткойны можно потерять, доверив их бирже (которую могут взломать), сайту-сервису по хранению (аналогично), можно потерять флешку с приватными ключами, может сдохнуть жесткий диск, а еще могут нагрянуть хакеры.

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

Нода – это программа, которая запущена и работает на компьютере или сервере, и обменивается данными с такими же нодами по всему миру. Принцип работы сравним с битторентом – есть огромная база транзакций, есть программы у участников на компе. Каждая такая программа – это как филиал банка, где можно выставлять счета, оплачивать счета, переводить деньги из одного филиала в другой на тот или иной счет. На своей установленной ноде вы создаете адреса для получения денег (например 15u2exuYtMbvaDyVNYWgThFidZP7KHyjmM), с неё же отправляете на другие адреса, можно отправлять в рамках своей ноды, что бы запутать/размазать и т.п.

Каждый раз, когда вы делаете транзакцию (перевод средств) в своей ноде, ваша нода пишет в вашу локальную копию блокчейна эти данные, подписанные вашей уникальной цифровой подписью, и эта ваша копия блокчейна синхронизируется с другими нодами, а те с другими и т.п. – и это быстрый процесс. Стоит вам перевести деньги у себя локально с одного адреса на другой, об этом узнают в течении минуты-двух на другом конце планеты. Другой вопрос, что эту сделку не посчитают окончательно завершенной, пока майнеры не добавят её в нужное кол-во блоков в свои копии блокчейна, пока эти копии тоже не синхронизируются и не разойдутся.. Но это другой вопрос.

Итак, для себя я вижу применение полезным применение ноды в двух случаях:

  1. Когда хочу иметь полный, надежный и бесконтрольный доступ к своим же средствам
  2. Когда хочу иметь надежный и быстрый платежный интерфейс

С первым пунктом всё понятно – паранойя и жажда контроля. Что насчет второго?


Реклама


Нода как платежный интерфейс

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

Чужое API

И тут начинаются пляски с бубнами. Самое очевидное, на первый взгляд решение, это использование стороннего API. Многие сайты предоставляют такие решения, например вот решение от blockchain.info. Я его пользовал несколько лет назад, и вот что мне не понравилось (это было давно, сейчас ситуация могла измениться):

Проблема 1. Задержки в трансфере

Для получения платежа нужно сначала обратиться (через API) на сайт blockchain.info, получить новый адрес для получения платежа, дать адрес клиенту, клиент на этот адрес отправляет средства – это всё еще кошелек blockhain.info (далее – BI). Через какое-то время по шедулеру деньги переводятся на с кошелька, который перевел клиент, на кошель, который указал ты.. Но не сразу. В некоторых случаях BI ждет подтверждений, в некоторых ждет, когда мелкие платежи в сумме составят какую-то сумму, и только потом BI вызывает callback на твоем сайте, сообщая о том, что средства пришли.

Я сбился со счета, когда злые клиенты писали мне лично, с вопросом – я перевел бабки, уже 10 подтверждений, почему не пополнился баланс?!?!?! В таких случаях, иногда пришлось клиента упрашивать подождать, иногда писать в саппорт BI, и, в особо запущенных случаях, перевод мог идти до ТРЕХ ДНЕЙ. Это многовато даже по меркам биткоина. Понятное дело, что второй раз люди не отправляли средства.

Кроме того, люди не отправляют неизвестно куда средства, дураков нет. Очень распространенный паттерн – отправить небольшую сумму, рублей на 30, проверить, пришло или нет, потом вывести её, проверить вернулось ли, сколько по факту списалось комиссии и т.п. Очевидно, если с 30 рублями такая история на несколько дней, сколько нервов потребуется при вводе/выводе крупной суммы?

Проблема 2. Технические ограничения

Для каждого пользователя я создавал свой адрес, но первая ласточка прозвучала, когда кол-во юзеров перевалило за 1000. Банально перестал работать интерфейс – в то время никто не ожидал, что кому-то может понабиться такое кол-во, и после 999 кошелька JavaScript просто падал с ошибкой на сайте.

Ладно, не беда, я продолжил получение нужных мне данных через API, и через какое-то время столкнулся с тем, что меня начали отвергать – размер моих данных, с учетом кол-ва адресов и переводов превысил допустимые для них нормы. Об этом мне сообщили и пообещали жуткие кары, после чего я переделал механизм – стал по другому генерировать, стал заново использовать адреса..  Но это не круто, когда не можешь делать так, как нужно тебе.

Проблема 3. Фатальная

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

Хочу сразу отметить, у меня нет претензий к BlockChain.Info, у них отличное и бесплатное API, для каких-то ненагруженных проектов я бы выбрал именно их.

В те дни я пробовал работу разных API, неплохое было у https://developers.xapo.com/, какой-то платный сервис обещал все, что мне было нужно, но не смог принять (и увидеть!) платеж от меня, какой-то отдавал ошибки при запросах к API и т.п. В общем на рынке было не так много интеграционных решений для проведения платежей. Не уверен, что и сейчас есть, но должны же быть.

Своё API

А теперь о своём. Биткойн нода, как я писал вначале, имеет встроенное API. Иными словами, если залезть в конфиг и выставить нужные настройки, на компе/сервере с нодой поднимется Web-сервис, на него можно отправлять запросы – создания адресов, получения денег, отправки денег, получать информацию о блокчейне, валидировать адреса и т.п. В простейшей схеме это выглядит так – у вас есть какой-то своей сервер, которым пользуются пользователи, и есть биткоин-нода, которая (в идеале) видна только вашему серверу. Ваш сервер обращается к ноде, для того, что бы удовлетворить запросы пользователей.

Давайте установим и проверим.


Реклама


Установка.

Говорю сразу, для ноды важно место. Сейчас она занимает больше 200Гб и будет дальше расти, т.к. содержит весь блокчейн. Дисковое место по какой-то иронии сейчас дорогое, так что сервер дешевле брать с HDD, или вообще установить её на ноутбуке дома и пробросить порт. Я расскажу на примере установки на ноутбук, на который установлен Ubuntu Server LTS.

Порядок действий:

Стать рутом

sudo bash
(ввести свой пароль)

Добавить ppa

add-apt-repository
ppa:bitcoin/bitcoin apt-get update

Выполнить

apt-get install bitcoind

Отредактировать файл  /etc/bitcoin/bitcoin.conf

server=1
rpcuser=SomeUser
rpcpassword=SomeStrongVeryStrongReallyStrongPassword
rpcport=8332

Пароль и пользователь должны быть очень надежными, символов по 100 каждый! Это все же деньги.

Создать директорию для хранения блокчейна (200Гб на сегодня). По умолчанию будет всё падать в /home

mkdir /mnt/btc_blockchain

Добавить запуск ноды в кронтаб после перезагрузки

@reboot bitcoind -daemon -datadir=/mnt/btc_blockchain -conf=/etc/bitcoin/bitcoin.conf

Перезагрузить

Добавить алиас, что бы каждый раз не указывать конфиг

touch ~/.bash_aliases
source ./.bash_aliases

Для проверки выполнить

bitcoin-cli getbalance

Самая полезная команда поначалу – выводит список доступных команд

bitcoin-cli help

С её помощью так же можно узнать как пользоваться любой из представленных команд. Например:

bitcoin-cli help getbalance

 

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

bitcoin-cli getnewaddress

Отправлять деньги получателю

bitcoin-cli sendtoaddress

Или списку получателей (каждому свою сумму)

bitcoin-cli sendmany

Ну и т.п.

Что более приятно, обращаться к ноде через веб (если явно разрешить это в конфиге). Разумеется, о безопасности забывать нельзя, поэтому нужно, в идеале, работать через VPN каналы, ну, или хотя бы ограничить доступ к ноде по IP.


Реклама


Запуск API

Давайте изменим конфиг и посмотрим, что получится

 

Нода развернута на машине с адресом 192.168.88.244, а адрес компа, с которого я работаю, 192.168.88.248. На ноде я разрешаю подключаться только с него (ну и локально с самой ноды, конечно).

Ноду нужно перезапустить (в простейшем случае перезагрузите убунту, или убейте процесс bitcoind и запустите заново, скопировав команду из crontab)

Теперь можно проверить работу – откроем для начала в браузере

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

Если всё сделано правильно, результат будет таким:

Еще пару методов – запросим инфу о текущем состоянии блокчейна и попробуем осуществить перевод

Вывод будет выглядеть так

 

Вот, собственно, код:

import requests
from requests.auth import HTTPBasicAuth

# Указать rpc логин и пароль, который задавали в bitcoin.conf
node_login = "SomeUser"
node_password = "SomeStrongVeryStrongReallyStrongPassword"
# IP адрес ноды
node_address = "http://192.168.88.244:8332"

# Запросим баланс
payload = {
        "jsonrpc": "1.0",
        "id":"",
        "method": "getbalance",
    }
balance = requests.post(node_address, json=payload, auth=HTTPBasicAuth(node_login, node_password))
print("Balance", balance,balance.text)
print("-"*80)

# Запросим информацию о блокчейне
payload = {
        "jsonrpc": "1.0",
        "id":"",
        "method": "getblockchaininfo",
    }
b_info = requests.post(node_address, json=payload, auth=HTTPBasicAuth(node_login, node_password))
print("BlockChainInfo", b_info, b_info.json())
print("-"*80)

# Отправить 0.01 BTC автору статьи
payload = {
        "jsonrpc": "1.0",
        "id":"",
        "method": "sendtoaddress",
        "params": ["15u2exuYtMbvaDyVNYWgThFidZP7KHyjmM", "0.001", "donation"]
    }
send_money = requests.post(node_address, json=payload, auth=HTTPBasicAuth(node_login, node_password))
print("Send Money", send_money, send_money.json())

Готово, получилось – нода работает и скрипт отправляет и получает с неё данные. Считайте, платежный шлюз или что-то такое в кармане. Из полезного еще можно упомянуть такой параметр, как walletnotify. Можете вписать его в конфиг. Вот так:

walletnotify=/home/scripts/transaction.sh %s

Каждый раз, когда в вашу ноду прилетает информация о транзакции (кто-то отправил вам деньги или вы отправили кому-то), будет вызываться скрипт /home/scripts/transaction.sh (его надо написать, конечно).

Этому скрипту входящим параметром будет передаваться транзакция. Что с ней делать – ваш выбор. Я использовал так – как только приходила транзакция, срабатывал скрипт, писал этот переданный хеш транзации в файл, как наиболее надежное средство. Серверный демон мониторил файл, и, если находил там свежую запись, уже переносил в базу и проверял – т.е. вызывал метод ноды, который запрашивал информацию о транзакции. Если это была входящая транзакция, и это первое её упоминание, смотрел на какой адрес она пришла, по адресу находил в базе юзера с этим платежным адресом (адреса я выдавал) и сообщала ему, что платеж поступил и ждет подтверждений.

Еще из той же серии параметр blocknotify=/home/bitcoin/blocknotify.sh %s. Каждый раз, когда обновляется информация о блоках, он вызывает скрипт и передает ему номер блока. Это удобно использовать для обновления инфы о подтверждениях. Т.е. если блок изменился, значит поработали майнеры, можно проверить что там есть по нашим транзакциям.

Более подробно о командах можно узнать тут (на английском языке)


Реклама


Заключение

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

Удачи!

Последнее изменение:

Не забудьте рассказать друзьям об этой статье.
Чтобы поддержать ресурс Bablofil достаточно просто поделиться с друзьями этой статьей в социальных сетях. Каждый репост - это самая высокая оценка качества материала. Спасибо, что читаете этот блог.



Комментарии
Пожалуйста, авторизуйтесь, что бы оставить свой комментарий
Крипто-кошельки для помощи и благодарности проекту:

Bitcoin адрес проекта: [[address]]

Перевод на сумму [[value]] BTC получен. Спасибо!.
[[error]]

Ethereum адрес проекта: [[address]]