def __init__(self, loop: asyncio.AbstractEventLoop, server: str, port: int, proto: str) -> None: """ Connection object constructor. :param loop: an asyncio event loop :param server: a string containing a hostname :param port: port number that the server listens on :returns: A new Connection object """ logging.info("Connecting...") self.server_info = ServerInfo( server, hostname=server, ports=port) # type: ServerInfo logging.info(str(self.server_info.get_port(proto))) self.client = StratumClient(loop) # type: StratumClient self.connection = self.client.connect( self.server_info, proto_code=proto, use_tor=True, disable_cert_verify=(proto != "s")) # type: asyncio.Future loop.run_until_complete(self._do_connect()) self.queue = None # type: asyncio.Queue
def main(keys, address, broadcast): parser = argparse.ArgumentParser( description='Find and sweep all the funds from a mnemonic or bitcoin key, regardless of the derivation path or ' 'address format used.' ) # parser.add_argument( # 'key', help='master key to sweep, formats: mnemonic, xpriv or xpub') sweep_tx = parser.add_argument_group('sweep transaction') # sweep_tx.add_argument('--address', metavar='<address>', # help='craft a transaction sending all funds to this address') # sweep_tx.add_argument('--broadcast', default=False, action='store_true', # help='if present broadcast the transaction to the network') # sweep_tx.add_argument('--fee-rate', metavar='<rate>', type=int, # help='fee rate to use in sat/vbyte (default: next block fee)') scanning = parser.add_argument_group('scanning parameters') scanning.add_argument('--address-gap', metavar='<num>', default=10, type=int, help='max empty addresses gap to explore (default: 20)') scanning.add_argument('--account-gap', metavar='<num>', default=0, type=int, help='max empty account levels gap to explore (default: 0)') electrum = parser.add_argument_group('electrum server') electrum.add_argument('--host', metavar='<host>', help='hostname of the electrum server to use') electrum.add_argument('--port', metavar='<port>', type=int, help='port number of the electrum server to use') electrum.add_argument('--protocol', choices='ts', default='s', help='electrum connection protocol: t=TCP, s=SSL (default: s)') args = parser.parse_args() if args.host is not None: port = (args.protocol + str(args.port) ) if args.port else args.protocol server = ServerInfo(args.host, hostname=args.host, ports=port) else: with open('servers.json', 'r') as f: servers = json.load(f) server = random.choice(servers) server = ServerInfo( server['host'], hostname=server['host'], ports=server['port']) # TODO change fee rate from 25 to like 100 AND AUTOBROADCAST for key in keys: master_key = parse_key(key) asyncio.run(find_utxos(server, master_key, args.address_gap, args.account_gap, address, 25, broadcast))
async def setup_client() -> StratumClient: try: return CLIENT except NameError: pass server = ServerInfo({ "nickname": None, "hostname": "fortress.qtornado.com", "ip_addr": None, "ports": ["s50002", "t50001"], "version": "1.4", "pruning_limit": 0, "seen_at": 1533670768.8676858 }) client = StratumClient() await asyncio.wait_for(client.connect(server_info=server, proto_code='s', use_tor=False, disable_cert_verify=True), timeout=5) # # await asyncio.wait_for( # client.RPC( # 'server.version', # 'bitcoin-spv-merkle', # '1.2'), # timeout=5) return client
async def setup_client(): if CLIENT is not None: return CLIENT server = ServerInfo({ "nickname": None, "hostname": "bitcoin.cluelessperson.com", "ip_addr": "172.92.140.254", "ports": ["s50002", "t50001"], "version": "1.2", "pruning_limit": 0, "seen_at": 1533670768.588772 }) client = StratumClient() await asyncio.wait_for(client.connect(server_info=server, proto_code='s', use_tor=False, disable_cert_verify=True), timeout=5) await asyncio.wait_for(client.RPC('server.version', 'bitcoin-spv-merkle', '1.2'), timeout=5) return client
def main(): svr = ServerInfo("test-net", "testnet.hsmiths.com", ports="s50002") loop = asyncio.get_event_loop() conn = StratumClient() connector = conn.connect(svr, disable_cert_verify=True) loop.run_until_complete( interact(conn, svr, connector, "blockchain.address.get_balance", ["3KF9nXowQ4asSGxRRzeiTpDjMuwM2nypAN"])) loop.close()
async def connect(self): server_info = ServerInfo("", hostname="mdw.ddns.net", ports=50001) self.client = StratumClient(self.app.loop) self.connection = self.client.connect( server_info, proto_code="t") # type: asyncio.Future try: await self.connection self.connected = True except Exception: print("Unable to connect to server:", server_info)
def _get_server_info(self, network: str) -> ServerInfo: ''' Selects a server randomly from the list Filters onions, and other protocol versions Returns: (ServerInfo): the selected server ''' s = filter(lambda k: k not in self._servers, servers.SERVERS[network]) s = filter(lambda k: 'onion' not in k['hostname'], s) s = filter(lambda k: k['version'] == self.protocol_version, s) server = random.choice(list(s)) return ServerInfo(server)
def main(): parser = argparse.ArgumentParser(description='Subscribe to BTC events') parser.add_argument('method', help='"blockchain.numblocks.subscribe" or similar') parser.add_argument('args', nargs="*", default=[], help='Arguments for method') parser.add_argument('--server', default='cluelessperson.com', help='Hostname of Electrum server to use') parser.add_argument('--protocol', default='s', help='Protocol code: t=TCP Cleartext, s=SSL, etc') parser.add_argument('--port', default=None, help='Port number to override default for protocol') parser.add_argument('--tor', default=False, action="store_true", help='Use local Tor proxy to connect') parser.add_argument('--debug', default=False, action="store_true", help='Enable debug output from connectrum library') args = parser.parse_args() if args.debug: import logging logging.getLogger('connectrum').setLevel(logging.DEBUG) # convert to our datastruct about servers. svr = ServerInfo(args.server, args.server, ports=((args.protocol + str(args.port)) if args.port else args.protocol)) loop = asyncio.get_event_loop() conn = StratumClient() connector = conn.connect(svr, args.protocol, use_tor=svr.is_onion, disable_cert_verify=True) loop.run_until_complete( listen(conn, svr, connector, args.method, args.args)) loop.close()
def main(): parser = argparse.ArgumentParser(description='Subscribe to BTC events') parser.add_argument('server', help='Hostname of ElectrumX server to use') parser.add_argument('--port', default=None, help='Port number to override default for protocol') args = parser.parse_args() svr = ServerInfo(args.server, args.server, ports=('t' + args.port)) loop = asyncio.get_event_loop() conn = MyStratumClient() connector = conn.connect(svr, use_tor=False, disable_cert_verify=True) loop.run_until_complete(listen(conn, svr, connector)) loop.close()
def call_electrum(conn, method, *args): # call a method and format up the response nicely print("args") print(args) svr = ServerInfo("electrumx.tamami-foundation.org", "electrumx.tamami-foundation.org", ports=(("tcp" + str("50001")) if "50001" else "tcp")) conn = StratumClient() time.sleep(10) t = '' try: resp = conn.RPC(method, *args) time.sleep(10) except ElectrumErrorResponse as e: response, req = e.args t += "2-1" return t print("CALL_ELECTRUM REPONSE") print(resp) return resp
fut, Q = conn.subscribe('blockchain.numblocks.subscribe') top_blk = await fut while 1: top_blk = max(await Q.get()) print("new top-block: %r" % (top_blk, )) app.loop.create_task(track_top_block()) if __name__ == "__main__": app = web.Application() app.router.add_route('GET', '/', homepage) app.router.add_route('POST', '/', search) app.router.add_route('GET', '/addr/{addr}', address_page) app.router.add_route('GET', '/txn/{txn_hash}', transaction_page) app.router.add_route('GET', '/blk/{height}', block_page) if 1: ks = KnownServers() ks.from_json('../connectrum/servers.json') servers = ks.select(is_onion=False, min_prune=1000) assert servers, "Need some servers to talk to." el_server = servers[0] else: el_server = ServerInfo('hardcoded', 'electrum.vom-stausee.de', 's') app.loop.create_task(startup_code(app)) web.run_app(app)
def main(): parser = argparse.ArgumentParser( description= 'Find and sweep all the funds from a mnemonic or bitcoin key, regardless of the derivation path or ' 'address format used.') parser.add_argument( 'key', help='master key to sweep, formats: mnemonic, xpriv or xpub') sweep_tx = parser.add_argument_group('sweep transaction') sweep_tx.add_argument( '--address', metavar='<address>', help='craft a transaction sending all funds to this address') sweep_tx.add_argument( '--broadcast', default=False, action='store_true', help='if present broadcast the transaction to the network') sweep_tx.add_argument( '--fee-rate', metavar='<rate>', type=int, help='fee rate to use in sat/vbyte (default: next block fee)') scanning = parser.add_argument_group('scanning parameters') scanning.add_argument('--max-gap', metavar='<num>', default=20, type=int, help='address gap limit (default: 20)') scanning.add_argument( '--max-account', metavar='<num>', default=10, type=int, help='max number of account levels to explore (default: 10)') electrum = parser.add_argument_group('electrum server') electrum.add_argument('--host', metavar='<host>', help='hostname of the electrum server to use') electrum.add_argument('--port', metavar='<port>', type=int, help='port number of the electrum server to use') electrum.add_argument( '--protocol', choices='ts', default='s', help='electrum connection protocol: t=TCP, s=SSL (default: s)') args = parser.parse_args() master_key = parse_key(args.key) if args.host is not None: port = (args.protocol + str(args.port)) if args.port else args.protocol server = ServerInfo(args.host, hostname=args.host, ports=port) else: with open('servers.json', 'r') as f: servers = json.load(f) server = random.choice(servers) server = ServerInfo(server['host'], hostname=server['host'], ports=server['port']) loop = asyncio.get_event_loop() loop.run_until_complete( find_utxos(server, master_key, args.max_gap, args.max_account, args.address, args.fee_rate, args.broadcast)) loop.close()
class Connection: """ Connection object. Connects to an Electrum server, and handles all Stratum protocol messages. """ # pylint: disable=E1111 def __init__(self, loop: asyncio.AbstractEventLoop, server: str, port: int, proto: str) -> None: """ Connection object constructor. :param loop: an asyncio event loop :param server: a string containing a hostname :param port: port number that the server listens on :returns: A new Connection object """ logging.info("Connecting...") self.server_info = ServerInfo(server, hostname=server, ports=port) # type: ServerInfo logging.info(str(self.server_info.get_port(proto))) self.client = StratumClient(loop) # type: StratumClient self.connection = self.client.connect( self.server_info, proto_code=proto, use_tor=True, disable_cert_verify=(proto != "s")) # type: asyncio.Future self.queue = None # type: asyncio.Queue async def do_connect(self) -> None: """ Coroutine. Establishes a persistent connection to an Electrum server. Awaits the connection because AFAIK an init method can't be async. """ await self.connection logging.info("Connected to server") async def listen_rpc(self, method: str, args: List) -> Any: """ Coroutine. Sends a normal RPC message to the server and awaits response. :param method: The Electrum API method to use :param args: Params associated with current method :returns: Future. Response from server for this method(args) """ return await self.client.RPC(method, *args) def listen_subscribe(self, method: str, args: List) -> None: """ Sends a "subscribe" message to the server and adds to the queue. Throws away the immediate future containing the "history" hash. :param method: The Electrum API method to use :param args: Params associated with current method """ t = self.client.subscribe( method, *args) # type: Tuple[asyncio.Future, asyncio.Queue] future, queue = t self.queue = queue return future async def consume_queue( self, queue_func: Callable[[List[str]], Awaitable[None]]) -> None: """ Coroutine. Infinite loop that consumes the current subscription queue. :param queue_func: A function to call when new responses arrive """ while True: result = await self.queue.get() # type: List[str] await queue_func(result)
def server(): return ServerInfo("onion", hostname="fdkhv2bb7hqel2e7.onion", ports=12345)
while 1: top_blk = max(await Q.get()) print("new top-block: %r" % (top_blk, )) app.loop.create_task(track_top_block()) if __name__ == "__main__": app = web.Application() app.router.add_route('GET', '/', homepage) app.router.add_route('POST', '/', search) app.router.add_route('GET', '/addr/{addr}', address_page) app.router.add_route('GET', '/txn/{txn_hash}', transaction_page) app.router.add_route('GET', '/blk/{height}', block_page) if 0: ks = KnownServers() ks.from_json('../connectrum/servers.json') servers = ks.select(is_onion=False, min_prune=1000) assert servers, "Need some servers to talk to." el_server = servers[0] else: el_server = ServerInfo('hardcoded', sys.argv[-1], 's') #el_server = ServerInfo('hardcoded', 'daedalus.bauerj.eu', 's') loop = asyncio.get_event_loop() loop.create_task(startup_code(app)) web.run_app(app)