d['prevout_n'] = vds.read_uint32()
scriptSig = vds.read_bytes(vds.read_compact_size())
d['sequence'] = vds.read_uint32()
- # actually I don't need that at all
- # if not is_coinbase: d['address'] = extract_public_key(scriptSig)
- # d['script'] = decode_script(scriptSig)
+
+ if scriptSig:
+ pubkeys, signatures, address = get_address_from_input_script(scriptSig)
+ else:
+ pubkeys = []
+ signatures = []
+ address = None
+
+ d['address'] = address
+ d['signatures'] = signatures
+
return d
d = {}
d['value'] = vds.read_int64()
scriptPubKey = vds.read_bytes(vds.read_compact_size())
- d['address'] = extract_public_key(scriptPubKey)
- #d['script'] = decode_script(scriptPubKey)
+ d['address'] = get_address_from_output_script(scriptPubKey)
d['raw_output_script'] = scriptPubKey.encode('hex')
d['index'] = i
return d
"OP_WITHIN", "OP_RIPEMD160", "OP_SHA1", "OP_SHA256", "OP_HASH160",
"OP_HASH256", "OP_CODESEPARATOR", "OP_CHECKSIG", "OP_CHECKSIGVERIFY", "OP_CHECKMULTISIG",
"OP_CHECKMULTISIGVERIFY",
- ("OP_SINGLEBYTE_END", 0xF0),
- ("OP_DOUBLEBYTE_BEGIN", 0xF000),
- "OP_PUBKEY", "OP_PUBKEYHASH",
- ("OP_INVALIDOPCODE", 0xFFFF),
+ "OP_NOP1", "OP_NOP2", "OP_NOP3", "OP_NOP4", "OP_NOP5", "OP_NOP6", "OP_NOP7", "OP_NOP8", "OP_NOP9", "OP_NOP10",
+ ("OP_INVALIDOPCODE", 0xFF),
])
vch = None
opcode = ord(bytes[i])
i += 1
- if opcode >= opcodes.OP_SINGLEBYTE_END:
- opcode <<= 8
- opcode |= ord(bytes[i])
- i += 1
if opcode <= opcodes.OP_PUSHDATA4:
nSize = opcode
elif opcode == opcodes.OP_PUSHDATA4:
(nSize,) = struct.unpack_from('<I', bytes, i)
i += 4
- vch = bytes[i:i+nSize]
- i += nSize
+ if i+nSize > len(bytes):
+ vch = "_INVALID_"+bytes[i:]
+ i = len(bytes)
+ else:
+ vch = bytes[i:i+nSize]
+ i += nSize
yield (opcode, vch, i)
def script_GetOpName(opcode):
+ try:
return (opcodes.whatis(opcode)).replace("OP_", "")
+ except KeyError:
+ return "InvalidOp_"+str(opcode)
def decode_script(bytes):
return True
-def extract_public_key(bytes):
- decoded = list(script_GetOp(bytes))
+
+def get_address_from_input_script(bytes):
+ try:
+ decoded = [ x for x in script_GetOp(bytes) ]
+ except:
+ # coinbase transactions raise an exception
+ return [], [], None
# non-generated TxIn transactions push a signature
# (seventy-something bytes) and then their public key
- # (65 bytes) onto the stack:
- match = [opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4]
+ # (33 or 65 bytes) onto the stack:
+
+ match = [ opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4 ]
+ if match_decoded(decoded, match):
+ return None, None, public_key_to_bc_address(decoded[1][1])
+
+ # p2sh transaction, 2 of n
+ match = [ opcodes.OP_0 ]
+ while len(match) < len(decoded):
+ match.append(opcodes.OP_PUSHDATA4)
+
if match_decoded(decoded, match):
- return public_key_to_bc_address(decoded[1][1])
+
+ redeemScript = decoded[-1][1]
+ num = len(match) - 2
+ signatures = map(lambda x:x[1].encode('hex'), decoded[1:-1])
+ dec2 = [ x for x in script_GetOp(redeemScript) ]
+
+ # 2 of 2
+ match2 = [ opcodes.OP_2, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_2, opcodes.OP_CHECKMULTISIG ]
+ if match_decoded(dec2, match2):
+ pubkeys = [ dec2[1][1].encode('hex'), dec2[2][1].encode('hex') ]
+ return pubkeys, signatures, hash_160_to_bc_address(hash_160(redeemScript), 5)
+
+ # 2 of 3
+ match2 = [ opcodes.OP_2, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_3, opcodes.OP_CHECKMULTISIG ]
+ if match_decoded(dec2, match2):
+ pubkeys = [ dec2[1][1].encode('hex'), dec2[2][1].encode('hex'), dec2[3][1].encode('hex') ]
+ return pubkeys, signatures, hash_160_to_bc_address(hash_160(redeemScript), 5)
+
+ return [], [], None
+
+
+def get_address_from_output_script(bytes):
+ try:
+ decoded = [ x for x in script_GetOp(bytes) ]
+ except:
+ return None
# The Genesis Block, self-payments, and pay-by-IP-address payments look like:
# 65 BYTES:... CHECKSIG
# DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG
match = [opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_0, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG]
if match_decoded(decoded, match):
- return "None"
+ return None
# Pay-by-Bitcoin-address TxOuts look like:
# DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG
if match_decoded(decoded, match):
return hash_160_to_bc_address(decoded[2][1])
- #raise BaseException("address not found in script") see ce35795fb64c268a52324b884793b3165233b1e6d678ccaadf760628ec34d76b
- return "None"
+ # p2sh
+ match = [ opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUAL ]
+ if match_decoded(decoded, match):
+ addr = hash_160_to_bc_address(decoded[1][1],5)
+ return addr
+
+ return None