def broadcast_transaction(self, raw_transaction: str) -> Optional[str]: ''' Sends given transaction to connected node. Args: raw_transaction (str): hex string containing signed transaction Returns: str, None: transaction address if transaction was sent, None otherwise. ''' deserialized_transaction = self.deserialize_raw_transaction( raw_transaction) serialized_transaction = deserialized_transaction.serialize() get_data = self.send_inventory(serialized_transaction) if not get_data: logger.debug( ConnectionProblem( 'Clove could not get connected with any of the nodes for too long.' )) self.reset_connection() return node = self.get_current_node() if all(el.hash != Hash(serialized_transaction) for el in get_data.inv): logger.debug( UnexpectedResponseFromNode( 'Node did not ask for our transaction', node)) self.reset_connection() return message = msg_tx() message.tx = deserialized_transaction if not self.send_message(message, 20): return logger.info('[%s] Looking for reject message.', node) messages = self.capture_messages([ msg_reject, ], timeout=REJECT_TIMEOUT, buf_size=8192, ignore_empty=True) if messages: logger.debug(TransactionRejected(messages[0], node)) self.reset_connection() return logger.info('[%s] Reject message not found.', node) transaction_address = b2lx(deserialized_transaction.GetHash()) logger.info('[%s] Transaction %s has just been sent.', node, transaction_address) return transaction_address
def getdata_tx(self, txhash): if txhash in self.mempool.pool: tx = self.mempool.pool[txhash] else: tx = self.chaindb.gettx(txhash) if tx is None: return msg = messages.msg_tx() msg.tx = tx self.send_message(msg)
def _process_message(self, **kwargs): msg = MsgSerializable.stream_deserialize(Wrapper(self.my_socket)) if msg.command == b"version": # TODO conglomerate these message strings into a dictionary # Send Verack # print('version: ', msg.strSubVer, msg.nVersion) self.my_socket.send( msg_verack().to_bytes() ) return "version" elif msg.command == b"verack": # print("verack: ", msg) return "verack" elif msg.command == b"inv": pass # print("inv: ", msg.inv) # print(dir(msg)) # print(type(msg.inv)) elif msg.command == b"ping": # print("ping: ", msg) self.my_socket.send(msg_pong(msg.nonce).to_bytes()) elif msg.command == b"getheaders": pass # print("getheaders received ") elif msg.command == b"addr": # TODO this needs multi-message support # print("addr: size ", len(msg.addrs)) for address in msg.addrs: node = Link(address.ip, address.port) self.results.add(node) return True elif msg.command == b"getdata": # print("getdata: ", msg.inv) if 'transaction' not in kwargs: return False the_tx = kwargs['transaction'] for request in msg.inv: if request.hash == the_tx.GetHash(): print(threading.current_thread().name,"sending tx: ", self.link) # new message to send transaction to_send = msg_tx() to_send.tx = the_tx self.my_socket.send(to_send.to_bytes()) # print("SENT OUR PC BRO TRANSACTION") return "donedone" else: pass # print("something else: ", msg.command, msg) return False
def broadcast_listen(self): pubsub = redis.pubsub() pubsub.subscribe('broadcast') for msg in pubsub.listen(): tx = msg['data'] try: tx = tx.decode() btx = bytes.fromhex(tx) tx = CTransaction.deserialize(btx) # CheckTransaction(tx) # TODO: Fix money supply? msg = msg_tx() msg.tx = tx self.send_message(msg) print('Sent tx %s' % b2lx(msg.tx.GetTxid())) if self.chaindb.tx_is_orphan(msg.tx): self.log.info("MemPool: Ignoring orphan TX %s" % (b2lx(msg.tx.GetHash()), )) else: self.chaindb.mempool_add(msg.tx) except Exception as e: print(e) traceback.print_exc()