Трудности в отправке транзакции. Bitcoin. Provider API

206
07 января 2019, 15:10

Всем привет.

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

История такова. Мне нужен был provider-API для Java, с помощью которого я бы смог отправлять транзакции и создавать адреса. Вездесущая bitcoinJ требует наличия собственной ноды с блокчейном для функционирования. Остальные провайдеры либо не имеют Java SDK, либо берут свою комиссию, либо требуют наличие своего коммерческого ресурса. В итоге я пришел к blockcypher api.

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

В общем, на этот раз проблема совсем аномального(с моего уровня полета) генеза. После перехода аномальной точки бифуркации, доступ к адресу закрывается и я не могу перевести с него средства. Я вычислил что это происходит в такой комбинации:

  1. Сгенерировать 2 адреса
  2. Пополнить 1 с помощью онлайн сервисов типа https://coinfaucet.eu/en/btc-testnet/
  3. Перевести пару раз монеты с 1 на 2
  4. Попытаться перевести обратно со 2 на 1(или на любой другой) (на данном этапе все и обламывается)

Причем с 1 все еще можно будет переводить куда угодно монеты. 2 уже можно считать забракованым, с него никуда не вывести. Не исключено что существуют еще комбинации в которых вылазит эта проблема. Но пока что я выявил только такую закономерность. Есть еще один момент. Если после этого создать еще 3 адрес и пополнить его извне. То с 3 тоже нельзя будет отправить на 1. Все остальные комбинации возможны. Т.е. 3->2, 1->3. Надеюсь хотя-бы немного понятно выразился. Проблема не в недостатке средств! Я всегда дожидаюсь пока будет хотя бы одно подтверждение сети!

Сама ошибка выкидывается последним методом в приведенном ниже коде. Выглядит вот так:

BlockCypherException{message=Bad Request, status=400, blockCypherError=[Error{error='Error reading signatures and pubkeys: Counts of public keys and signatures are not equal..'}], exception=null}

А вот пример транзакций, которые ее вызвают:

{"tx":{"hash":"3930029653f65375db2ef227be24639b8d8c33272136386c239b3b723599b700","block_height":-1,"addresses":["mm1UEmcppHf1dhLqVXoUwpce7whw4cHCS9","myn4YcaU1h4VURSVVZsSNoYUho9GCcqmRU"],"total":21453193,"fees":23600,"relayed_by":"78.128.150.96","received":"2018-09-20T21:32:40.603523199Z","ver":1,"vin_sz":3,"vout_sz":1,"confirmations":0,"preference":"high","double_spend":false,"inputs":[{"prev_hash":"a30cd76ad10b500a6dc9a17ad118da9fc80d4aa02dcba64fd0018ecf5b37ba2d","output_index":0,"output_value":76931,"addresses":["mm1UEmcppHf1dhLqVXoUwpce7whw4cHCS9"],"script_type":"pay-to-pubkey-hash"},{"prev_hash":"c862edbfb9bd64dd16a90a6d575d35affc8e7eafa77d1492a2722742f56e3f21","output_index":0,"output_value":7693,"addresses":["mm1UEmcppHf1dhLqVXoUwpce7whw4cHCS9"],"script_type":"pay-to-pubkey-hash"},{"prev_hash":"e5b44f7452d76d3a1cf14b36b204c68a7b311ef8824c7fc1e095d5f3296103d0","output_index":0,"output_value":21392169,"addresses":["mm1UEmcppHf1dhLqVXoUwpce7whw4cHCS9"],"script_type":"pay-to-pubkey-hash"}],"outputs":[{"value":21453193,"script":"76a914c84db8bd4b66fbffaf91c5ca11dc3f398d603b6d88ac","addresses":["myn4YcaU1h4VURSVVZsSNoYUho9GCcqmRU"],"script_type":"pay-to-pubkey-hash"}]},"tosign":["493da515f2c84fceb56de759940eeb598f9ba304e6a2651534a838f796d930ff","f13cb2beca8a470aee60c6f27f64eadc00addde04df55771668f0e12409e3058","88ea0fc5f68ffa57c4c4479bf3565d64f49b0e5d75fa645b5f71c30d60374351"],"signatures":["3045022100b5652ba3310d3fafde713ab9cd9628c9d617e2e969f9687b6938bdb07e3a99a3022064facf1853da51e7f426bfef5ea8f50fb301de6efc6796e43915078ff9ce987a","304502210095336bcd28c1f08b31f6e25bfc77421f3ec7556089626ee09720ed44e51e6a8302201adaa05e32d561955ec0c0193daaa4ff246cdd4207b2ca8d09781a73af6ecc21","30440220086c4c9833173d68179e2da9c79f1c92f9cff9717ea3caf5014d6f191999bb30022058f6162ce01227611143e5632f8e077013546d73d735daed0202df5762d4e1bc"],"pubkeys":["0388e410aa94114b5a0fb683be1e15ef7e8f6ac4a3555beac22f4f8d2575dde60e"]}
{"tx":{"hash":"7befea4f60cfbc50597a03346add775bf7b4bb0f5f428a9582b32ce79da474ed","block_height":-1,"addresses":["msggp35jUPYubFU2zPm8YHYDunat7c244g","mogaQxPWuaQH9mB85Z5eGeL5ABrcX2PYqf"],"total":45212,"fees":30600,"relayed_by":"78.128.150.96","received":"2018-09-20T23:19:11.202405866Z","ver":1,"vin_sz":4,"vout_sz":2,"confirmations":0,"preference":"high","double_spend":false,"inputs":[{"prev_hash":"c806ed8b26bbebbd293f792f85d6534785b0bac3a7103d4c1a9460ef740d7252","output_index":0,"output_value":5858,"addresses":["msggp35jUPYubFU2zPm8YHYDunat7c244g"],"script_type":"pay-to-pubkey-hash"},{"prev_hash":"90a140afa6941819791232423e48ac29c5f4bb6654e0daba5a548e9f8789ac50","output_index":0,"output_value":7000,"addresses":["msggp35jUPYubFU2zPm8YHYDunat7c244g"],"script_type":"pay-to-pubkey-hash"},{"prev_hash":"957c81ee26c5ca653768050d8ebaed886e2ffb48400ca80ccdb1fe4badd16ef3","output_index":0,"output_value":7000,"addresses":["msggp35jUPYubFU2zPm8YHYDunat7c244g"],"script_type":"pay-to-pubkey-hash"},{"prev_hash":"6e6a20dce45febf93cd5b13579d98138ab0918de9c1961b8c9c6505d02b0221d","output_index":0,"output_value":55954,"addresses":["msggp35jUPYubFU2zPm8YHYDunat7c244g"],"script_type":"pay-to-pubkey-hash"}],"outputs":[{"value":7000,"script":"76a9145992e68a2ac35feffbee743e092cec95cc7b9f3288ac","addresses":["mogaQxPWuaQH9mB85Z5eGeL5ABrcX2PYqf"],"script_type":"pay-to-pubkey-hash"},{"value":38212,"script":"76a9148578be922d6fc2e391ac668203dcedf44dd32b6c88ac","addresses":["msggp35jUPYubFU2zPm8YHYDunat7c244g"],"script_type":"pay-to-pubkey-hash"}]},"tosign":["9191af28a70c531aaf6f9f6eb5f44077e4d26ecfcd7fd0c6d544c352dd9ade9e","4905f011ac0449cf56cc927d07ea7e233f3f9fa96d720de0f70dae774676b151","ed20429e349915b3fec3a443d0e4ee962d6ff98639581e5541cfa555ae6fc936","cf906927e62ce445529601e496c826b0332bf156effe2c39e7a8b3d80d0c3e92"],"signatures":["30440220541d9227b0eb4d8bae3dc3c1e6c4e0868debe244e03d9ab3ebb6a4b1b6ece90c0220326bfdb53f6800f97c5071a99f1dee0915e01d2814699f15e8d3c547a5cbe75a","30440220797a533a1ce452edaa8e24634e4a3024124205d903cb687e9dcec51291dec320022011e8083108319d6856674e869d62197d837ece0f4bc4a4cdff7aa4c8ccb17fc1","3044022017f3429f7ccc4fb3d137e04b94a47e2ba4d19f05d017514f29ae687de65b996402202e7a58d809c222c9d01a1473650af9e01bf84bf7ca62cf101277d31bbac5a1be","3044022056848052dc3237d41abf6cb3d716bf7021a30f3346db11b301bb7c6b27339a70022072790eaebf49a63c25406103779ead18de66f70a4d9f52a060c5d2419e308774"],"pubkeys":["02fb6e3502b464dd5335fb48113bc9b2cee2a36a2e6edfff9c94e8ac8225541f5e"]}

Вот мой, полу-рабочий, добытый кровью и потом код отправки транзакции:

private static Transaction sendBtc(String from, String to, String privateKey, String pubKey, long value) throws Exception {
        IntermediaryTransaction unsignedTX = null;
        long satoshi = value;
        unsignedTX = context.getTransactionService().
                newTransaction(
                        new ArrayList<>(Arrays.asList(from)),
                        new ArrayList<>(Arrays.asList(to)), satoshi);
        unsignedTX.addPubKeys(pubKey);
        SignUtils.signWithHexKeyNoPubKey(unsignedTX, privateKey);
        return context.getTransactionService().sendTransaction(unsignedTX);
    }

Причем, прошу заметить, я использую метод signWithHexKeyNoPubKey, но при этом добавляю публичный ключ к транзакции unsignedTX.addPubKeys(pubKey);. Именно данная комбинация "работает". Остальные комбинации с signWithHexKeyWithPubKey и т.д. не работают вообще!

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

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

READ ALSO
Получение сообщений андроидом от firebase

Получение сообщений андроидом от firebase

Есть десяток андроидов, все подписаны на topic firebaseСообщения не содержат заголовка (notification) только date и не много

144
Покрыть тестом значение в методе

Покрыть тестом значение в методе

Есть класс в котором есть методВ методе инициализируется переменная String, ей присваивается ссылка

168
что такое Proxy Object?

что такое Proxy Object?

что такое proxy object в Hibernate?

266
Архитектура настольного приложения

Архитектура настольного приложения

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

147