|
@ -36,6 +36,7 @@ import random |
|
|
|
|
|
|
|
|
NO_SIGNATURE = 'ff' |
|
|
NO_SIGNATURE = 'ff' |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class SerializationError(Exception): |
|
|
class SerializationError(Exception): |
|
|
""" Thrown when there's a problem deserializing or serializing """ |
|
|
""" Thrown when there's a problem deserializing or serializing """ |
|
|
|
|
|
|
|
@ -393,20 +394,20 @@ def get_address_from_output_script(bytes): |
|
|
# 65 BYTES:... CHECKSIG |
|
|
# 65 BYTES:... CHECKSIG |
|
|
match = [ opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG ] |
|
|
match = [ opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG ] |
|
|
if match_decoded(decoded, match): |
|
|
if match_decoded(decoded, match): |
|
|
return 'pubkey', decoded[0][1].encode('hex') |
|
|
return TYPE_PUBKEY, decoded[0][1].encode('hex') |
|
|
|
|
|
|
|
|
# Pay-by-Bitcoin-address TxOuts look like: |
|
|
# Pay-by-Bitcoin-address TxOuts look like: |
|
|
# DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG |
|
|
# DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG |
|
|
match = [ opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG ] |
|
|
match = [ opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG ] |
|
|
if match_decoded(decoded, match): |
|
|
if match_decoded(decoded, match): |
|
|
return 'address', hash_160_to_bc_address(decoded[2][1]) |
|
|
return TYPE_ADDRESS, hash_160_to_bc_address(decoded[2][1]) |
|
|
|
|
|
|
|
|
# p2sh |
|
|
# p2sh |
|
|
match = [ opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUAL ] |
|
|
match = [ opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUAL ] |
|
|
if match_decoded(decoded, match): |
|
|
if match_decoded(decoded, match): |
|
|
return 'address', hash_160_to_bc_address(decoded[1][1],5) |
|
|
return TYPE_ADDRESS, hash_160_to_bc_address(decoded[1][1],5) |
|
|
|
|
|
|
|
|
return 'script', bytes |
|
|
return TYPE_SCRIPT, bytes |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -542,7 +543,7 @@ class Transaction: |
|
|
pubkey = public_key_from_private_key(privkey) |
|
|
pubkey = public_key_from_private_key(privkey) |
|
|
address = address_from_private_key(privkey) |
|
|
address = address_from_private_key(privkey) |
|
|
u = network.synchronous_get(('blockchain.address.listunspent',[address])) |
|
|
u = network.synchronous_get(('blockchain.address.listunspent',[address])) |
|
|
pay_script = klass.pay_script('address', address) |
|
|
pay_script = klass.pay_script(TYPE_ADDRESS, address) |
|
|
for item in u: |
|
|
for item in u: |
|
|
item['scriptPubKey'] = pay_script |
|
|
item['scriptPubKey'] = pay_script |
|
|
item['redeemPubkey'] = pubkey |
|
|
item['redeemPubkey'] = pubkey |
|
@ -560,7 +561,7 @@ class Transaction: |
|
|
return |
|
|
return |
|
|
|
|
|
|
|
|
total = sum(i.get('value') for i in inputs) - fee |
|
|
total = sum(i.get('value') for i in inputs) - fee |
|
|
outputs = [('address', to_address, total)] |
|
|
outputs = [(TYPE_ADDRESS, to_address, total)] |
|
|
self = klass.from_io(inputs, outputs) |
|
|
self = klass.from_io(inputs, outputs) |
|
|
self.sign(keypairs) |
|
|
self.sign(keypairs) |
|
|
return self |
|
|
return self |
|
@ -577,9 +578,9 @@ class Transaction: |
|
|
|
|
|
|
|
|
@classmethod |
|
|
@classmethod |
|
|
def pay_script(self, output_type, addr): |
|
|
def pay_script(self, output_type, addr): |
|
|
if output_type == 'script': |
|
|
if output_type == TYPE_SCRIPT: |
|
|
return addr.encode('hex') |
|
|
return addr.encode('hex') |
|
|
elif output_type == 'address': |
|
|
elif output_type == TYPE_ADDRESS: |
|
|
addrtype, hash_160 = bc_address_to_hash_160(addr) |
|
|
addrtype, hash_160 = bc_address_to_hash_160(addr) |
|
|
if addrtype == 0: |
|
|
if addrtype == 0: |
|
|
script = '76a9' # op_dup, op_hash_160 |
|
|
script = '76a9' # op_dup, op_hash_160 |
|
@ -636,7 +637,7 @@ class Transaction: |
|
|
script += push_script(redeem_script) |
|
|
script += push_script(redeem_script) |
|
|
|
|
|
|
|
|
elif for_sig==i: |
|
|
elif for_sig==i: |
|
|
script = txin['redeemScript'] if p2sh else self.pay_script('address', address) |
|
|
script = txin['redeemScript'] if p2sh else self.pay_script(TYPE_ADDRESS, address) |
|
|
else: |
|
|
else: |
|
|
script = '' |
|
|
script = '' |
|
|
|
|
|
|
|
@ -797,9 +798,9 @@ class Transaction: |
|
|
"""convert pubkeys to addresses""" |
|
|
"""convert pubkeys to addresses""" |
|
|
o = [] |
|
|
o = [] |
|
|
for type, x, v in self.outputs: |
|
|
for type, x, v in self.outputs: |
|
|
if type == 'address': |
|
|
if type == TYPE_ADDRESS: |
|
|
addr = x |
|
|
addr = x |
|
|
elif type == 'pubkey': |
|
|
elif type == TYPE_PUBKEY: |
|
|
addr = public_key_to_bc_address(x.decode('hex')) |
|
|
addr = public_key_to_bc_address(x.decode('hex')) |
|
|
else: |
|
|
else: |
|
|
addr = 'SCRIPT ' + x.encode('hex') |
|
|
addr = 'SCRIPT ' + x.encode('hex') |
|
|