Ich suche nach Einzelheiten zu Step15-17 von Redeeming a raw Tx Step By Step , was im Wesentlichen der Schritt ist, in dem die verkettete Raw-Tx-Struktur doppelt sha256-gehasht und dann mit einer ECDSA-Bibliothek signiert wird. Ich habe auch auf andere Rohtransaktionsleitfäden verwiesen ; Ich suche speziell, wie man eine rohe Hex-Tx-Struktur ohne GUI/Website/etc signiert
Ich habe ein Testnet- Tx mit Bitcoincore v0.10 (ein vollständiger Knoten) erstellt und dasselbe mit Python versucht und kann die rohe Tx-Struktur mit Python ecdsa nicht korrekt signieren .
Ich zeige zuerst die Bitcoincore-Befehle :
importprivkey 93FxXUeMJp93YQAtGeW5cE23gFN4sJbBr1RBmerLFVUDuqQqKL5
mu858WTEPiWWpAJRTMxC4ka6DJqiaCZiSB
createrawtransaction '[{"txid" : "72b764383b99fb3d112ac8b474a5d7c4242b75dbfee2d4e9cf9a6703d90f805a", "vout" : 1}]' '{"n1hjyVvYQPQtejJcANd5ZJM5rmxHCCgWL7" : 0.990}'
signrawtransaction 01000000015a800fd903679acfe9d4e2fedb752b24c4d7a574b4c82a113dfb993b3864b7720000000000ffffffff01c09ee605000000001976a914dd6cce9f255a8cc17bda8ba0373df8e861cb866e88ac00000000
Final bitcoincore hex Tx (mit signrawtransaction
):01000000015a800fd903679acfe9d4e2fedb752b24c4d7a574b4c82a113dfb993b3864b772010000008a47304402204d78d2e6c0f801573e4960fb8e51ad939380d119d25f97d15efdedf815b05f02022066bd2ab0b401e32e7ce67ea45f8224097eeafbef2335d563776e5efe6632732d01410479b22a5127d176a49d506c86f791031f94a389227ef46a8ddb725a88c944c37e3f753de6ee0b441a0237801f140810e111a1fd8276a2a5d0ee07224a1b551cc1ffffffff01c09ee605000000001976a914dd6cce9f255a8cc17bda8ba0373df8e861cb866e88ac00000000
Jetzt folgt der Python 2.7.9 -Code (FYI, mit iPython 2.0 , daher fehlt im folgenden Code ein Boilerplate):
# please excuse the hexlify/unhexlify, I work better in strings than bytes
import __future__
from pybitcointools import sha256
import hashlib, ecdsa
from ecdsa import SigningKey, SECP256k1
addr, pubkey = 'mu858WTEPiWWpAJRTMxC4ka6DJqiaCZiSB', '0479b22a5127d176a49d506c86f791031f94a389227ef46a8ddb725a88c944c37e3f753de6ee0b441a0237801f140810e111a1fd8276a2a5d0ee07224a1b551cc1'
rawtx = '01000000015a800fd903679acfe9d4e2fedb752b24c4d7a574b4c82a113dfb993b3864b7720100000000ffffffff01c09ee605000000001976a914dd6cce9f255a8cc17bda8ba0373df8e861cb866e88ac00000000' # TX structure with 00 as scriptSig, from bitcoincore createrawtransaction
# replacing the '00' scriptSig value
unsigned.append(rawtx[:82])
unsigned.append('19'+'76a914953de657be4b305f606d9a9fbd35b070a682475788ac') # scriptSig = scriptPubKey input
unsigned.append(rawtx[84:])
unsigned.append('01000000') # appending sighash_all
unsigned = ''.join(unsigned)
unsigned = '01000000015a800fd903679acfe9d4e2fedb752b24c4d7a574b4c82a113dfb993b3864b772010000001976a914953de657be4b305f606d9a9fbd35b070a682475788acffffffff01c09ee605000000001976a914dd6cce9f255a8cc17bda8ba0373df8e861cb866e88ac0000000001000000'
# See https://github.com/warner/python-ecdsa/blob/master/README.md
sig1 = sk.sign(sha256(sha256(unsigned)), hashfunc=hashlib.sha256, sigencode=ecdsa.util.sigencode_der) # note this references 2 different sha256 functions
sig2 = [hex(len(sig1 + '\x01'))[2:], hexlify(sig1), hexlify('\x01'), hex(len(unhexlify(pubkey)))[2:], pubkey]
sig2
>>> ['48', '304502200e98d54ad642488121fa1fd4d055ff8f5b40773a21ecb42b5ef44ed9fd3b103c022100a2a56ffc3f27021a4be5d1d7a3016eff08fe7f550a4a894cca845ceab54dc53b', '01', '41', '0479b22a5127d176a49d506c86f791031f94a389227ef46a8ddb725a88c944c37e3f753de6ee0b441a0237801f140810e111a1fd8276a2a5d0ee07224a1b551cc1']
sig2 = len(''.join(map(unhexlify, sig2)))
hex(len(''.join(map(unhexlify, sig2))))[2:]
>>> '8b' # push 139 bytes
sig3
>>> 8b48304502200e98d54ad642488121fa1fd4d055ff8f5b40773a21ecb42b5ef44ed9fd3b103c022100a2a56ffc3f27021a4be5d1d7a3016eff08fe7f550a4a894cca845ceab54dc53b01410479b22a5127d176a49d506c86f791031f94a389227ef46a8ddb725a88c944c37e3f753de6ee0b441a0237801f140810e111a1fd8276a2a5d0ee07224a1b551cc1
signed = unsigned[:82] + sig3 + unsigned[84:] # inserting the signature into the 00 the core software uses in place of ScriptSig
Endgültiger ( ungültiger ) Python-Tx:
01000000015a800fd903679acfe9d4e2fedb752b24c4d7a574b4c82a113dfb993b3864b772010000008b48304502200e98d54ad642488121fa1fd4d055ff8f5b40773a21ecb42b5ef44ed9fd3b103c022100a2a56ffc3f27021a4be5d1d7a3016eff08fe7f550a4a894cca845ceab54dc53b01410479b22a5127d176a49d506c86f791031f94a389227ef46a8ddb725a88c944c37e3f753de6ee0b441a0237801f140810e111a1fd8276a2a5d0ee07224a1b551cc1ffffffff01c09ee605000000001976a914dd6cce9f255a8cc17bda8ba0373df8e861cb866e88ac00000000
Das Senden des von Python generierten Tx funktioniert nicht. Wenn ich sendrawtransaction <PYTHON HEX>
in Bitcoincore einen ungültigen Signaturfehler zurückgebe (insbesondere 16: Mandatory-Script-Verify-Flag-Failed (Skript ohne Fehler ausgewertet, aber mit einem falschen/leeren obersten Stack-Element beendet) (Code -26) ).
(TL;DR) FRAGE : Was mache ich falsch, wenn ich die rohe Transaktionsstruktur manuell signiere?
NB: Mir ist bewusst, dass pybitcointools und verwandte Bibliotheken Txs signieren können, aber ich suche nach Einzelheiten , da selbst diese beiden sehr gründlichen Bitcoin SE-Ressourcen ( LINK1 , LINK2 ) an den Details vorbeigehen. Ich würde eine Antwort für Python ECDSA oder PyCrypto bevorzugen , aber OpenSSL ist meiner Meinung nach die nächstbeste Antwort.
OK, ich habe herausgefunden, wie man den rohen Tx mit Python ecdsa signiert. Ich gehe es durch:
Abrufen:
createrawtransaction '[{"txid" : "72b764383b99fb3d112ac8b474a5d7c4242b75dbfee2d4e9cf9a6703d90f805a", "vout" : 1}]' '{"n2kx7k6JuA5Wy27fawaeiPX7dq8mbRDPAv" : 0.99}'
=01000000015a800fd903679acfe9d4e2fedb752b24c4d7a574b4c82a113dfb993b3864b7720100000000ffffffff01c09ee605000000001976a914e900510876cb689f1db6fa982376c301362b740c88ac00000000
Und dann fügen Sie den scriptPubKey für scriptSig's hinzu 00
:
unsigned = '01000000015a800fd903679acfe9d4e2fedb752b24c4d7a574b4c82a113dfb993b3864b772010000001976a914953de657be4b305f606d9a9fbd35b070a682475788acffffffff01c09ee605000000001976a914dd6cce9f255a8cc17bda8ba0373df8e861cb866e88ac0000000001000000'
Hinweis unsigned
hat das 01000000
angehängt, weil das SIGNHASH ist 01
(das in einer Minute auch an die DER-Signatur angehängt wird)
Also verdoppeln wir SHA256- Bytes und geben txhash
als Bytes zurück :txhash = hashlib.sha256(hashlib.sha256(unsigned.decode('hex')).digest()).digest()
Wir brauchen auch den privkey für mu858WTEPiWWpAJRTMxC4ka6DJqiaCZiSB
(in geheimer Exponentenform, dh hex): privkey = 'dc57c6d067376c36bbed632c9d00f03767867f337d5a86b5b0308a60004f08ee'.zfill(64)
privkey = 'dc57c6d067376c36bbed632c9d00f03767867f337d5a86b5b0308a60004f08ee'
Jetzt signieren wir mit diesem korrigierten Code :
signingkey = ecdsa.SigningKey.from_string(privkey.decode('hex'), curve=ecdsa.SECP256k1)
SIG = signingkey.sign_digest(txhash, sigencode=ecdsa.util.sigencode_der) +'01'.decode('hex')
Dies ist Arbeitscode. Von hier an machen wir einfach die Unterschrift:
ScriptSig
=<varint of total sig length>
<SIG from code, including appended 01 SIGNHASH>
<length of pubkey (0x21 or 0x41)>
<pubkey>
wopubkey = '0479b22a5127d176a49d506c86f791031f94a389227ef46a8ddb725a88c944c37e3f753de6ee0b441a0237801f140810e111a1fd8276a2a5d0ee07224a1b551cc1
Geben Sie uns ein gültiges signiertes Tx , ohne Bitcoincore zu verwenden :
01000000015a800fd903679acfe9d4e2fedb752b24c4d7a574b4c82a113dfb993b3864b772010000008a47304402204d78d2e6c0f801573e4960fb8e51ad939380d119d25f97d15efdedf815b05f02022066bd2ab0b401e32e7ce67ea45f8224097eeafbef2335d563776e5efe6632732d01410479b22a5127d176a49d506c86f791031f94a389227ef46a8ddb725a88c944c37e3f753de6ee0b441a0237801f140810e111a1fd8276a2a5d0ee07224a1b551cc1ffffffff01c09ee605000000001976a914dd6cce9f255a8cc17bda8ba0373df8e861cb866e88ac00000000
SIG
wird <r><s>
miteinander verkettet. Wir müssen überprüfen, s < N/2
wo N
die Kurvenreihenfolge ist, 115792089237316195423570985008687907852837564279074904382605163141518161494337. Wenn s>N/2
, danns = N-s
sigencode=ecdsa.util.sigencode_der
durchsigencode=ecdsa.util.sigencode_der_canonize
signingkey = ecdsa.SigningKey.from_string(privkey.decode('hex'), curve=ecdsa.SECP256k1)
Ihnen einfach die r,s-Werte oder etwas anderes? Ich benutze das überhaupt nicht. Ich versuche nur, meinen eigenen Code zu debuggen, wo mein Roh-TX in Ordnung ist, und meine Methoden zur Berechnung von r,s-Werten bekannte Tests bestehen, aber ich kann anscheinend kein signiertes TX im Vergleich zu Bitcoin Core duplizieren, und dieses kleine bisschen könnte sein warum? Würdest du @WizardOfOzzie wissen?
Morsecoder
Morsecoder
Zauberer von Ozzie
Zauberer von Ozzie