Estaba siguiendo https://bitcointalk.org/index.php?topic=453086.0 para crear un mensaje en OP_RETURN. Puedo decodificar mi transacción sin procesar, pero en signrawtransaction da
error: {"código":-22,"mensaje":"Error en la decodificación de TX"}
Validé la dirección, ¿hay algo que falta en ese tutorial?
Escribí un pequeño programa de demostración que coloca un fragmento de datos en un script OP_RETURN. Requiere una instancia de bitcoin que acepte conexiones RPC, aunque podría implementarse sin eso. Puedes encontrarlo en github aquí . Ha sido probado, pero solo en testnet. Voy a revisar el código y explicar lo que está haciendo.
[...]
logging.basicConfig()
logging.getLogger("BitcoinRPC").setLevel(logging.DEBUG)
Esto hace que el registro sea más detallado. Es útil porque muestra qué llamadas RPC se están realizando.
rpc_user = "bitcoinrpc"
rpc_password = "87Y9A2gs25E9HDPGc9axqSqzxMR2MyTtrMkYc5KiZk2Z"
rpc = AuthServiceProxy("http://%s:%s@127.0.0.1:18332/" % (rpc_user, rpc_password))
Tenga en cuenta que su contraseña será diferente y que utilizará el puerto 8332 para la red principal en lugar del puerto 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
La - Decimal("0.005")
parte es para que paguemos una tarifa de transacción.
# 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"
Estas son dos codificaciones diferentes de un hash de clave de pago a público de todos ceros. La superior es la representación de la red principal y la inferior es la representación de la red de prueba.
# My change address
change_address = "mhZuYnuMCZLjZKeDMnY48xsR5qkjq7bAr9"
Recuerde, esta es mi dirección de cambio. Si no lo cambias, me estarás enviando dinero.
tx = rpc.createrawtransaction([{"txid": txid, "vout": vout}], \
{change_address: change_amount, \
dummy_address: SATOSHI})
Y ahora tenemos una transacción real. Sin embargo, no contiene ninguno de nuestros propios datos, por lo que tendremos que arreglarlo.
# 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"
Esto es un poco un truco. En lugar de crear nuestra propia salida, creamos una salida ficticia, luego buscamos el patrón que crea y lo reemplazamos. Probablemente haya una mejor manera de hacer esto, pero esto parece más fácil.
# 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)
A continuación, creamos los datos que queremos poner en la cadena de bloques. Estoy usando la cadena Melons.
, pero podrías usar cualquier cosa. (Sin embargo, más de 40 bytes no es estándar). Cubrí la mayor parte de esto en mi otra respuesta .
Este código se romperá si los datos tienen más de 75 bytes. Si lo necesita para más que eso, puede usar OP_PUSHDATA1 en lugar de los datos push de un solo byte que estoy usando aquí.
#Append int of length to start
newScriptPubKey = hexlify(chr(len(unhexlify(newScriptPubKey)))) + newScriptPubKey
Esta parte es un poco diferente a mi otra respuesta, porque también debemos incluir la longitud de scriptPubKey. Este código se romperá con datos de más de 251 bytes. Si desea que funcione con datos más largos que eso, codifique una variante correctamente.
if oldScriptPubKey not in tx:
raise Exception("Something broke!")
Comprobación de errores para este método muy destartalado.
tx = tx.replace(oldScriptPubKey, newScriptPubKey)
Finalmente, un reemplazo de cadena cambia el nuevo script por el antiguo.
tx = rpc.signrawtransaction(tx)['hex']
Bitcoin maneja el levantamiento agitado aquí.
rpc.sendrawtransaction(tx)
¡Hecho! Ahora solo espere a que su transacción entre en un bloque.
Ejecuté el código ( salida ) y produje una transacción, que puede ver en Block Explorer aquí . Si copia la cadena junto a OP_RETURN y la pega en un convertidor hexadecimal a ASCII , obtiene...
Melons.
¡Hecho!
Encontré esta página web útil mientras escribía esto.
scriptsig
scriptPubKey, en realidad. does that mean the tx will be removed / invalidated by the network?
Realmente no. Se eliminará del conjunto de salida de transacciones no gastadas en algunos clientes, pero muchos clientes aún lo recordarán. (Deben hacerlo, porque necesitan demostrar a los nuevos clientes que es solo una transacción OP_RETURN).getnewaddress
) y luego txhex = createrawtransaction
. Luego obtengo el script hexadecimal por decodedtx = decoderawtransaction txhex
y oldScriptHex = decodedtx.scriptPubKey.hex
. Luego txhex.replace(oldScriptHex, newScriptHex)
, este enfoque ya no decodifica (código -22; la decodificación de TX falló). ¿por qué? newScriptHex
es idéntica en su versión y la mía.createrawtransaction
con un me vout
gusta {"data": "your hex data"}
y no tiene que lidiar con el reemplazo.Puede facilitarle la vida utilizando una de nuestras bibliotecas OP_RETURN:
El código también le mostrará exactamente cómo se hace.
http://digitalcommons.augustana.edu/cscfaculty/1/
Artículo académico que describe los diferentes métodos de inserción de datos para la cadena de bloques de Bitcoin.
Matthieu
mago
Escalón