Я следил за https://bitcointalk.org/index.php?topic=453086.0 для создания сообщения в OP_RETURN. Я могу декодировать свою необработанную транзакцию, но на signrawtransaction она дает
ошибка: {"код":-22,"сообщение":"Ошибка декодирования TX"}
Я проверил адрес, есть ли что-то, чего не хватает в этом руководстве.
Я написал небольшую демонстрационную программу, которая помещает фрагмент данных в сценарий OP_RETURN. Для этого требуется экземпляр биткойна, который принимает соединения RPC, хотя его можно реализовать и без него. Вы можете найти его на github здесь . Это было протестировано, но только в тестовой сети. Я собираюсь просмотреть код и объяснить, что он делает.
[...]
logging.basicConfig()
logging.getLogger("BitcoinRPC").setLevel(logging.DEBUG)
Это делает ведение журнала более подробным. Это удобно, потому что показывает, какие вызовы RPC выполняются.
rpc_user = "bitcoinrpc"
rpc_password = "87Y9A2gs25E9HDPGc9axqSqzxMR2MyTtrMkYc5KiZk2Z"
rpc = AuthServiceProxy("http://%s:%s@127.0.0.1:18332/" % (rpc_user, rpc_password))
Обратите внимание, что ваш пароль будет другим, и вы используете порт 8332 для основной сети вместо порта 18332.
first_unspent = rpc.listunspent()[0]
txid = first_unspent['txid']
vout = first_unspent['vout']
input_amount = first_unspent['amount']
SATOSHI = Decimal("0.00000001")
change_amount = input_amount - Decimal("0.005") - SATOSHI
Часть - Decimal("0.005")
заключается в том, что мы платим комиссию за транзакцию.
# Marker address we're going to replace
# Produces a pattern that's easy to search for
mainnet = 0
if mainnet:
dummy_address = "1111111111111111111114oLvT2"
else:
dummy_address = "mfWxJ45yp2SFn7UciZyNpvDKrzbhyfKrY8"
Это две разные кодировки хэша Pay to Public Key, состоящего из всех нулей. Верхний — это представление основной сети, а нижний — представление тестовой сети.
# My change address
change_address = "mhZuYnuMCZLjZKeDMnY48xsR5qkjq7bAr9"
Помните, это мой адрес смены. Если вы не поменяете его, вы будете присылать мне деньги.
tx = rpc.createrawtransaction([{"txid": txid, "vout": vout}], \
{change_address: change_amount, \
dummy_address: SATOSHI})
И вот у нас есть реальная сделка. Однако он не содержит никаких наших собственных данных, поэтому нам придется это исправить.
# Pattern to replace
# Represents length of script, then OP_DUP OP_HASH160,
# then length of hash, then 20 bytes of zeros, OP_EQUALVERIFY OP_CHECKSIG
oldScriptPubKey = "1976a914000000000000000000000000000000000000000088ac"
Это немного взломать. Вместо того, чтобы создавать собственный вывод, мы создаем фиктивный вывод, затем ищем полученный шаблон и заменяем его. Вероятно, есть лучший способ сделать это, но это кажется самым простым.
# Data to insert
data = "Melons."
if len(data) > 75:
raise Exception("Can't contain this much data-use OP_PUSHDATA1")
newScriptPubKey = "6a" + hexlify(chr(len(data))) + hexlify(data)
Затем мы создаем данные, которые хотим поместить в блокчейн. Я использую строку Melons.
, но вы можете использовать что угодно. (Однако более 40 байт нестандартны.) Я рассмотрел большую часть этого в своем другом ответе .
Этот код сломается, если данные длиннее 75 байт. Если вам это нужно для большего, вы можете использовать OP_PUSHDATA1 вместо однобайтовых pushdata, которые я использую здесь.
#Append int of length to start
newScriptPubKey = hexlify(chr(len(unhexlify(newScriptPubKey)))) + newScriptPubKey
Эта часть немного отличается от моего другого ответа, потому что нам также нужно включить длину scriptPubKey. Этот код сломается, если данные длиннее 251 байта. Если вы хотите, чтобы он работал с более длинными данными, правильно закодируйте вариант.
if oldScriptPubKey not in tx:
raise Exception("Something broke!")
Проверка ошибок для этого очень шаткого метода.
tx = tx.replace(oldScriptPubKey, newScriptPubKey)
Наконец, замена строки заменяет новый скрипт на старый.
tx = rpc.signrawtransaction(tx)['hex']
Биткойн справляется с подъемом здесь.
rpc.sendrawtransaction(tx)
Сделанный! Теперь просто подождите, пока ваша транзакция попадет в блок.
Я запустил код ( output ) и произвел транзакцию, которую вы можете увидеть в Block Explorer здесь . Если вы скопируете строку рядом с OP_RETURN и вставите ее в преобразователь Hex в ASCII , вы получите...
Melons.
Сделанный!
Я нашел эту веб-страницу полезной при написании этого.
scriptsig
scriptPubKey, на самом деле. does that mean the tx will be removed / invalidated by the network?
Не совсем. Он будет удален из набора неизрасходованных транзакций в некоторых клиентах, но многие клиенты все равно его помнят. (Они должны, потому что им нужно доказать новым клиентам, что это просто транзакция OP_RETURN.)getnewaddress
), а затем txhex = createrawtransaction
. Затем я получаю шестнадцатеричный сценарий с помощью decodedtx = decoderawtransaction txhex
и oldScriptHex = decodedtx.scriptPubKey.hex
. Тогда txhex.replace(oldScriptHex, newScriptHex)
и этот подход больше не декодируется (код -22; декодирование TX не удалось). Почему? newScriptHex
идентичен в вашей версии и моей.createrawtransaction
с vout
подобным {"data": "your hex data"}
и не иметь дело с заменой.Вы можете упростить себе жизнь, используя одну из наших библиотек OP_RETURN:
Код также покажет вам, как именно это делается.
http://digitalcommons.augustana.edu/cscfaculty/1/
Научная статья, описывающая различные методы вставки данных для блокчейна Биткойн.
Матьё
умник
Эшелон