• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Прием платежей BTC, ETH, DASH, LTC без посредников и приватных ключей (2021)

marmalade

Gray Hat ♣ White Rabbit
Пользователь
Регистрация
29.07.2021
Сообщения
691
Реакции
723
Гарант сделки
10
Депозит
0.1 и др.
Когда писал свою приемку нигде не мог найти нормальную статью и посвятил около 3-ех дней чтобы понять ситуацию и оценить рынок данных сервисов. Около недели ушло на то, чтобы найти подходящие API сервисы и стабильно парсить блокчейн. Информацию можно найти, но вся она недостоверная либо устаревшая.

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

Формулируем цель: простая, бесплатная, стабильная приемка оплаты для минимальной vps’ки с zero trust подходом (без приватного ключа)

Чтобы принимать платежи в крипте, есть несколько вариантов, точнее один – это парсить блокчейн, а вот вариантов реализаций несколько:
  • Своя блокчейн нода
  • Мерчант сервис
  • АПИ сервисы

Мерчанты

Минусы:
  • берут от 1% и иногда закладывают скрытую комиссию в fee.
  • иногда просят приват ключ
Плюсы:
  • множество монеток для оплаты, erc20 и bnb токены тоже

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

АПИ сервисы

Есть множество АПИ сервисов, которые могут предоставлять ту или иную информацию, но это не всегда про прием оплаты. Я потратил некоторое время чтобы обнаружить, что некоторые сервисы предоставляют лишь экономический анализ волатильности, стакана и пр. Некоторые, имеют сложную регистрацию, порою с ручной модерацией, а некоторые и вовсе не работают.

Бесплатных, действительно мало и они имеют сильные лимиты, у платных же, ценообразование у них Х запроов в Y времени, например 1000 запросов в минуту при общих 100 000 в месяц. Несколько прикинув в голове кол-во запросов я неожиданно обнаружил, что мерчантом будет пользоваться даже выгодней.

Локальный блокчейн журнал на один кошелек

Поднимать свою блокчейн ноду на сервере необходимо под каждую криптовалюту, это требует не только времени и дальнейшей поддержки работоспособности но и дискового пространства. Биткоин журнал уже давно перевалил за 300 гигабайт.

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

Это решение необходимо было оставить до следующего утра, обдумать и проснувшись, я уже не чесал репу, а думал какую базу для хранения взять и что может пойти не так. Это хорошее решение, так как можно использовать несколько апи сервисов, ротируя их, пока не закончаться лимиты, а если и их не хватит – всегда можно прикрутить самые дешевые прокси. Тор, кстати, уже активно экплоатировался на многих АПИ сервисах и с его помощью не всегда получается спарсить блочейн, но это самый доступный и простой ротируемый прокси.

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

Python:
try:
    txs = parse_blockcypher(wallet, ticker)
except:
    print(f"Something wrong with blockcypther")
    try:
        txs = parse_chainso(wallet, ticker)
    except:
        print(f"Something wrong with chainso")

Бесплатные blockchain explorer API

Про Chainso уже было описано в одной статье, с реализацией на php, поэтому про этот сервис не буду писать, у него хорошие бесплатные лимиты, 300 запросов в минуту, но он не поддерживает Segwit адресса, а именно bn*** и 3***, только 1***, и на практике - иногда просто неработает, т.к. разрабы все никак не выкатят платную версию, поэтому не могут обещать стабильности

Поэтому, в данной статье я рассмотрю blockcypher, а чейнсо можно использовать как второй, резервный провайдер данных. в случае есть блоксайфер будет недоступен или порежет IP на лимит.

Сайфер нам скромно предоставляет 3 запроса в секунду и 200 запросов в час. Тут я чуть было не отказался от своей затеи, ведь по сравнению с чейнсо, данные лимиты совершенно крохоборские. Но несколько раз обдумав общий подход к проверке транзакций я понял, что этого будет достаточно. Ведь к локальной базе данных можно обращаться безлимитно, а вот синхронизировать ее с блокчейном можно в ленивом режиме, например 1 раз в минуту. Получается 60 запросов в час на один кошелек в одной валюте. Для четырех валют выходит 1 запрос в 72 секунды. Вполне оперативно. Например, на сервисе sms-activate для ждал зачисление баланса более 10 минут после подтверждения транзакции.

