def test_toposort(self): def get_all(x): return self.l self.assertRaises(ValueError, toposorted, self.l, get_all) def get_a(x): if x == 'a': return ['b'] return [] self.assertEquals(toposorted(self.l, get_a), ['b', 'a'])
def get_history_for_asset(self, asset): """Returns the history of how an address got its coins. """ history = [] address_lookup = { a.get_address(): 1 for a in self.address_man.get_addresses_for_color_set( asset.get_color_set())} for color in asset.color_set.color_id_set: colordef = self.ccc.colormap.get_color_def(color) color_transactions = self.ccc.cdstore.get_all(color) transaction_lookup = {} color_record = defaultdict(list) for row in color_transactions: txhash, outindex, colorvalue, other = row mempool = False if not transaction_lookup.get(txhash): tx = self.ccc.blockchain_state.get_tx(txhash) blockhash, x = self.ccc.blockchain_state.get_tx_blockhash( txhash) if blockhash: height = self.ccc.blockchain_state.get_block_height( blockhash) else: height = -1 mempool = True transaction_lookup[txhash] = (tx, height) tx, height = transaction_lookup[txhash] output = tx.outputs[outindex] address = self.ccc.raw_to_address(output.raw_address) if address_lookup.get(address): color_record[txhash].append({ 'txhash': txhash, 'address': address, 'value': colorvalue, 'height': height, 'outindex': outindex, 'inindex': -1, 'mempool': mempool, }) # check the inputs seen_hashes = {} for txhash, tup in transaction_lookup.items(): tx, height = tup mempool = height == -1 for input_index, input in enumerate(tx.inputs): inhash = input.prevout.hash in_outindex = input.prevout.n intx = self.ccc.blockchain_state.get_tx(inhash) in_raw = intx.outputs[in_outindex] address = self.ccc.raw_to_address(in_raw.raw_address) # find the transaction that corresponds to this input transaction = color_record.get(inhash) if not transaction: continue # find the output transaction corresponding to this input # index and record it as being spent for item in transaction: if item['outindex'] == in_outindex: color_record[txhash].append({ 'txhash': txhash, 'address': address, 'value': -item['value'], 'height': height, 'inindex': input_index, 'outindex': -1, 'mempool': mempool, }) break for txhash, color_record_transaction in color_record.items(): for item in color_record_transaction: value = item['value'] if value < 0: item['action'] = 'sent' item['value'] = -int(value) elif txhash == colordef.genesis['txhash']: item['action'] = 'issued' item['value'] = int(value) else: item['action'] = 'received' item['value'] = int(value) history.append(item) def dependent_txs(txhash): """all transactions from current block this transaction directly depends on""" dependent_txhashes = [] tx, height = transaction_lookup[txhash] for inp in tx.inputs: if inp.prevout.hash in transaction_lookup: dependent_txhashes.append(inp.prevout.hash) return dependent_txhashes sorted_txhash_list = toposort.toposorted(transaction_lookup.keys(), dependent_txs) txhash_position = {txhash:i for i, txhash in enumerate(sorted_txhash_list)} def compare(a,b): """order in which we get back the history #1 - whether or not it's a mempool transaction #2 - height of the block the transaction is in #3 - whatever transaction is least dependent within a block #4 - whether we're sending or receiving #4 - outindex within a transaction/inindex within a transaction """ return a['mempool'] - b['mempool'] \ or a['height'] - b['height'] \ or txhash_position[a['txhash']] - txhash_position[b['txhash']] \ or a['outindex'] - b['outindex'] \ or a['inindex'] - b['inindex'] return sorted(history, cmp=compare)
def get_history_for_asset(self, asset): """Returns the history of how an address got its coins. """ history = [] address_lookup = { a.get_address(): 1 for a in self.address_man.get_addresses_for_color_set( asset.get_color_set()) } for color in asset.color_set.color_id_set: colordef = self.ccc.colormap.get_color_def(color) color_transactions = self.ccc.cdstore.get_all(color) transaction_lookup = {} color_record = defaultdict(list) for row in color_transactions: txhash, outindex, colorvalue, other = row mempool = False if not transaction_lookup.get(txhash): tx = self.ccc.blockchain_state.get_tx(txhash) blockhash, x = self.ccc.blockchain_state.get_tx_blockhash( txhash) if blockhash: height = self.ccc.blockchain_state.get_block_height( blockhash) else: height = -1 mempool = True transaction_lookup[txhash] = (tx, height) tx, height = transaction_lookup[txhash] output = tx.outputs[outindex] address = self.ccc.raw_to_address(output.raw_address) if address_lookup.get(address): color_record[txhash].append({ 'txhash': txhash, 'address': address, 'value': colorvalue, 'height': height, 'outindex': outindex, 'inindex': -1, 'mempool': mempool, }) # check the inputs seen_hashes = {} for txhash, tup in transaction_lookup.items(): tx, height = tup mempool = height == -1 for input_index, input in enumerate(tx.inputs): inhash = input.prevout.hash in_outindex = input.prevout.n intx = self.ccc.blockchain_state.get_tx(inhash) in_raw = intx.outputs[in_outindex] address = self.ccc.raw_to_address(in_raw.raw_address) # find the transaction that corresponds to this input transaction = color_record.get(inhash) if not transaction: continue # find the output transaction corresponding to this input # index and record it as being spent for item in transaction: if item['outindex'] == in_outindex: color_record[txhash].append({ 'txhash': txhash, 'address': address, 'value': -item['value'], 'height': height, 'inindex': input_index, 'outindex': -1, 'mempool': mempool, }) break for txhash, color_record_transaction in color_record.items(): for item in color_record_transaction: value = item['value'] if value < 0: item['action'] = 'sent' item['value'] = -int(value) elif txhash == colordef.genesis['txhash']: item['action'] = 'issued' item['value'] = int(value) else: item['action'] = 'received' item['value'] = int(value) history.append(item) def dependent_txs(txhash): """all transactions from current block this transaction directly depends on""" dependent_txhashes = [] tx, height = transaction_lookup[txhash] for inp in tx.inputs: if inp.prevout.hash in transaction_lookup: dependent_txhashes.append(inp.prevout.hash) return dependent_txhashes sorted_txhash_list = toposort.toposorted(transaction_lookup.keys(), dependent_txs) txhash_position = { txhash: i for i, txhash in enumerate(sorted_txhash_list) } def compare(a, b): """order in which we get back the history #1 - whether or not it's a mempool transaction #2 - height of the block the transaction is in #3 - whatever transaction is least dependent within a block #4 - whether we're sending or receiving #4 - outindex within a transaction/inindex within a transaction """ return a['mempool'] - b['mempool'] \ or a['height'] - b['height'] \ or txhash_position[a['txhash']] - txhash_position[b['txhash']] \ or a['outindex'] - b['outindex'] \ or a['inindex'] - b['inindex'] return sorted(history, cmp=compare)