def _render_GET_thread(self, request: Request) -> bytes: """ GET request /graphviz/full.{format} Returns the rendered graph file """ set_cors(request, 'GET') tx_storage = self.manager.tx_storage graphviz = GraphvizVisualizer(tx_storage) if b'weight' in request.args: graphviz.show_weight = self.parse_bool_arg( request.args[b'weight'][0].decode('utf-8')) if b'acc_weight' in request.args: graphviz.show_acc_weight = self.parse_bool_arg( request.args[b'acc_weight'][0].decode('utf-8')) if b'verifications' in request.args: graphviz.include_verifications = self.parse_bool_arg( request.args[b'verifications'][0].decode('utf-8')) if b'funds' in request.args: graphviz.include_funds = self.parse_bool_arg( request.args[b'funds'][0].decode('utf-8')) if b'only_blocks' in request.args: graphviz.only_blocks = self.parse_bool_arg( request.args[b'only_blocks'][0].decode('utf-8')) dot = graphviz.dot(format=self.format.dot) request.setHeader(b'content-type', self.format.content_type) if self.format is FileFormat.DOT: return str(dot).encode('utf-8') return dot.pipe()
def on_new_tx(self, key: HathorEvents, args: EventArguments) -> None: """ This method is called every change in the DAG. It saves a new snapshot in disk. """ if not self.is_running: return n = self.sequence tx_storage = self.manager.tx_storage graphviz = GraphvizVisualizer(tx_storage) graphviz.include_verifications = True graphviz.include_funds = True dot = graphviz.dot(format=self.format) dot.render(os.path.join(self.dirname, 'seq_{:010d}'.format(n))) self.sequence += 1
def _render_GET_thread(self, request: Request) -> bytes: """ GET request /graphviz/ Expects 'format' parameter in request to set the content-type of the graph Format options are 'pdf', 'png' and 'jpg'. Default format is 'pdf' Returns the file """ set_cors(request, 'GET') contenttype = { 'pdf': b'application/pdf', 'png': b'image/png', 'jpg': b'image/jpeg', 'dot': b'application/dot', } dotformat = 'pdf' if b'format' in request.args: dotformat = request.args[b'format'][0].decode('utf-8') tx_storage = self.manager.tx_storage if b'tx' in request.args: # Getting tx neightborhood tx_hex = request.args[b'tx'][0].decode('utf-8') success, message = validate_tx_hash(tx_hex, tx_storage) if not success: return json.dumps({ 'success': False, 'message': message }, indent=4).encode('utf-8') else: graph_type = request.args[b'graph_type'][0].decode('utf-8') max_level = int(request.args[b'max_level'][0]) if max_level > settings.MAX_GRAPH_LEVEL: return json.dumps( { 'success': False, 'message': 'Graph max level is {}'.format( settings.MAX_GRAPH_LEVEL) }, indent=4).encode('utf-8') tx = tx_storage.get_transaction(bytes.fromhex(tx_hex)) graphviz = GraphvizVisualizer(tx_storage) dot = graphviz.tx_neighborhood(tx, format=dotformat, max_level=max_level, graph_type=graph_type) else: weight = False if b'weight' in request.args: weight = self.parseBoolArg( request.args[b'weight'][0].decode('utf-8')) acc_weight = False if b'acc_weight' in request.args: acc_weight = self.parseBoolArg( request.args[b'acc_weight'][0].decode('utf-8')) include_verifications = True if b'verifications' in request.args: include_verifications = self.parseBoolArg( request.args[b'verifications'][0].decode('utf-8')) include_funds = False if b'funds' in request.args: include_funds = self.parseBoolArg( request.args[b'funds'][0].decode('utf-8')) only_blocks = False if b'only_blocks' in request.args: only_blocks = self.parseBoolArg( request.args[b'only_blocks'][0].decode('utf-8')) graphviz = GraphvizVisualizer(tx_storage) graphviz.include_verifications = include_verifications graphviz.include_funds = include_funds graphviz.only_blocks = only_blocks graphviz.show_weight = weight graphviz.show_acc_weight = acc_weight dot = graphviz.dot(format=dotformat) if dotformat == 'dot': request.setHeader(b'content-type', contenttype[dotformat]) return str(dot).encode('utf-8') request.setHeader(b'content-type', contenttype[dotformat]) return dot.pipe()
def test_double_spending_attempt_1(self): manager = self.manager1 add_new_blocks(manager, 5, advance_clock=15) add_blocks_unlock_reward(manager) from hathor.crypto.util import decode_address from hathor.graphviz import GraphvizVisualizer from hathor.transaction import Transaction from hathor.wallet.base_wallet import WalletInputInfo, WalletOutputInfo graphviz = GraphvizVisualizer(manager.tx_storage, include_verifications=True, include_funds=True) addr = manager.wallet.get_unused_address() outputs = [] outputs.append(WalletOutputInfo(decode_address(addr), 1, None)) outputs.append(WalletOutputInfo(decode_address(addr), 1000, None)) outputs.append( WalletOutputInfo(decode_address(addr), 6400 - 1001, None)) tx_fund0 = manager.wallet.prepare_transaction_compute_inputs( Transaction, outputs, manager.tx_storage) tx_fund0.weight = 1 tx_fund0.parents = manager.get_new_tx_parents() tx_fund0.timestamp = int(self.clock.seconds()) tx_fund0.resolve() self.assertTrue(manager.propagate_tx(tx_fund0)) def do_step(tx_fund): inputs = [ WalletInputInfo(tx_fund.hash, 0, manager.wallet.get_private_key(addr)) ] outputs = [WalletOutputInfo(decode_address(addr), 1, None)] tx1 = manager.wallet.prepare_transaction(Transaction, inputs, outputs, tx_fund.timestamp + 1) tx1.weight = 1 tx1.parents = manager.get_new_tx_parents(tx1.timestamp) tx1.resolve() self.assertTrue(manager.propagate_tx(tx1)) inputs = [] inputs.append( WalletInputInfo(tx1.hash, 0, manager.wallet.get_private_key(addr))) inputs.append( WalletInputInfo(tx_fund.hash, 1, manager.wallet.get_private_key(addr))) outputs = [ WalletOutputInfo(decode_address(addr), tx_fund.outputs[1].value + 1, None) ] tx2 = manager.wallet.prepare_transaction(Transaction, inputs, outputs, tx1.timestamp + 1) tx2.weight = 1 tx2.parents = manager.get_new_tx_parents(tx2.timestamp) tx2.resolve() self.assertTrue(manager.propagate_tx(tx2)) inputs = [ WalletInputInfo(tx_fund.hash, 0, manager.wallet.get_private_key(addr)) ] outputs = [WalletOutputInfo(decode_address(addr), 1, None)] tx3 = manager.wallet.prepare_transaction(Transaction, inputs, outputs, tx_fund.timestamp + 1) tx3.weight = tx1.weight + tx2.weight + 0.1 tx3.parents = manager.get_new_tx_parents(tx3.timestamp) tx3.resolve() self.assertTrue(manager.propagate_tx(tx3)) inputs = [ WalletInputInfo(tx_fund.hash, 1, manager.wallet.get_private_key(addr)) ] outputs = [ WalletOutputInfo(decode_address(addr), tx_fund.outputs[1].value, None) ] tx4 = manager.wallet.prepare_transaction(Transaction, inputs, outputs, tx_fund.timestamp + 1) tx4.weight = 1 tx4.parents = manager.get_new_tx_parents(tx4.timestamp) tx4.resolve() self.assertTrue(manager.propagate_tx(tx4)) inputs = [] inputs.append( WalletInputInfo(tx2.hash, 0, manager.wallet.get_private_key(addr))) inputs.append( WalletInputInfo(tx4.hash, 0, manager.wallet.get_private_key(addr))) outputs = [] outputs.append(WalletOutputInfo(decode_address(addr), 1, None)) outputs.append( WalletOutputInfo(decode_address(addr), 2 * tx_fund.outputs[1].value, None)) tx5 = manager.wallet.prepare_transaction(Transaction, inputs, outputs, tx2.timestamp + 1) tx5.weight = tx3.weight - tx1.weight + 0.1 tx5.parents = [tx2.hash, tx4.hash] tx5.resolve() self.assertTrue(manager.propagate_tx(tx5)) return tx5 tx = tx_fund0 N = 10 for _ in range(N): tx = do_step(tx) block = add_new_block(manager) self.assertIn(tx.hash, block.parents) dot = graphviz.dot() dot.render('dot0') meta = tx.get_metadata() self.assertIsNone(meta.conflict_with) self.assertIsNone(meta.voided_by) self.assertEqual(tx.outputs[1].value, 1000 * 2**N) self.assertConsensusValid(manager)