|
|
@ -359,8 +359,9 @@ def parse_scriptSig(d, _bytes): |
|
|
|
match = [ opcodes.OP_0 ] + [ opcodes.OP_PUSHDATA4 ] * (len(decoded) - 1) |
|
|
|
if match_decoded(decoded, match): |
|
|
|
x_sig = [bh2u(x[1]) for x in decoded[1:-1]] |
|
|
|
redeem_script = bh2u(decoded[-1][1]) |
|
|
|
try: |
|
|
|
m, n, x_pubkeys, pubkeys, redeemScript = parse_redeemScript(decoded[-1][1]) |
|
|
|
m, n, x_pubkeys, pubkeys = parse_redeemScript_multisig(bfh(redeem_script)) |
|
|
|
except NotRecognizedRedeemScript: |
|
|
|
print_error("parse_scriptSig: cannot find address in input script (p2sh?)", |
|
|
|
bh2u(_bytes)) |
|
|
@ -373,16 +374,16 @@ def parse_scriptSig(d, _bytes): |
|
|
|
d['signatures'] = parse_sig(x_sig) |
|
|
|
d['x_pubkeys'] = x_pubkeys |
|
|
|
d['pubkeys'] = pubkeys |
|
|
|
d['redeemScript'] = redeemScript |
|
|
|
d['address'] = hash160_to_p2sh(hash_160(bfh(redeemScript))) |
|
|
|
d['redeem_script'] = redeem_script |
|
|
|
d['address'] = hash160_to_p2sh(hash_160(bfh(redeem_script))) |
|
|
|
return |
|
|
|
|
|
|
|
print_error("parse_scriptSig: cannot find address in input script (unknown)", |
|
|
|
bh2u(_bytes)) |
|
|
|
|
|
|
|
|
|
|
|
def parse_redeemScript(s): |
|
|
|
dec2 = [ x for x in script_GetOp(s) ] |
|
|
|
def parse_redeemScript_multisig(redeem_script): |
|
|
|
dec2 = [ x for x in script_GetOp(redeem_script) ] |
|
|
|
try: |
|
|
|
m = dec2[0][0] - opcodes.OP_1 + 1 |
|
|
|
n = dec2[-2][0] - opcodes.OP_1 + 1 |
|
|
@ -395,8 +396,10 @@ def parse_redeemScript(s): |
|
|
|
raise NotRecognizedRedeemScript() |
|
|
|
x_pubkeys = [bh2u(x[1]) for x in dec2[1:-2]] |
|
|
|
pubkeys = [safe_parse_pubkey(x) for x in x_pubkeys] |
|
|
|
redeemScript = multisig_script(pubkeys, m) |
|
|
|
return m, n, x_pubkeys, pubkeys, redeemScript |
|
|
|
redeem_script2 = bfh(multisig_script(pubkeys, m)) |
|
|
|
if redeem_script2 != redeem_script: |
|
|
|
raise NotRecognizedRedeemScript() |
|
|
|
return m, n, x_pubkeys, pubkeys |
|
|
|
|
|
|
|
|
|
|
|
def get_address_from_output_script(_bytes, *, net=None): |
|
|
@ -471,8 +474,7 @@ def parse_witness(vds, txin): |
|
|
|
# now 'n' is the number of items in the witness |
|
|
|
w = list(bh2u(vds.read_bytes(vds.read_compact_size())) for i in range(n)) |
|
|
|
|
|
|
|
add_w = lambda x: var_int(len(x) // 2) + x |
|
|
|
txin['witness'] = var_int(n) + ''.join(add_w(i) for i in w) |
|
|
|
txin['witness'] = var_int(n) + ''.join(witness_push(i) for i in w) |
|
|
|
|
|
|
|
# FIXME: witness version > 0 will probably fail here. |
|
|
|
# For native segwit, we would need the scriptPubKey of the parent txn |
|
|
@ -487,18 +489,19 @@ def parse_witness(vds, txin): |
|
|
|
if txin['type'] == 'coinbase': |
|
|
|
pass |
|
|
|
elif txin['type'] == 'p2wsh-p2sh' or n > 2: |
|
|
|
witness_script = w[-1] |
|
|
|
try: |
|
|
|
m, n, x_pubkeys, pubkeys, witnessScript = parse_redeemScript(bfh(w[-1])) |
|
|
|
m, n, x_pubkeys, pubkeys = parse_redeemScript_multisig(bfh(witness_script)) |
|
|
|
except NotRecognizedRedeemScript: |
|
|
|
raise UnknownTxinType() |
|
|
|
txin['signatures'] = parse_sig(w[1:-1]) |
|
|
|
txin['num_sig'] = m |
|
|
|
txin['x_pubkeys'] = x_pubkeys |
|
|
|
txin['pubkeys'] = pubkeys |
|
|
|
txin['witnessScript'] = witnessScript |
|
|
|
txin['witness_script'] = witness_script |
|
|
|
if not txin.get('scriptSig'): # native segwit script |
|
|
|
txin['type'] = 'p2wsh' |
|
|
|
txin['address'] = bitcoin.script_to_p2wsh(txin['witnessScript']) |
|
|
|
txin['address'] = bitcoin.script_to_p2wsh(witness_script) |
|
|
|
elif txin['type'] == 'p2wpkh-p2sh' or n == 2: |
|
|
|
txin['num_sig'] = 1 |
|
|
|
txin['x_pubkeys'] = [w[1]] |
|
|
@ -641,12 +644,18 @@ class Transaction: |
|
|
|
public_key.verify_digest(sig_string, pre_hash, sigdecode = ecdsa.util.sigdecode_string) |
|
|
|
j = pubkeys.index(pubkey) |
|
|
|
print_error("adding sig", i, j, pubkey, sig) |
|
|
|
self._inputs[i]['signatures'][j] = sig |
|
|
|
self.add_signature_to_txin(self._inputs[i], j, sig) |
|
|
|
#self._inputs[i]['x_pubkeys'][j] = pubkey |
|
|
|
break |
|
|
|
# redo raw |
|
|
|
self.raw = self.serialize() |
|
|
|
|
|
|
|
@classmethod |
|
|
|
def add_signature_to_txin(cls, txin, signingPos, sig): |
|
|
|
txin['signatures'][signingPos] = sig |
|
|
|
txin['scriptSig'] = None # force re-serialization |
|
|
|
txin['witness'] = None # force re-serialization |
|
|
|
|
|
|
|
def deserialize(self): |
|
|
|
if self.raw is None: |
|
|
|
return |
|
|
@ -736,17 +745,17 @@ class Transaction: |
|
|
|
return '00' |
|
|
|
if txin['type'] == 'coinbase': |
|
|
|
return txin['witness'] |
|
|
|
pubkeys, sig_list = self.get_siglist(txin, estimate_size) |
|
|
|
add_w = lambda x: var_int(len(x) // 2) + x |
|
|
|
if txin['type'] in ['p2wpkh', 'p2wpkh-p2sh']: |
|
|
|
witness = var_int(2) + add_w(sig_list[0]) + add_w(pubkeys[0]) |
|
|
|
elif txin['type'] in ['p2wsh', 'p2wsh-p2sh']: |
|
|
|
n = len(sig_list) + 2 |
|
|
|
witness_script = multisig_script(pubkeys, txin['num_sig']) |
|
|
|
witness = var_int(n) + '00' + ''.join(add_w(x) for x in sig_list) + add_w(witness_script) |
|
|
|
else: |
|
|
|
witness = txin.get('witness', None) |
|
|
|
if not witness: |
|
|
|
|
|
|
|
witness = txin.get('witness', None) |
|
|
|
if witness is None: |
|
|
|
pubkeys, sig_list = self.get_siglist(txin, estimate_size) |
|
|
|
if txin['type'] in ['p2wpkh', 'p2wpkh-p2sh']: |
|
|
|
witness = var_int(2) + witness_push(sig_list[0]) + witness_push(pubkeys[0]) |
|
|
|
elif txin['type'] in ['p2wsh', 'p2wsh-p2sh']: |
|
|
|
n = len(sig_list) + 2 |
|
|
|
witness_script = multisig_script(pubkeys, txin['num_sig']) |
|
|
|
witness = var_int(n) + '00' + ''.join(witness_push(x) for x in sig_list) + witness_push(witness_script) |
|
|
|
else: |
|
|
|
raise Exception('wrong txin type:', txin['type']) |
|
|
|
if self.is_txin_complete(txin) or estimate_size: |
|
|
|
value_field = '' |
|
|
@ -756,7 +765,7 @@ class Transaction: |
|
|
|
|
|
|
|
@classmethod |
|
|
|
def is_segwit_input(cls, txin): |
|
|
|
has_nonzero_witness = txin.get('witness', '00') != '00' |
|
|
|
has_nonzero_witness = txin.get('witness', '00') not in ('00', None) |
|
|
|
return cls.is_segwit_inputtype(txin['type']) or has_nonzero_witness |
|
|
|
|
|
|
|
@classmethod |
|
|
@ -768,6 +777,11 @@ class Transaction: |
|
|
|
_type = txin['type'] |
|
|
|
if _type == 'coinbase': |
|
|
|
return txin['scriptSig'] |
|
|
|
|
|
|
|
script_sig = txin.get('scriptSig', None) |
|
|
|
if script_sig is not None: |
|
|
|
return script_sig |
|
|
|
|
|
|
|
pubkeys, sig_list = self.get_siglist(txin, estimate_size) |
|
|
|
script = ''.join(push_script(x) for x in sig_list) |
|
|
|
if _type == 'p2pk': |
|
|
@ -1035,7 +1049,8 @@ class Transaction: |
|
|
|
sig = private_key.sign_digest_deterministic(pre_hash, hashfunc=hashlib.sha256, sigencode = ecdsa.util.sigencode_der) |
|
|
|
if not public_key.verify_digest(sig, pre_hash, sigdecode = ecdsa.util.sigdecode_der): |
|
|
|
raise Exception('Sanity check verifying our own signature failed.') |
|
|
|
txin['signatures'][j] = bh2u(sig) + '01' |
|
|
|
sig = bh2u(sig) + '01' |
|
|
|
self.add_signature_to_txin(txin, j, sig) |
|
|
|
#txin['x_pubkeys'][j] = pubkey |
|
|
|
txin['pubkeys'][j] = pubkey # needed for fd keys |
|
|
|
self._inputs[i] = txin |
|
|
|