mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-08-28 07:51:27 +00:00
parent
b0966671d7
commit
7b8b75c7d3
2 changed files with 46 additions and 8 deletions
|
@ -224,6 +224,10 @@ class TestTransaction(unittest.TestCase):
|
||||||
tx = transaction.Transaction('010000000001010d350cefa29138de18a2d63a93cffda63721b07a6ecfa80a902f9514104b55ca0000000000fdffffff012a4a824a00000000160014b869999d342a5d42d6dc7af1efc28456da40297a024730440220475bb55814a52ea1036919e4408218c693b8bf93637b9f54c821b5baa3b846e102207276ed7a79493142c11fb01808a4142bbdd525ae7bdccdf8ecb7b8e3c856b4d90121024cdeaca7a53a7e23a1edbe9260794eaa83063534b5f111ee3c67d8b0cb88f0eec8010000')
|
tx = transaction.Transaction('010000000001010d350cefa29138de18a2d63a93cffda63721b07a6ecfa80a902f9514104b55ca0000000000fdffffff012a4a824a00000000160014b869999d342a5d42d6dc7af1efc28456da40297a024730440220475bb55814a52ea1036919e4408218c693b8bf93637b9f54c821b5baa3b846e102207276ed7a79493142c11fb01808a4142bbdd525ae7bdccdf8ecb7b8e3c856b4d90121024cdeaca7a53a7e23a1edbe9260794eaa83063534b5f111ee3c67d8b0cb88f0eec8010000')
|
||||||
self.assertEqual('51087ece75c697cc872d2e643d646b0f3e1f2666fa1820b7bff4343d50dd680e', tx.txid())
|
self.assertEqual('51087ece75c697cc872d2e643d646b0f3e1f2666fa1820b7bff4343d50dd680e', tx.txid())
|
||||||
|
|
||||||
|
def test_txid_input_p2wsh_p2sh_not_multisig(self):
|
||||||
|
tx = transaction.Transaction('0100000000010160f84fdcda039c3ca1b20038adea2d49a53db92f7c467e8def13734232bb610804000000232200202814720f16329ab81cb8867c4d447bd13255931f23e6655944c9ada1797fcf88ffffffff0ba3dcfc04000000001976a91488124a57c548c9e7b1dd687455af803bd5765dea88acc9f44900000000001976a914da55045a0ccd40a56ce861946d13eb861eb5f2d788ac49825e000000000017a914ca34d4b190e36479aa6e0023cfe0a8537c6aa8dd87680c0d00000000001976a914651102524c424b2e7c44787c4f21e4c54dffafc088acf02fa9000000000017a914ee6c596e6f7066466d778d4f9ba633a564a6e95d874d250900000000001976a9146ca7976b48c04fd23867748382ee8401b1d27c2988acf5119600000000001976a914cf47d5dcdba02fd547c600697097252d38c3214a88ace08a12000000000017a914017bef79d92d5ec08c051786bad317e5dd3befcf87e3d76201000000001976a9148ec1b88b66d142bcbdb42797a0fd402c23e0eec288ac718f6900000000001976a914e66344472a224ce6f843f2989accf435ae6a808988ac65e51300000000001976a914cad6717c13a2079066f876933834210ebbe68c3f88ac0347304402201a4907c4706104320313e182ecbb1b265b2d023a79586671386de86bb47461590220472c3db9fc99a728ebb9b555a72e3481d20b181bd059a9c1acadfb853d90c96c01210338a46f2a54112fef8803c8478bc17e5f8fc6a5ec276903a946c1fafb2e3a8b181976a914eda8660085bf607b82bd18560ca8f3a9ec49178588ac00000000')
|
||||||
|
self.assertEqual('e9933221a150f78f9f224899f8568ff6422ffcc28ca3d53d87936368ff7c4b1d', tx.txid())
|
||||||
|
|
||||||
|
|
||||||
class NetworkMock(object):
|
class NetworkMock(object):
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,14 @@ class SerializationError(Exception):
|
||||||
""" Thrown when there's a problem deserializing or serializing """
|
""" Thrown when there's a problem deserializing or serializing """
|
||||||
|
|
||||||
|
|
||||||
|
class UnknownTxinType(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class NotRecognizedRedeemScript(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class BCDataStream(object):
|
class BCDataStream(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.input = None
|
self.input = None
|
||||||
|
@ -302,8 +310,14 @@ def parse_scriptSig(d, _bytes):
|
||||||
if match_decoded(decoded, match):
|
if match_decoded(decoded, match):
|
||||||
item = decoded[0][1]
|
item = decoded[0][1]
|
||||||
if item[0] == 0:
|
if item[0] == 0:
|
||||||
|
# segwit embedded into p2sh
|
||||||
d['address'] = bitcoin.hash160_to_p2sh(bitcoin.hash_160(item))
|
d['address'] = bitcoin.hash160_to_p2sh(bitcoin.hash_160(item))
|
||||||
d['type'] = 'p2wpkh-p2sh' if len(item) == 22 else 'p2wsh-p2sh'
|
if len(item) == 22:
|
||||||
|
d['type'] = 'p2wpkh-p2sh'
|
||||||
|
elif len(item) == 34:
|
||||||
|
d['type'] = 'p2wsh-p2sh'
|
||||||
|
else:
|
||||||
|
print_error("unrecognized txin type", bh2u(item))
|
||||||
else:
|
else:
|
||||||
# payto_pubkey
|
# payto_pubkey
|
||||||
d['type'] = 'p2pk'
|
d['type'] = 'p2pk'
|
||||||
|
@ -361,7 +375,7 @@ def parse_redeemScript(s):
|
||||||
match_multisig = [ op_m ] + [opcodes.OP_PUSHDATA4]*n + [ op_n, opcodes.OP_CHECKMULTISIG ]
|
match_multisig = [ op_m ] + [opcodes.OP_PUSHDATA4]*n + [ op_n, opcodes.OP_CHECKMULTISIG ]
|
||||||
if not match_decoded(dec2, match_multisig):
|
if not match_decoded(dec2, match_multisig):
|
||||||
print_error("cannot find address in input script", bh2u(s))
|
print_error("cannot find address in input script", bh2u(s))
|
||||||
return
|
raise NotRecognizedRedeemScript()
|
||||||
x_pubkeys = [bh2u(x[1]) for x in dec2[1:-2]]
|
x_pubkeys = [bh2u(x[1]) for x in dec2[1:-2]]
|
||||||
pubkeys = [safe_parse_pubkey(x) for x in x_pubkeys]
|
pubkeys = [safe_parse_pubkey(x) for x in x_pubkeys]
|
||||||
redeemScript = multisig_script(pubkeys, m)
|
redeemScript = multisig_script(pubkeys, m)
|
||||||
|
@ -431,20 +445,29 @@ def parse_witness(vds, txin):
|
||||||
txin['value'] = vds.read_uint64()
|
txin['value'] = vds.read_uint64()
|
||||||
n = vds.read_compact_size()
|
n = vds.read_compact_size()
|
||||||
w = list(bh2u(vds.read_bytes(vds.read_compact_size())) for i in range(n))
|
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)
|
||||||
|
|
||||||
if txin['type'] == 'coinbase':
|
if txin['type'] == 'coinbase':
|
||||||
pass
|
pass
|
||||||
elif n > 2:
|
elif n > 2:
|
||||||
txin['signatures'] = parse_sig(w[1:-1])
|
try:
|
||||||
m, n, x_pubkeys, pubkeys, witnessScript = parse_redeemScript(bfh(w[-1]))
|
m, n, x_pubkeys, pubkeys, witnessScript = parse_redeemScript(bfh(w[-1]))
|
||||||
|
except NotRecognizedRedeemScript:
|
||||||
|
raise UnknownTxinType()
|
||||||
|
txin['signatures'] = parse_sig(w[1:-1])
|
||||||
txin['num_sig'] = m
|
txin['num_sig'] = m
|
||||||
txin['x_pubkeys'] = x_pubkeys
|
txin['x_pubkeys'] = x_pubkeys
|
||||||
txin['pubkeys'] = pubkeys
|
txin['pubkeys'] = pubkeys
|
||||||
txin['witnessScript'] = witnessScript
|
txin['witnessScript'] = witnessScript
|
||||||
else:
|
elif n == 2:
|
||||||
txin['num_sig'] = 1
|
txin['num_sig'] = 1
|
||||||
txin['x_pubkeys'] = [w[1]]
|
txin['x_pubkeys'] = [w[1]]
|
||||||
txin['pubkeys'] = [safe_parse_pubkey(w[1])]
|
txin['pubkeys'] = [safe_parse_pubkey(w[1])]
|
||||||
txin['signatures'] = parse_sig([w[0]])
|
txin['signatures'] = parse_sig([w[0]])
|
||||||
|
else:
|
||||||
|
raise UnknownTxinType()
|
||||||
|
|
||||||
def parse_output(vds, i):
|
def parse_output(vds, i):
|
||||||
d = {}
|
d = {}
|
||||||
|
@ -474,7 +497,12 @@ def deserialize(raw):
|
||||||
if is_segwit:
|
if is_segwit:
|
||||||
for i in range(n_vin):
|
for i in range(n_vin):
|
||||||
txin = d['inputs'][i]
|
txin = d['inputs'][i]
|
||||||
|
try:
|
||||||
parse_witness(vds, txin)
|
parse_witness(vds, txin)
|
||||||
|
except UnknownTxinType:
|
||||||
|
txin['type'] = 'unknown'
|
||||||
|
# FIXME: GUI might show 'unknown' address (e.g. for a non-multisig p2wsh)
|
||||||
|
continue
|
||||||
# segwit-native script
|
# segwit-native script
|
||||||
if not txin.get('scriptSig'):
|
if not txin.get('scriptSig'):
|
||||||
if txin['num_sig'] == 1:
|
if txin['num_sig'] == 1:
|
||||||
|
@ -674,7 +702,9 @@ class Transaction:
|
||||||
witness_script = multisig_script(pubkeys, txin['num_sig'])
|
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)
|
witness = var_int(n) + '00' + ''.join(add_w(x) for x in sig_list) + add_w(witness_script)
|
||||||
else:
|
else:
|
||||||
raise BaseException('wrong txin type')
|
witness = txin.get('witness', None)
|
||||||
|
if not witness:
|
||||||
|
raise BaseException('wrong txin type:', txin['type'])
|
||||||
if self.is_txin_complete(txin) or estimate_size:
|
if self.is_txin_complete(txin) or estimate_size:
|
||||||
value_field = ''
|
value_field = ''
|
||||||
else:
|
else:
|
||||||
|
@ -682,8 +712,12 @@ class Transaction:
|
||||||
return value_field + witness
|
return value_field + witness
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def is_segwit_input(self, txin):
|
def is_segwit_input(cls, txin):
|
||||||
return txin['type'] in ['p2wpkh', 'p2wpkh-p2sh', 'p2wsh', 'p2wsh-p2sh']
|
return cls.is_segwit_inputtype(txin['type']) or bool(txin.get('witness', False))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def is_segwit_inputtype(cls, txin_type):
|
||||||
|
return txin_type in ('p2wpkh', 'p2wpkh-p2sh', 'p2wsh', 'p2wsh-p2sh')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def input_script(self, txin, estimate_size=False):
|
def input_script(self, txin, estimate_size=False):
|
||||||
|
|
Loading…
Add table
Reference in a new issue