Ich versuche, die TX-Generierungslogik in eine andere (und unpopuläre) Sprache zu portieren. Ich habe mir viel zu lange den Kopf dagegen geschlagen und hätte weggehen sollen, aber, naja, du weißt schon, Schließung und Sturheit.
Blockchain.info, Electrum und Bitcoin Core entschlüsseln alle meinen Versuch eines TX in etwas vernünftig aussehendes, wie zum Beispiel:
{
"txid" : "49c210ae472c5b5e39447e1f6d9bc020cd0f0075cc03d919afb0857a964e1f41",
"version" : 1,
"locktime" : 0,
"vin" : [
{
"txid" : "b097384c42a3be2730db3e3720a1806c76172b6b62b2b5ee007c2c6fd295cadf",
"vout" : 1,
"scriptSig" : {
"asm" : "30460221009f478737296e39bbcff2ef7c6f013acc25bea75941acd8573bcea83ca910018b022100e9bff518297fec344d6e7e42cabc5ec793c4be507af68210bdde803a8a2958ed0104d8f39341451e2e66a00ef010c815f1284bc5e3a187476aab319b2d127b7e219c9b9e68bff311c63474242a9baab34f7ddec05de2c45bd140a74a64621ccb42cb",
"hex" : "4930460221009f478737296e39bbcff2ef7c6f013acc25bea75941acd8573bcea83ca910018b022100e9bff518297fec344d6e7e42cabc5ec793c4be507af68210bdde803a8a2958ed014104d8f39341451e2e66a00ef010c815f1284bc5e3a187476aab319b2d127b7e219c9b9e68bff311c63474242a9baab34f7ddec05de2c45bd140a74a64621ccb42cb"
},
"sequence" : 4294967295
}
],
"vout" : [
{
"value" : 0.00439999,
"n" : 0,
"scriptPubKey" : {
"asm" : "OP_DUP OP_HASH160 7847eb9e366653aeb8857d541236fe4fd90c57e7 OP_EQUALVERIFY OP_CHECKSIG",
"hex" : "76a9147847eb9e366653aeb8857d541236fe4fd90c57e788ac",
"reqSigs" : 1,
"type" : "pubkeyhash",
"addresses" : [
"1BxzF8rgXtuiPuSN8azdMJgryzQSWt4Uoj"
]
}
}
]
}
Beim Versuch, eine Transaktion in Bitcoin Core zu senden, erhalte ich "Fehler -25". Beim Lesen anderer StackExchange-Posts und Googeln werden die möglichen Ursachen wie folgt aufgeführt:
"Beim Lesen des Quellcodes wird dieser Fehler zurückgegeben, wenn AcceptToMemoryPool fehlschlägt, aber nicht, wenn es fehlschlägt, weil die Transaktion ungültig ist. Gibt debug.log irgendetwas aus, wenn dies passiert?"
"Sie erhalten diesen obskuren RPC-Fehler, wenn Ihr TX Ausgaben verwendet, von denen Bitcoin noch nie gehört hat." Nichts erscheint in ~/.bitcoin/debug.log.
Beim Versuch, es mit dem Slash-Pushtx-Dienst von blockchain.info zu senden (oh, komm schon, gibt es ernsthaft keine weiße Liste für Websites, auf die ich verlinken kann?), erhalte ich „Skript führte zu einem nicht wahren Stack: []“, was impliziert, dass ich irgendwo einen Fehler in meiner Signaturlogik gemacht habe.
Ich bin durch diese gegangen:
http://procbits.com/2013/08/27/generating-a-bitcoin-address-with-javascript
http://www.righto.com/2014/02/bitcoins-hard-way-using-raw-bitcoin.html
Schritt-für-Schritt-Beispiel zum Einlösen einer Rohtransaktion erforderlich
Und andere, einschließlich verschiedener Ruby-, Python-, Java- und JavaScript-Implementierungen, aber ich brauche mehr als 10 Reputation, um mehr als 2 Links zu posten. Ich kann beim besten Willen nicht herausfinden, wo ich abweiche.
Ich weiß, dass Teile davon veraltet sind. Der private Schlüssel, mit dem ich beginne (von Electrum), ist nicht als komprimiert gekennzeichnet (33 Bytes nach DecodeBase58Check, wobei das letzte 0x01 ist), daher sollte der öffentliche Schlüssel in der Transaktion, aus der ich zu ziehen versuche, auch nicht komprimiert sein.
Der TX, den ich ausgeben möchte ( b097384c42a3be2730db3e3720a1806c76172b6b62b2b5ee007c2c6fd295cadf , zweite Ausgabe, auch bekannt als 1) mit diesem TX hat ein Ausgabeskript, das Pay to Public Key Hash (d9495c762aed3dba15eec648beb58a8a4) gemäß blockchain info ist. Der vollständige scriptPubKey des Prevouts lautet:
OP_DUP OP_HASH160 d9495c762aed3dba15eec648beb55a8a43b8d1bd OP_EQUALVERIFY OP_CHECKSIG
Mein privater Schlüssel, der von WIF dekodiert wurde und durch ecdsa::pub_from_priv(), ecdsa::pub_encode() läuft, stimmt mit diesem Wert überein.
Es scheint, als wäre es der schwierige Teil, das richtige Zeug zu hashen, bevor der Hash in die Signatur eingetragen wird. Ich hänge 0x01 an die Signatur an, nachdem sie aus ecdsa::Sign() kommt. Bevor der TX signiert wird, wird ihm 01000000 angehängt. scriptSig (das Skript in der Eingabe für den TX, den ich baue) ist "OP_DUP, OP_HASH160, PUSHDATA, Bitcoin-Adresse (Public Key Hash), OP_EQUALVERIFY, OP_CHECKSIG", bevor es signiert wird, dann wird es zu einem varstr der sig und des pubKey , und das dekodiert in vernünftig aussehenden Bytecode:
scriptSig:
0: OP_PUSHDATA 0x304602210094c538663c149f40929bb787d6174104a694181d063943a745e558b17d09e276022100b1812105ea6d7a8206c9019303a6459a9a2b2524b364debe69405b5d8b90c6c301
74: OP_PUSHDATA 0x04d8f39341451e2e66a00ef010c815f1284bc5e3a187476aab319b2d127b7e219c9b9e68bff311c63474242a9baab34f7ddec05de2c45bd140a74a64621ccb42cb
scriptPubKey:
0: OP_DUP
1: OP_HASH160
2: OP_PUSHDATA 0x7847eb9e366653aeb8857d541236fe4fd90c57e7
23: OP_EQUALVERIFY
24: OP_CHECKSIG
Die Verwendung des alten scriptPubKey als scriptSig wird angenähert und geht von einer einfachen Bezahlung bis zur Signatur aus, anstatt tatsächlich den genauen scriptPubKey aus dem TX zu ziehen, auf das gezogen wird, aber in diesem einfachen Fall scheinen sie zu stimmen.
Hier ist der rohe, (falsch?) signierte TX:
0100000001dfca95d26f2c7c00eeb5b2626b2b17766c80a120373edb3027bea3424c3897b0010000008b48304502202647239b48610693967a24c7c976f0df903891113c56f50b6e3368c3f73eefb0022100e372ab8bf76ab35cba1ce6c1890fb6b27bb4d6d54f080180b46a6ecc2ae09248014104d8f39341451e2e66a00ef010c815f1284bc5e3a187476aab319b2d127b7e219c9b9e68bff311c63474242a9baab34f7ddec05de2c45bd140a74a64621ccb42cbffffffff01c0b60600000000001976a9147847eb9e366653aeb8857d541236fe4fd90c57e788ac00000000
Hier ist der Code:
https://gist.github.com/scrottie/15f2fca963d164306dcb
PrivateKey auf Anfrage (da ist $1 drin).
Wenn jemand in der Lage ist, das wegzuwerfen und herauszufinden, wo ich falsch gelaufen bin, wäre ich sehr dankbar.
%&@!
Behoben mit dieser Änderung:
$privateKey = $privateKey->as_hex(); $privateKey =~ s{^0x}{} or die;
warn sprintf "doing: python sig.py '%s' '%s'\n", $privateKey, to_hex($s256);
open my $python, '-|', 'python', 'sig.py', $privateKey, to_hex($s256) or die $!;
my $sig = readline $python;
warn "python says for sig: $sig\n";
$sig =~ s{[^0-9a-fA-F]}{}g;
$sig = from_hex($sig);
Und diese Datei als sig.py hinzufügen:
import ecdsa
import ecdsa.der
import ecdsa.util
import sys
privateKey = sys.argv[1]
s256 = sys.argv[2]
# print("privateKey len: "); print(len(privateKey.decode('hex')))
# print(privateKey)
# print("s256 len: "); print(len(s256.decode('hex')))
# print(s256)
sk = ecdsa.SigningKey.from_string(privateKey.decode('hex'), curve=ecdsa.SECP256k1)
sig = sk.sign_digest(s256.decode('hex'), sigencode=ecdsa.util.sigencode_der) + '\01' # 01 is hashtype
print sig.encode('hex')
ich bin neu hier und täusche mich anscheinend selbst. Ich konnte die Module auf CPAN, die mit openssl zusammenarbeiten, nicht zum Laufen bringen, also hatte ich eine Option für die EC-Bibliothek, etwas, das in reinem Perl geschrieben war. Das hat anscheinend Probleme, obwohl es Unit-Tests besteht. Oder ich habe es falsch verwendet.
Das führte zu einer Ausgabe, die https://blockchain.info/pushtx dazu brachte , „Transaction Submitted“ zu sagen. Und dann bewegten sich die Münzen.
Vielen Dank an alle, die angehalten haben, um dies in Augenschein zu nehmen. Ich schulde dir ein Bier. Ich werde versuchen, es mit sehr, sehr guten Kommentaren und Dokumenten voranzutreiben.
Entschuldigung, ich verwende keine Perl-Sprache und habe keine Perl-Umgebung installiert, um Ihren Code zu debuggen
Sehen Sie sich an, wie Sie einen Basis-Tx einlösen können.
Ich sehe Schritt 13 nicht, in dem Sie 01000000 = SIGHASH_ALL an die Daten anhängen müssen, die Sie in Ihrer makeRawTransaction-Methode signieren
Amaclin
Schotte
Schotte
Schotte
Amaclin