Ich bin https://bitcointalk.org/index.php?topic=453086.0 gefolgt, um eine Nachricht in OP_RETURN zu erstellen. Ich kann meine Rohtransaktion entschlüsseln, aber bei signrawtransaction gibt es sie
error: {"code":-22,"message":"TX-Decodierung fehlgeschlagen"}
Ich habe die Adresse validiert, gibt es etwas, das in diesem Tutorial fehlt.
Ich habe ein kleines Demoprogramm geschrieben, das einen Datenausschnitt in ein OP_RETURN-Skript einfügt. Es erfordert eine Bitcoin-Instanz, die RPC-Verbindungen akzeptiert, obwohl es auch ohne diese implementiert werden könnte. Sie finden es hier auf github . Es wurde getestet, aber nur auf Testnet. Ich werde den Code durchgehen und erklären, was er tut.
[...]
logging.basicConfig()
logging.getLogger("BitcoinRPC").setLevel(logging.DEBUG)
Dadurch wird die Protokollierung ausführlicher. Es ist praktisch, weil es zeigt, welche RPC-Aufrufe getätigt werden.
rpc_user = "bitcoinrpc"
rpc_password = "87Y9A2gs25E9HDPGc9axqSqzxMR2MyTtrMkYc5KiZk2Z"
rpc = AuthServiceProxy("http://%s:%s@127.0.0.1:18332/" % (rpc_user, rpc_password))
Beachten Sie, dass Ihr Passwort anders sein wird und dass Sie Port 8332 für Mainnet anstelle von Port 18332 verwenden.
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
Der - Decimal("0.005")
Teil ist so, dass wir eine Transaktionsgebühr zahlen.
# 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"
Dies sind zwei unterschiedliche Kodierungen eines Pay to Public Key Hash aus lauter Nullen. Die obere ist die Mainnet-Darstellung und die untere die Testnet-Darstellung.
# My change address
change_address = "mhZuYnuMCZLjZKeDMnY48xsR5qkjq7bAr9"
Denken Sie daran, dies ist meine Änderungsadresse. Wenn Sie es nicht ändern, schicken Sie mir Geld.
tx = rpc.createrawtransaction([{"txid": txid, "vout": vout}], \
{change_address: change_amount, \
dummy_address: SATOSHI})
Und jetzt haben wir eine tatsächliche Transaktion. Es enthält jedoch keine unserer eigenen Daten, also müssen wir das beheben.
# 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"
Das ist ein kleiner Hack. Anstatt unsere eigene Ausgabe zu erstellen, erstellen wir eine Dummy-Ausgabe, suchen dann nach dem Muster, das sie erzeugt, und ersetzen sie. Es gibt wahrscheinlich einen besseren Weg, dies zu tun, aber das scheint am einfachsten zu sein.
# 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)
Als nächstes erstellen wir die Daten, die wir in die Blockchain einfügen möchten. Ich verwende die Zeichenfolge Melons.
, aber Sie könnten alles verwenden. (Über 40 Bytes ist jedoch kein Standard.) Ich habe das meiste davon in meiner anderen Antwort behandelt .
Dieser Code bricht, wenn die Daten länger als 75 Byte sind. Wenn Sie es für mehr als das brauchen, können Sie OP_PUSHDATA1 anstelle der Single-Byte-Pushdata verwenden, die ich hier verwende.
#Append int of length to start
newScriptPubKey = hexlify(chr(len(unhexlify(newScriptPubKey)))) + newScriptPubKey
Dieser Teil unterscheidet sich ein wenig von meiner anderen Antwort, da wir auch die Länge des scriptPubKey angeben müssen. Dieser Code bricht bei Daten, die länger als 251 Bytes sind. Wenn Sie möchten, dass es länger an Daten arbeitet, codieren Sie eine Variante richtig.
if oldScriptPubKey not in tx:
raise Exception("Something broke!")
Fehler bei der Überprüfung dieser sehr wackeligen Methode.
tx = tx.replace(oldScriptPubKey, newScriptPubKey)
Schließlich tauscht ein String-Replace das neue Skript gegen das alte aus.
tx = rpc.signrawtransaction(tx)['hex']
Bitcoin übernimmt hier das wuchtige Heben.
rpc.sendrawtransaction(tx)
Fertig! Warten Sie jetzt einfach, bis Ihre Transaktion in einen Block gelangt.
Ich habe den Code ausgeführt ( Ausgabe ) und eine Transaktion erstellt, die Sie hier im Block Explorer sehen können . Wenn Sie die Zeichenfolge neben OP_RETURN kopieren und in einen Hex-zu-ASCII-Konverter einfügen , erhalten Sie ...
Melons.
Fertig!
Ich fand diese Webseite hilfreich, während ich dies schrieb.
scriptsig
scriptPubKey, eigentlich. does that mean the tx will be removed / invalidated by the network?
Nicht wirklich. Es wird in einigen Clients aus dem Ausgabesatz für nicht ausgegebene Transaktionen entfernt, aber viele Clients werden sich immer noch daran erinnern. (Das müssen sie, weil sie neuen Kunden beweisen müssen, dass es sich nur um eine OP_RETURN-Transaktion handelt.)getnewaddress
) eingebe und dann txhex = createrawtransaction
. Dann bekomme ich das Skript hex durch decodedtx = decoderawtransaction txhex
und oldScriptHex = decodedtx.scriptPubKey.hex
. Dann txhex.replace(oldScriptHex, newScriptHex)
und dieser Ansatz dekodiert nicht mehr (Code -22; TX-Dekodierung fehlgeschlagen). warum? newScriptHex
ist in deiner und meiner Version identisch.createrawtransaction
mit einem vout
Like verwenden {"data": "your hex data"}
und müssen sich nicht um das Ersetzen kümmern.Sie können sich das Leben leichter machen, indem Sie eine unserer OP_RETURN-Bibliotheken verwenden:
Der Code zeigt Ihnen auch genau, wie es gemacht wird.
http://digitalcommons.augustana.edu/cscfaculty/1/
Akademisches Papier, das die verschiedenen Methoden der Dateneinfügung für die Blockchain von Bitcoin beschreibt.
Matthias
Zauberer
Echelon