URI: 
       tobelisk - obelisk - Electrum server using libbitcoin as its backend
  HTML git clone https://git.parazyd.org/obelisk
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tobelisk (3604B)
       ---
            1 #!/usr/bin/env python3
            2 # Copyright (C) 2020-2021 Ivan J. <parazyd@dyne.org>
            3 #
            4 # This file is part of obelisk
            5 #
            6 # This program is free software: you can redistribute it and/or modify
            7 # it under the terms of the GNU Affero General Public License version 3
            8 # as published by the Free Software Foundation.
            9 #
           10 # This program is distributed in the hope that it will be useful,
           11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
           12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
           13 # GNU Affero General Public License for more details.
           14 #
           15 # You should have received a copy of the GNU Affero General Public License
           16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
           17 import asyncio
           18 import sys
           19 from argparse import ArgumentParser
           20 from configparser import RawConfigParser, NoSectionError
           21 from logging import getLogger, FileHandler, Formatter, StreamHandler
           22 from os import devnull
           23 
           24 from obelisk.protocol import ElectrumProtocol, VERSION
           25 
           26 # Used for destructor/cleanup
           27 PROTOCOL = None
           28 
           29 
           30 def logger_config(log, config):
           31     """Setup logging"""
           32     fmt = Formatter("%(asctime)s\t%(levelname)s\t%(message)s")
           33     logstream = StreamHandler()
           34     logstream.setFormatter(fmt)
           35     debuglevel = config.get("obelisk", "log_level", fallback="INFO")
           36     logstream.setLevel(debuglevel)
           37     log.addHandler(logstream)
           38     filename = config.get("obelisk", "log_file", fallback=devnull)
           39     append_log = config.getboolean("obelisk", "append_log", fallback=False)
           40     logfile = FileHandler(filename, mode=("a" if append_log else "w"))
           41     logfile.setFormatter(fmt)
           42     logfile.setLevel(debuglevel)
           43     log.addHandler(logfile)
           44     log.setLevel(debuglevel)
           45     return log, filename
           46 
           47 
           48 async def run_electrum_server(config, chain):
           49     """Server coroutine"""
           50     log = getLogger("obelisk")
           51     host = config.get("obelisk", "host")
           52     port = int(config.get("obelisk", "port"))
           53 
           54     endpoints = {}
           55     endpoints["query"] = config.get("obelisk", "query")
           56     endpoints["heart"] = config.get("obelisk", "heart")
           57     endpoints["block"] = config.get("obelisk", "block")
           58     endpoints["trans"] = config.get("obelisk", "trans")
           59 
           60     server_cfg = {}
           61     hostname_list = config.get("obelisk", "hostname").split(",")
           62     server_cfg["server_hostnames"] = hostname_list
           63     server_cfg["server_port"] = port
           64 
           65     global PROTOCOL
           66     PROTOCOL = ElectrumProtocol(log, chain, endpoints, server_cfg)
           67 
           68     server = await asyncio.start_server(PROTOCOL.recv, host, port)
           69     async with server:
           70         await server.serve_forever()
           71 
           72 
           73 def main():
           74     """Main orchestration"""
           75     parser = ArgumentParser(description=f"obelisk {VERSION}")
           76     parser.add_argument("config_file", help="Path to config file")
           77     args = parser.parse_args()
           78 
           79     try:
           80         config = RawConfigParser()
           81         config.read(args.config_file)
           82         config.options("obelisk")
           83     except NoSectionError:
           84         print(f"error: Invalid config file {args.config_file}")
           85         return 1
           86 
           87     log = getLogger("obelisk")
           88     log, logfilename = logger_config(log, config)
           89     log.info(f"Starting obelisk {VERSION}")
           90     log.info(f"Logging to {logfilename}")
           91 
           92     chain = config.get("obelisk", "chain")
           93     if chain not in ("mainnet", "testnet"):
           94         log.error("chain is not 'mainnet' or 'testnet'")
           95         return 1
           96 
           97     try:
           98         asyncio.run(run_electrum_server(config, chain))
           99     except KeyboardInterrupt:
          100         print("\r", end="")
          101         log.debug("Caught KeyboardInterrupt, exiting...")
          102         if PROTOCOL:
          103             asyncio.run(PROTOCOL.stop())
          104         return 0
          105 
          106     return 1
          107 
          108 
          109 if __name__ == "__main__":
          110     sys.exit(main())