From 2d498628c185354da827eaf66dcc6a1661736bb3 Mon Sep 17 00:00:00 2001 From: ThomasV Date: Tue, 30 Apr 2013 20:44:11 +0400 Subject: [PATCH] in mempool, use input addresses from parser instead of reading them from database --- backends/bitcoind/blockchain_processor.py | 29 ++++----------- backends/bitcoind/deserialize.py | 55 +++++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 24 deletions(-) diff --git a/backends/bitcoind/blockchain_processor.py b/backends/bitcoind/blockchain_processor.py index 756946d..d95764e 100644 --- a/backends/bitcoind/blockchain_processor.py +++ b/backends/bitcoind/blockchain_processor.py @@ -827,33 +827,21 @@ class BlockchainProcessor(Processor): if not tx: continue + mpa = self.mempool_addresses.get(tx_hash, []) for x in tx.get('inputs'): - txi = (x.get('prevout_hash') + int_to_hex(x.get('prevout_n'), 4)).decode('hex') - try: - addr = self.db.Get(txi) - except: - tx_prev = self.get_mempool_transaction(x.get('prevout_hash')) - try: - addr = tx_prev['outputs'][x.get('prevout_n')]['address'] - if not addr: continue - except: - continue - l = self.mempool_addresses.get(tx_hash, []) - if addr not in l: - l.append(addr) - self.mempool_addresses[tx_hash] = l - #if addr not in touched_addresses: + # we assume that the input address can be parsed by deserialize(); this is true for Electrum transactions + addr = x.get('address') + if addr and addr not in mpa: + mpa.append(addr) touched_addresses.append(addr) for x in tx.get('outputs'): addr = x.get('address') - l = self.mempool_addresses.get(tx_hash, []) - if addr not in l: - l.append(addr) - self.mempool_addresses[tx_hash] = l - #if addr not in touched_addresses: + if addr and addr not in mpa: + mpa.append(addr) touched_addresses.append(addr) + self.mempool_addresses[tx_hash] = mpa self.mempool_hashes.append(tx_hash) # remove older entries from mempool_hashes @@ -864,7 +852,6 @@ class BlockchainProcessor(Processor): if tx_hash not in self.mempool_hashes: self.mempool_addresses.pop(tx_hash) for addr in addresses: - #if addr not in touched_addresses: touched_addresses.append(addr) # rebuild mempool histories diff --git a/backends/bitcoind/deserialize.py b/backends/bitcoind/deserialize.py index 75cbc3e..066be33 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 @@ -336,6 +344,47 @@ 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 + # (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) ] -- 1.7.1