Actualmente estoy tratando de descubrir cómo usar Python para construir una transacción con OP_RETURN. Traté de codificar el mensaje yo mismo y no tuve suerte. Encontré una función, OPReturn(), en Internet, pero cuando intento usarla, aparece el error (de la API de transmisión de Blockchain.info):Exception: None Standard Script Output OP_RETURN 594f4c4f53574147
Código:
# coding: utf-8
from bitcoin import *
import binascii
from test import *
priv = sha256('brain wallet')
pub = privtopub(priv)
addr = pubtoaddr(pub)
inputs = unspent(addr)
message = "YOLOSWAG"
FullLen = format(len(message)+2,'x').rjust(2,'0')
MessageLen = format(len(message),'x').rjust(2,'0')
ID = binascii.hexlify(str(message))
snd = "6a"+MessageLen+ID
outputs = [{'value': 50000, 'address': addr}, {'value': 0, 'script': snd}]
fee = 10000
tx = mksend(inputs, outputs, addr, fee)
dt = deserialize(tx)
ins = dt['ins']
#print addr
#print ins
for ind, elm in enumerate(ins):
print elm
tx = sign(tx, ind, priv)
#print tx
print(pushtx(tx))
He bifurcado la biblioteca pybitcointools para devolver una OP_RETURN
cadena hexadecimal con el formato correcto, o insertarla OP_RETURN
en una transacción hexadecimal sin procesar.
Mi tenedor se puede encontrar aquí . El código es el siguiente:
from bitcoin.pyspecials import safe_hexlify, from_string_to_bytes, from_int_to_byte, from_string_to_bytes
def mk_opreturn(msg, rawtx=None, json=0):
def op_push(data):
import struct
if len(data) < 0x4c:
return from_int_to_byte(len(data)) + from_string_to_bytes(data)
elif len(data) < 0xff:
return from_int_to_byte(76) + struct.pack('<B', len(data)) + from_string_to_bytes(data)
elif len(data) < 0xffff:
return from_int_to_byte(77) + struct.pack('<H', len(data)) + from_string_to_bytes(data)
elif len(data) < 0xffffffff:
return from_int_to_byte(78) + struct.pack('<I', len(data)) + from_string_to_bytes(data)
else: raise Exception("Input data error. Rawtx must be hex chars" \
+ "0xffffffff > len(data) > 0")
orhex = safe_hexlify(b'\x6a' + op_push(msg))
orjson = {'script' : orhex, 'value' : 0}
if rawtx is not None:
try:
txo = deserialize(rawtx)
if not 'outs' in txo.keys(): raise Exception("OP_Return cannot be the sole output!")
txo['outs'].append(orjson)
newrawtx = serialize(txo)
return newrawtx
except:
raise Exception("Raw Tx Error!")
return orhex if not json else orjson
Tenga en cuenta que el nombre del módulo se ha cambiado a btc
(desde bitcoin
) en mi bifurcación.
Para ejecutar esto, usará os.chdir("c:/python/pybitcointools")
(o cualquier directorio en el que se haya descargado. Luego from bitcoin import *
. Ahora, usemos msg = 'The enemy of my enemy is my friend'
y rawtx = "01000000016e3cd2b24fcf49259db29888ec5fe6521070041cb8c7bb2017537046f9e00f2b0000000000ffffffff0168d61100000000001976a91469bbbb16301e40b9fb67130e1aa53a2281d60af088ac00000000"
.
mk_opreturn(msg, rawtx)
devoluciones:
01000000016e3cd2b24fcf49259db29888ec5fe6521070041cb8c7bb2017537046f9e00f2b0000000000ffffffff0268d61100000000001976a91469bbbb16301e40b9fb67130e1aa53a2281d60af088ac0000000000000000246a2254686520656e656d79206f66206d7920656e656d79206973206d7920667269656e6400000000
Este es el Tx sin procesar con el OP_RETURN
correctamente insertado. Ejecute la función sin el rawtx
parámetro y devuelve la cadena.6a2254686520656e656d79206f66206d7920656e656d79206973206d7920667269656e64
El script es simplemente (por así decirlo) tomando una transacción sin procesar y empalmando un número hexadecimal que representa una salida Tx adicional. Entonces está buscando ffffffff ( secuencia ) y agregando 6a
hex encoding of your msg
(hasta 20 bytes)
El mensaje necesita convertirse a hexadecimal (lo que hace el código).
El código funciona bien para mí, aunque todavía tengo que intentar transmitir. Basado en su error citado
Recibo el error (de la API de transmisión de Blockchain.info): Excepción: Ninguna Salida de script estándar OP_RETURN 594f4c4f53574147
Tendría que decir que BCI está reaccionando a la MessageLen
parte del código. Debe haber un OP_PUSHDATA1
( 0x4c
) entre OP_RETURN
( 0x6a
) y la longitud del mensaje de 1 byte, 0x08
.
Probar:6a4c08594f4c4f53574147
Alternativamente, intente con otro servicio para enviar el Tx sin procesar, por ejemplo:
ID = binascii.hexlify(str(message))
ya no se ocupa de eso?2a6a28
40 byte data
, donde 2a
dice empujar los siguientes 42 bytes, 6a
es OP_RETURN y 28
dice empujar los 40 bytes. Este es el formato requerido para Bitcoincore.Es posible que encuentre útil nuestra biblioteca python-OP_RETURN, ya sea para usarla de forma inmediata o para mirar dentro para ver cómo estamos creando transacciones OP_RETURN.
https://github.com/coinspark/python-OP_RETURN
También tiene una característica interesante para almacenar datos de tamaño arbitrario en la cadena de bloques mediante múltiples transacciones encadenadas con OP_RETURN y para recuperar esos datos mediante un único número de referencia de 12 dígitos.
'OP_RETURN.py", line 456, in OP_RETURN_bitcoin_cmd
if not len(port):
TypeError: object of type 'int' has no len()'
OP_RETURN_BITCOIN_PORT
usando un número entero en una cadena en lugar de un número entero.
Nick ODell
mago de ozzie
mago de ozzie