X-Git-Url: https://git.novaco.in/?p=electrum-server.git;a=blobdiff_plain;f=backends%2Fbitcoind%2Fdeserialize.py;h=93ad4d42479a0d6301fcb2013884f0acc807c610;hp=c84a0090cdbb7d511e30e2bae5d6087ef91a84f6;hb=cbcd7ba2e6a8cf6b64b032f974445f107aff8ad1;hpb=9946c27d674e797b448c95f79e3050de50305818 diff --git a/backends/bitcoind/deserialize.py b/backends/bitcoind/deserialize.py index c84a009..93ad4d4 100644 --- a/backends/bitcoind/deserialize.py +++ b/backends/bitcoind/deserialize.py @@ -215,9 +215,17 @@ def parse_TxIn(vds): 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 @@ -272,10 +280,8 @@ opcodes = Enumeration("Opcodes", [ "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), ]) @@ -285,10 +291,6 @@ def script_GetOp(bytes): 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 @@ -301,14 +303,21 @@ def script_GetOp(bytes): elif opcode == opcodes.OP_PUSHDATA4: (nSize,) = struct.unpack_from(' 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): @@ -336,9 +345,53 @@ def match_decoded(decoded, to_match): +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 + # (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): + + 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): - decoded = [ x for x in script_GetOp(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 @@ -350,7 +403,7 @@ def get_address_from_output_script(bytes): # 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 @@ -367,8 +420,6 @@ def get_address_from_output_script(bytes): 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) - print "p2sh", addr return addr - #raise BaseException("address not found in script") see ce35795fb64c268a52324b884793b3165233b1e6d678ccaadf760628ec34d76b - return "None" + return None