И это только с помощью одного сервиса и без прокси. Chainso может подстраховать LTC и часть BTC кошельков, но в данном случае, я бы рекомендовал blockchain.info, хоть там и cloudflare на фронтенде.

Парсим API Blockcypher

Рассмотрим на примере парсинга BTC блокчейна.

Python:
url = "https://api.blockcypher.com/v1/btc/main/addrs/37mFrx7otSSzUizXmPXbKo1xHMZeiZpxh9/full?limit=50"

АПИ Сайфера достаточно простое с одной лишь загвоздкой, по запросу на кошелек – выдает транзакции с максимум в 20 input/output чанков, если их больше, то необходимо делать дополнительный АПИ запрос на хеш транзакции, чтобы собрать общую сумму транзакции. Поэтому на и нужен chainso, а так же, можно поставить лимит на кол-во транзакций по АПИ. Вот так устроен блокчейн, вы возможно видели нечто подобное:

1627645835900.png


Поэтому, чтобы собрать сумму перевода, необходимо пройтись по всем инпутами и аутпутам и просуммировать value, если в адресах есть необходимый нам кошелек. Намного проще это можно объяснить с помощью кода:
Python:
    r = requests.get(url)
    data = r.json()
    txs = data['txs']
    for tx in txs:
        val = 0
        for out in tx['outputs']:
            if wallet in out['addresses']:
                val = out['value'] + val
        for inp in tx['inputs']:
            if wallet in inp['addresses']:
                val = inp['output_value'] * -1 + val
        if 'next_outputs' in tx:
            nxt = tx['next_outputs']
            url = nxt.replace('limit=20', 'limit=999999')
            r = requests.get(url)
            data = r.json()
            for out in data['outputs']:
                if wallet in out['addresses']:
                    val = out['value'] + val
            for inp in data['inputs']:
                if wallet in inp['addresses']:
                    val = inp['output_value'] * -1 + val
        if type(val) == int:
            val = val / pow(10, 8)
    tx = [hash, wallet, ticker, val, dt, confirms]

В input собираем исходящую транзакцию, в output собираем входящую, которая нам и необходима для сверки с плательщиком

1627643121500.png


Безопасность

Но как нам понять, кто именно из пользователей сделал перевод, если кошелек для всех один общий? В случае QIWI или Yoomoney – можно написать примечание, а в случае криптовалюты – нельзя (ну кроме эфира). В таком случаем мы можем ориентировать только на сумму перевода.

Восьмизначное число исчесляемое сатошами, в случае Bitcoin, довольно уникально, но вдруг, у вас тысячи пользователей которые могут платить одновременно и это число совпадет двоих и больше пользователей? Можем начислить им всем по мере подтверждения транзакций,но кому первому и опять, вдруга, кто из них, случайно или умышленно, мог указать слишком маленькую комиссию и транзакция не прошла, но была ему зачислена вместо более добросовестного покупателя?

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

Итог

Имеем простую приемку платажей, которая будет работать на сервере и с 128 Mbit RAM, которая не хранит ни приватных ключей ни каких-либо данных, ей нет оснований не доверять или ожидать подлог и довольно надежная из-за несколких источников данных, достаточно добавить столько необходимых резервных функций с парсилкой любого публичного блокчейна, чтобы приобрести ощущение стабильности, в моем случае 4-ех сервисов хватило.
 
Используется в продакшене здесь: http://xssforum7mmh3n56inuf2h73hvhnzobi7h2ytb3gvklrfqm7ut3xdnyd.onion/threads/54585/
 
Насколько вообще хороша идея принимать платежи на какой-то определенный пул кошельков по сравнению с генерацией кошелька отдельно для каждого пользователя?
 
Это лучше чем принимать через мерчи.
Так как:
А) комплаенс
Б) амеры зачастую не понимают что после оплаты надо нажать на кнопку «я оплатил» и приходится ручками на балансы закидывать ?
 
Если принимать на какой-то определённый пул кошельков, то есть вероятность, хоть и очень маленькая, что будет такая ситуация, когда у двух юзеров будет одна сумма и один кош.
Лучше всё же считаю для каждого пользователя генерировать новый кошелёк, это повышает конфиденциальность.
Написано же - делаем чек есть ли щас активный инвойс на такую же сумму, если да то добавляем к текущему 0.0000001 до тех пор пока не будет уникальной сумма. Но это меньше 1% всех платежей обычно
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх