Одним из основных преимуществ Биткоина является то, как просто, легко и удобно работать с ним, с точки зрения разработчика. Биткоин не имеет ни сторонних зависимостей, ни проприетарных API, ни быстро меняющихся интерфейсов. Каков бы ни был ваш любимый язык программирования, есть неплохая вероятность того, что уже существует простая биткоин-библиотека, которая позволит вам начать отправку и получение биткоинов в течение нескольких часов. Цель этой статьи – представить некоторые из этих библиотек, и показать основы работы с биткоин-адресами и транзакциями на любом языке.
Адреса, Ключи, Транзакции, ого!
Биткоин-протокол можно разделить на три логические части: управление адресами и ключами, создание транзакций и добавление транзакций в блоки (майнинг). Аспекты майнинга для начинающего разработчика неактуальны, и здесь не освещаются. Это отдельная специализированная область, которая быстро профессионализируется, а если вы заинтересованы в любительском майнинге – просто купите стандартное оборудование биткоин-шахтера. А вот адреса, ключи и транзакции – это то, с чем приходится иметь дело каждому, об этом-то мы и поговорим.
В плане управления биткоин-ключами, есть три типа объектов, с которыми вам придется иметь дело: секретные ключи, публичные ключи и адреса. Возможно, вы также видели термины «закрытый ключ» и » открытый ключ» в контексте криптографии с открытым ключом, так вот это то же самое. Биткоин использует не старые криптографические алгоритмы на основе разложения на множители (как RSA), а более новый вид криптографии, который называется эллиптическая криптография, поэтому биткоин-ключи немного отличается от, скажем, PGP-ключей. Секретный ключ выглядит следующим образом:
9d86361789d13823fd888fa45c9b356b
76d41a7e33b2b2c3056632721c4c1255
А соответствующий ему публичный:
04d8f08938e78447b2b1a629c503d5e17483b0d157
5
1a9e8f83c8460e6ec32fd68d0b4068e83c012f54df9
95e52ed8bae38056a8d922f9687200ae83e5a6728dff
Секретный ключ может быть преобразован в публичный ключ, а вот публичный ключ не может быть преобразован в секретный. Биткоин-адрес на самом деле не публичный ключ, а его хэш. Так, биткоин-адрес, соответствующий приведенному выше публичному ключу будет: 172YRdGzPqyXm9rm1EWKwPXTRsmcApoPQ6
Как вы могли бы заметить, биткоин-адрес представлен не в шестнадцатеричном виде, как секретный и публичный ключи. Это потому, что для него Биткоин использует «сжатый» формат представления, известный как base58check. Base58 говорит о том, что в нем используются 58 различных букв и цифр (ноль, О, l и I опущены, так как их слишком легко перепутать друг с другом). Base58 – это число с основанием 58 — аналогично привычному для нас двоичному (основание 2), десятичному (основание 10) или шестнадцатеричному (основание 16) представлению. Например, десятичное число 31337 в двоичном виде будет ’111101001101001′, в шестнадцатеричном — ’7A69′, а в основании 58 это просто ‘AKJ’. Ну а суффикс check в описании формата означает, что к перед переводом числа в base58 к нему еще добавляется четырехбайтовая «чек-сумма». Все биткоин-библиотеки (о которых мы поговорим чуть позже) делают перевод в base58check автоматически, так что вам не придется это специально программировать.
Ну а теперь, поговорим о транзакциях.
Первое, что необходимо иметь в виду, это то, что в биткоине нет понятия «счетов» или «балансов», как в обычной бухгалтерии. Все средства хранятся в объектах, известных как «выходы транзакции». Каждая транзакция имеет один или несколько «входов», каждый из которых тратит неизрасходованный «выход» более ранней транзакции («UTXO=unspent transaction output»). Общее количество биткоинов во всех входах суммируется, и транзакция может затем распределить эту сумму на любое количество своих собственных «выходов». Вот как типичная транзакция выглядит в json формате:
{ "locktime": 0, "ins": [ { "script": "", "outpoint": { "index": 0, "hash": "319ba90f1645eed46a8fd48e9754ca979c3371f59099d32634a8b56549ce02aa" }, "sequence": 4294967295 } ], "outs": [ { "value": 1000000, "script": "76a914a41d15ae657ad3bfd0846771a34d7584c37d54a288ac" }, { "value": 344164, "script": "76a914c4c5d791fcb4654a1ef5e03fe0ad3d9c598f982788ac" } ], "version": 1 }
А если это затем сериализовать, мы получим:
0100000001aa02ce4965b5a83426d39990f571339c97ca54978ed48f6ad4ee45 160fa99b310000000000ffffffff0230750000000000001976a914a41d15ae65 7ad3bfd0846771a34d7584c37d54a288ac204e0000000000001976a914c4c5d7 91fcb4654a1ef5e03fe0ad3d9c598f982788ac00000000
Параметр каждого выхода «script» это чаще всего просто способ представления адреса получателя. Преобразовав два выходных скрипта указанной транзакции в адреса, мы получим «1FxkfJQLJTXpW6QmxGT6oF43ZH959ns8Cq
» и «1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T
«, соответственно. Единственный вход в этой транзакции является ссылкой на выход предыдущей транзакции (хэш-код транзакции и индекс выхода в ней). Посмотрев на blockchain.info, мы видим, что выход 0 транзакции с хэш-кодом 319ba90f… имеет 1354164 сатоши (наименьшая стомиллионная доля биткоина), которые можно потратить. Два выхода транзакции тратят в сумме 1344164. Куда же деваются еще 10000 сатоши? Они оставлены в качестве оплаты за транзакцию майнеру, который включит эту транзакцию в блок.
Как вы уже догадались, транзакция может потратить только весь вход полностью, а не частично. Чтобы обойти эту проблему, вводится понятие «сдачи» — один из выходов отправляется получателю, а вот второй – возвращает «сдачу» с потраченного входа на свой собственный адрес. В нашем примере транзакции, первый выход – это 0.01 BTC оплаты, а второй выход — сдача. После создания транзакции, вам нужно подписать каждый вход секретным ключом, который соответствует этому адресу. Этот процесс для эллиптической криптографии не так уж и тривиален – но библиотеки-то нам на что? Они все за нас сделают, только дай правильный секретный ключ. Вот как эта наша транзакция выглядит, когда ее подписали:
0100000001aa02ce4965b5a83426d39990f571339c97ca54978ed48f6ad4ee45 160fa99b31000000008b48304502203bcabb367ca84b2af394597bff4a6169fa 55b156708557256d2c584f1bd54e1502210086fdf257e58dbb5e1f3b4686f438 5e86ea89e677a6c90a3c87ce276d88ad2b31014104e6eb4c73192bcc7b63f7e3 c05ed52c0d98abac6f6aa0876e2e57eeda6b60fe03098cb63633d08077b14cc3 0efe9bc5c9866ebc1297c03399e27381539025f887ffffffff0240420f000000 00001976a914a41d15ae657ad3bfd0846771a34d7584c37d54a288ac64400500 000000001976a914c4c5d791fcb4654a1ef5e03fe0ad3d9c598f982788ac0000
Теперь, наконец, мы можем послать подготовленную транзакцию в сеть, где ее подхватят и включат в блокчейн майнеры. Самый лучший способ сделать это программно – через интерфейс на blockchain.info/pushtx. И это, в общем-то, все – конец теории, вы теперь эксперт в биткоин-транзакциях! Ну, во всяком случае, это вполне рабочий минимум знаний, пока мы не стали рассуждать о платежных скриптах, схемах с арбитражем или с залогом и прочих продвинутых прелестях биткоин-транзакций. Но все это лучше оставить для другой статьи.
Bitcoind
Bitcoind является «эталонным клиентом», созданным основной командой биткоин-разработчиков. Это полноценный биткоин-узел, который загружает всю историю транзакций (blockchain) и обрабатывает транзакции. Bitcoind несколько ограничен по функциональности, например, он не может выдать вам историю транзакций по адресу, который вы не импортировали заранее. Тем не менее, он предоставляет достаточно мощный интерфейс для программиста. После загрузки Bitcoind и его инсталляции/сборки, первым шагом является создание файла конфигурации в папке Биткоина ( ~/.bitcoin
– ведь вы на Линуксе, верно?) со следующим содержанием:
rpcuser=user rpcpassword=pass rpcport=8332 txindex=1
Понятно, стоит заменить user/pass на собственное имя пользователя и пароль. Как только вы сделаете это, перейдите в каталог, содержащий исполняемый файл (/bin если вы инсталлировали готовую сборку, или куда вы там его сами собрали) и запустите демон:
> ./bitcoind --daemon
Теперь, у вас есть два пути взаимодействия с демоном bitcoind, чтобы заставить его выполнять ваши команды. Первый способ попроще: в командной строке, вводите «bitcoind» с указанием имени команды и аргументов. Например:
> ./bitcoind getblockhash 1 00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048 > ./bitcoind getblock 00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048 { "hash" : "00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048", "confirmations" : 212362, "size" : 215, "height" : 1, "version" : 1, "merkleroot" : "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098", "tx" : [ "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098" ], "time" : 1231469665, "nonce" : 2573394689, "bits" : "1d00ffff", "difficulty" : 1.00000000, "previousblockhash" : "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f", "nextblockhash" : "000000006a625f06636b8bb6ac7b960a8d03705d1ace08b1a19da3fdcc99ddbd" } > ./bitcoind getrawtransaction 0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098 01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000
Второй способ использует JSON-RPC. Это общий интерфейс, который позволяет подключаться к bitcoind и выполнять команды из любого языка – а возможно, даже с другого компьютера. В Wiki Биткоина есть страница с подробным описанием некоторых способов сделать JSON-RPC-вызов в различных языках программирования. Для краткости я приведу только два.
В Pythone:
import httplib, json, base64 def mkrequest(url,user,pass,method,params,hasresponse=True): connection = httplib.HTTPConnection(url) postdata = json.dumps({ "method": method, "params": params }) req = urllib2.Request('http://localhost:8001',postdata, { 'Authorization': b'Basic '+base64.b64encode(user+':'+pass), }) if hasresponse: return urllib2.urlopen(req).read().strip()
А вот так это можно сделать в командной строке с помощью curl:
curl --user <user> --pass <pass> --data-binary '{"method": <method>, "params": [<param1>,<param2>...] }' http://localhsot:8332
SX
Есть два альтернативных инструментов командной строки для работы с биткоин-транзакциями: pyBitcointools и SX. SX был создан Амиром Тааки, pyBitcointools написал Виталик Бутерин. Синтаксис очень похож, хотя есть и отличия. Установка SX является относительно простым делом — все, что вам нужно сделать, это загрузить скрипт install-sx.sh, установить пару библиотек, и запустить этот скрипт. В Ubuntu, скажем, последовательность команд выглядит следующим образом:
wget http://sx.dyne.org/install-sx.sh sudo apt-get install git build-essential autoconf libtool libboost-all-dev pkg-config libcurl4-openssl-dev libleveldb-dev libzmq-dev libconfig++-dev libncurses5-dev qrencode chmod +x install-sx.sh ./install-sx.sh
После установки SX, вы с ним можете много чего сделать. Скажем, если вы просто создаете платформу для обработки платежей, вам достаточно загрузить историю по какому-то адресу и, возможно, посмотреть подробно его транзакции:
Спасибо огромное!