Esempio n. 1
0
def default_blockchain_info_opts(config_file=None):
    """
   Get our default blockchain.info options from a config file.
   """

    if config_file is None:
        config_file = virtualchain.get_config_filename()

    parser = SafeConfigParser()
    parser.read(config_file)

    blockchain_info_opts = {}

    api_token = None

    if parser.has_section("blockchain_info"):

        if parser.has_option("blockchain_info", "api_token"):
            api_token = parser.get("blockchain_info", "api_token")

    blockchain_info_opts = {
        "utxo_provider": "blockchain_info",
        "api_token": api_token
    }

    # strip Nones
    for (k, v) in blockchain_info_opts.items():
        if v is None:
            del blockchain_info_opts[k]

    return blockchain_info_opts
Esempio n. 2
0
def default_blockchain_info_opts( config_file=None ):
   """
   Get our default blockchain.info options from a config file.
   """
   
   if config_file is None:
       config_file = virtualchain.get_config_filename()
   
   parser = SafeConfigParser()
   parser.read( config_file )
   
   blockchain_info_opts = {}
   
   api_token = None 
   
   if parser.has_section("blockchain_info"):
       
       if parser.has_option("blockchain_info", "api_token"):
           api_token = parser.get("blockchain_info", "api_token")
           
   blockchain_info_opts = {
       "utxo_provider": "blockchain_info",
       "api_token": api_token
   }
   
   # strip Nones 
   for (k, v) in blockchain_info_opts.items():
      if v is None:
         del blockchain_info_opts[k]
   
   return blockchain_info_opts
Esempio n. 3
0
def default_chaincom_opts(config_file=None):
    """
   Get our default chain.com options from a config file.
   """

    if config_file is None:
        config_file = virtualchain.get_config_filename()

    parser = SafeConfigParser()
    parser.read(config_file)

    chaincom_opts = {}

    api_key_id = None
    api_key_secret = None

    if parser.has_section("chain_com"):

        if parser.has_option("chain_com", "api_key_id"):
            api_key_id = parser.get("chain_com", "api_key_id")

        if parser.has_option("chain_com", "api_key_secret"):
            api_key_secret = parser.get("chain_com", "api_key_secret")

    chaincom_opts = {"utxo_provider": "chain_com", "api_key_id": api_key_id, "api_key_secret": api_key_secret}

    # strip Nones
    for (k, v) in chaincom_opts.items():
        if v is None:
            del chaincom_opts[k]

    return chaincom_opts
Esempio n. 4
0
def default_blockcypher_opts( config_file=None ):
   """
   Get our default blockcypher.com options from a config file.
   """
   
   if config_file is None:
      config_file = virtualchain.get_config_filename()
   
   parser = SafeConfigParser()
   parser.read( config_file )
   
   blockcypher_opts = {}
   
   api_token = None 
   
   if parser.has_section('blockcypher'):
      
      if parser.has_option('blockcypher', 'api_token'):
         api_token = parser.get('blockcypher', 'api_token')
      
   blockcypher_opts = {
       'utxo_provider': "blockcypher",
       'api_token': api_token
   }
    
   
   # strip Nones 
   for (k, v) in blockcypher_opts.items():
      if v is None:
         del blockcypher_opts[k]
   
   return blockcypher_opts
Esempio n. 5
0
def default_chaincom_opts(config_file=None):
    """
   Get our default chain.com options from a config file.
   """

    if config_file is None:
        config_file = virtualchain.get_config_filename()

    parser = SafeConfigParser()
    parser.read(config_file)

    chaincom_opts = {}

    api_key_id = None
    api_key_secret = None

    if parser.has_section('chain_com'):

        if parser.has_option('chain_com', 'api_key_id'):
            api_key_id = parser.get('chain_com', 'api_key_id')

        if parser.has_option('chain_com', 'api_key_secret'):
            api_key_secret = parser.get('chain_com', 'api_key_secret')

        chaincom_opts = {
            'api_key_id': api_key_id,
            'api_key_secret': api_key_secret
        }

    # strip Nones
    for (k, v) in chaincom_opts.items():
        if v is None:
            del chaincom_opts[k]

    return chaincom_opts
Esempio n. 6
0
def default_blockcypher_opts(config_file=None):
    """
   Get our default blockcypher.com options from a config file.
   """

    if config_file is None:
        config_file = virtualchain.get_config_filename()

    parser = SafeConfigParser()
    parser.read(config_file)

    blockcypher_opts = {}

    api_token = None

    if parser.has_section('blockcypher'):

        if parser.has_option('blockcypher', 'api_token'):
            api_token = parser.get('blockcypher', 'api_token')

    blockcypher_opts = {'utxo_provider': "blockcypher", 'api_token': api_token}

    # strip Nones
    for (k, v) in blockcypher_opts.items():
        if v is None:
            del blockcypher_opts[k]

    return blockcypher_opts
Esempio n. 7
0
def configure( config_file=None, force=False, interactive=True ):
   """
   Configure blockstore:  find and store configuration parameters to the config file.
   
   Optionally prompt for missing data interactively (with interactive=True).  Or, raise an exception
   if there are any fields missing.
   
   Optionally force a re-prompting for all configuration details (with force=True)
   
   Return (bitcoind_opts, chaincom_opts)
   """
   
   if config_file is None:
      try:
         config_file = virtualchain.get_config_filename()
      except:
         pass 
   
   bitcoind_message  = "Blockstore does not have enough information to connect\n"
   bitcoind_message += "to bitcoind.  Please supply the following parameters:"
   
   bitcoind_opts = {}
   bitcoind_params = ["server", "port", "user", "passwd", "use_https"]
   
   chaincom_message  = 'NOTE: Blockstore currently requires API access to chain.com\n'
   chaincom_message += 'for getting unspent outputs. We will add support for using\n'
   chaincom_message += 'bitcoind and/or other API providers in the next release.\n'
   chaincom_message += "\n"
   chaincom_message += "If you have not done so already, please go to https://chain.com\n"
   chaincom_message += "and register for an API key and secret.  Once you have them,"
   chaincom_message += "please enter them here."
   
   chaincom_opts = {}
   chaincom_params = ["api_key_id", "api_key_secret"]
   
   if not force:
      
      # get current set of bitcoind opts
      tmp_bitcoind_opts = default_bitcoind_opts( config_file=config_file )
      bitcoind_opts = opt_strip( "bitcoind_", tmp_bitcoind_opts )
         
      # get current set of chaincom opts 
      chaincom_opts = default_chaincom_opts( config_file=config_file )
      
   # get any missing fields 
   bitcoind_opts, missing_bitcoin_opts = find_missing( bitcoind_message, bitcoind_params, bitcoind_opts, prompt_missing=interactive )
   chaincom_opts, missing_chaincom_opts = find_missing( chaincom_message, chaincom_params, chaincom_opts, prompt_missing=interactive )
   
   if not interactive and (len(missing_bitcoin_opts) > 0 or len(missing_chaincom_opts) > 0):
       
       # cannot continue 
       raise Exception("Missing configuration fields: %s" % (",".join( missing_bitcoin_opts + missing_chaincom_opts )) )
                       
   return (bitcoind_opts, chaincom_opts)
def get_magic_bytes():
   """
   (required by virtualchain state engine)
   
   Get the magic byte sequence for our OP_RETURNs
   """
   blockstore_opts = default_blockstore_opts( virtualchain.get_config_filename() )
   if blockstore_opts['testset']:
       return MAGIC_BYTES_TESTSET
   
   else:
       return MAGIC_BYTES_MAINSET
Esempio n. 9
0
def get_magic_bytes():
    """
   (required by virtualchain state engine)
   
   Get the magic byte sequence for our OP_RETURNs
   """
    blockstore_opts = default_blockstore_opts(
        virtualchain.get_config_filename())
    if blockstore_opts['testset']:
        return MAGIC_BYTES_TESTSET

    else:
        return MAGIC_BYTES_MAINSET
Esempio n. 10
0
def default_blockstore_opts( config_file=None, testset=False ):
   """
   Get our default blockstore opts from a config file
   or from sane defaults.
   """
   
   if config_file is None:
      config_file = virtualchain.get_config_filename()
   
   parser = SafeConfigParser()
   parser.read( config_file )
   
   blockstore_opts = {}
   tx_broadcaster = None 
   utxo_provider = None
   testset_first_block = None
   max_subsidy = 0
   
   if parser.has_section('blockstore'):
      
      if parser.has_option('blockstore', 'tx_broadcaster'):
         tx_broadcaster = parser.get('blockstore', 'tx_broadcaster')
      
      if parser.has_option('blockstore', 'utxo_provider'):
         utxo_provider = parser.get('blockstore', 'utxo_provider')
      
      if parser.has_option('blockstore', 'testset'):
         testset = bool(parser.get('blockstore', 'testset'))
         
      if parser.has_option('blockstore', 'testset_first_block'):
         testset_first_block = int( parser.get('blockstore', 'testset_first_block') )
         
      if parser.has_option('blockstore', 'max_subsidy'):
         max_subsidy = int( parser.get('blockstore', 'max_subsidy'))
         
         
   blockstore_opts = {
       'tx_broadcaster': tx_broadcaster,
       'utxo_provider': utxo_provider,
       'testset': testset,
       'testset_first_block': testset_first_block,
       'max_subsidy': max_subsidy
   }
   
   # strip Nones 
   for (k, v) in blockstore_opts.items():
      if v is None:
         del blockstore_opts[k]
   
   return blockstore_opts
Esempio n. 11
0
def setup( return_parser=False ):
   """
   Do one-time initialization.
   Call this to set up global state and set signal handlers.
   
   If return_parser is True, return a partially-
   setup argument parser to be populated with 
   subparsers (i.e. as part of main())
   
   Otherwise return None.
   """
   
   global blockstore_opts 
   global blockchain_client
   global blockchain_broadcaster
   global bitcoin_opts
   global utxo_opts 
   global blockstore_opts
   global dht_opts
   
   # set up our implementation 
   virtualchain.setup_virtualchain( blockstore_state_engine )
   
   # acquire configuration, and store it globally
   blockstore_opts, bitcoin_opts, utxo_opts, dht_opts = configure( interactive=True )
   
   # merge in command-line bitcoind options 
   config_file = virtualchain.get_config_filename()
   
   arg_bitcoin_opts = None 
   argparser = None 
   
   if return_parser:
      arg_bitcoin_opts, argparser = virtualchain.parse_bitcoind_args( return_parser=return_parser )
   
   else:
      arg_bitcoin_opts = virtualchain.parse_bitcoind_args( return_parser=return_parser )

   # command-line overrides config file
   for (k, v) in arg_bitcoin_opts.items():
      bitcoin_opts[k] = v
   
   # store options 
   set_bitcoin_opts( bitcoin_opts )
   set_utxo_opts( utxo_opts )
   
   if return_parser:
      return argparser 
   else:
      return None
Esempio n. 12
0
def default_blockstore_opts(config_file=None, testset=False):
    """
   Get our default blockstore opts from a config file
   or from sane defaults.
   """

    if config_file is None:
        config_file = virtualchain.get_config_filename()

    parser = SafeConfigParser()
    parser.read(config_file)

    blockstore_opts = {}
    tx_broadcaster = None
    utxo_provider = None
    testset_first_block = None
    max_subsidy = 0

    if parser.has_section('blockstore'):

        if parser.has_option('blockstore', 'tx_broadcaster'):
            tx_broadcaster = parser.get('blockstore', 'tx_broadcaster')

        if parser.has_option('blockstore', 'utxo_provider'):
            utxo_provider = parser.get('blockstore', 'utxo_provider')

        if parser.has_option('blockstore', 'testset'):
            testset = bool(parser.get('blockstore', 'testset'))

        if parser.has_option('blockstore', 'testset_first_block'):
            testset_first_block = int(
                parser.get('blockstore', 'testset_first_block'))

        if parser.has_option('blockstore', 'max_subsidy'):
            max_subsidy = int(parser.get('blockstore', 'max_subsidy'))

    blockstore_opts = {
        'tx_broadcaster': tx_broadcaster,
        'utxo_provider': utxo_provider,
        'testset': testset,
        'testset_first_block': testset_first_block,
        'max_subsidy': max_subsidy
    }

    # strip Nones
    for (k, v) in blockstore_opts.items():
        if v is None:
            del blockstore_opts[k]

    return blockstore_opts
Esempio n. 13
0
def setup( return_parser=False ):
   """
   Do one-time initialization.
   Call this to set up global state and set signal handlers.
   
   If return_parser is True, return a partially-
   setup argument parser to be populated with 
   subparsers (i.e. as part of main())
   
   Otherwise return None.
   """
   
   global blockchain_client
   global bitcoin_opts
   global chaincom_opts
   
   # set up our implementation 
   virtualchain.setup_virtualchain( blockstore_state_engine )
   
   # acquire configuration, and store it globally
   bitcoin_opts, chaincom_opts = configure( interactive=True )
   
   # merge in command-line bitcoind options 
   config_file = virtualchain.get_config_filename()
   
   arg_bitcoin_opts = None 
   argparser = None 
   
   if return_parser:
      arg_bitcoin_opts, argparser = virtualchain.parse_bitcoind_args( return_parser=return_parser )
   
   else:
      arg_bitcoin_opts = virtualchain.parse_bitcoind_args( return_parser=return_parser )

   # command-line overrides config file
   for (k, v) in arg_bitcoin_opts.items():
      bitcoin_opts[k] = v
   
   # store options 
   set_bitcoin_opts( bitcoin_opts )
   set_chaincom_opts( chaincom_opts )
   
   if return_parser:
      return argparser 
   else:
      return None
Esempio n. 14
0
def default_utxo_provider( config_file=None ):
   """
   Get our defualt UTXO provider options from a config file.
   """
   
   global SUPPORTED_UTXO_PROVIDERS
   
   if config_file is None:
      config_file = virtualchain.get_config_filename()
   
   parser = SafeConfigParser()
   parser.read( config_file )
   
   for provider_name in SUPPORTED_UTXO_PROVIDERS:
       if parser.has_section( provider_name ):
           return provider_name 
       
   return None
Esempio n. 15
0
def default_utxo_provider(config_file=None):
    """
   Get our defualt UTXO provider options from a config file.
   """

    global SUPPORTED_UTXO_PROVIDERS

    if config_file is None:
        config_file = virtualchain.get_config_filename()

    parser = SafeConfigParser()
    parser.read(config_file)

    for provider_name in SUPPORTED_UTXO_PROVIDERS:
        if parser.has_section(provider_name):
            return provider_name

    return None
Esempio n. 16
0
def get_first_block_id():
   """
   (required by virtualchain state engine)
   
   Get the id of the first block to start indexing.
   """ 
   blockstore_opts = default_blockstore_opts( virtualchain.get_config_filename() )
   start_block = None
   
   if TESTNET:
       if blockstore_opts['testset']:
           start_block = FIRST_BLOCK_TESTNET_TESTSET
       else:
           start_block = FIRST_BLOCK_TESTNET
   else:
       if blockstore_opts['testset']:
           start_block = FIRST_BLOCK_MAINNET_TESTSET
       else:
           start_block = FIRST_BLOCK_MAINNET

   return start_block
Esempio n. 17
0
def get_first_block_id():
    """
   (required by virtualchain state engine)
   
   Get the id of the first block to start indexing.
   """
    blockstore_opts = default_blockstore_opts(
        virtualchain.get_config_filename())
    start_block = None

    if TESTNET:
        if blockstore_opts['testset']:
            start_block = FIRST_BLOCK_TESTNET_TESTSET
        else:
            start_block = FIRST_BLOCK_TESTNET
    else:
        if blockstore_opts['testset']:
            start_block = FIRST_BLOCK_MAINNET_TESTSET
        else:
            start_block = FIRST_BLOCK_MAINNET

    return start_block
Esempio n. 18
0
def write_config_file(bitcoind_opts=None,
                      chaincom_opts=None,
                      config_file=None):
    """
   Update a configuration file, given the bitcoind options and chain.com options.
   Return True on success 
   Return False on failure
   """

    if config_file is None:
        try:
            config_file = virtualchain.get_config_filename()
        except:
            return False

    if config_file is None:
        return False

    parser = SafeConfigParser()
    parser.read(config_file)

    if bitcoind_opts is not None:

        bitcoind_opts = opt_strip("bitcoind_", bitcoind_opts)

        for opt_name, opt_value in bitcoind_opts.items():
            parser.set('bitcoind', opt_name, opt_value)

    if chaincom_opts is not None:

        for opt_name, opt_value in chaincom_opts.items():
            parser.set('chain_com', opt_name, opt_value)

    with open(config_file, "w") as fout:
        parser.write(fout)

    return True
Esempio n. 19
0
def write_config_file( bitcoind_opts=None, chaincom_opts=None, config_file=None ):
   """
   Update a configuration file, given the bitcoind options and chain.com options.
   Return True on success 
   Return False on failure
   """
   
   if config_file is None:
      try:
         config_file = virtualchain.get_config_filename()
      except:
         return False
      
   if config_file is None:
      return False 
   
   parser = SafeConfigParser()
   parser.read(config_file)
   
   if bitcoind_opts is not None:
      
      bitcoind_opts = opt_strip( "bitcoind_", bitcoind_opts )
      
      for opt_name, opt_value in bitcoind_opts.items():
         parser.set( 'bitcoind', opt_name, opt_value )
      
   if chaincom_opts is not None:
      
      for opt_name, opt_value in chaincom_opts.items():
         parser.set( 'chain_com', opt_name, opt_value )
      
   with open(config_file, "w") as fout:
      parser.write( fout )
   
   return True

   
Esempio n. 20
0
def default_blockstore_opts( config_file=None ):
   """
   Get our default blockstore opts from a config file
   or from sane defaults.
   """
   
   if config_file is None:
      config_file = virtualchain.get_config_filename()
   
   parser = SafeConfigParser()
   parser.read( config_file )
   
   blockstore_opts = {}
   tx_broadcaster = None 
   utxo_provider = None
   
   if parser.has_section('blockstore'):
      
      if parser.has_option('blockstore', 'tx_broadcaster'):
         tx_broadcaster = parser.get('blockstore', 'tx_broadcaster')
      
      if parser.has_option('blockstore', 'utxo_provider'):
         utxo_provider = parser.get('blockstore', 'utxo_provider')
      
   blockstore_opts = {
       'tx_broadcaster': tx_broadcaster,
       'utxo_provider': utxo_provider
   }
    
   
   # strip Nones 
   for (k, v) in blockstore_opts.items():
      if v is None:
         del blockstore_opts[k]
   
   return blockstore_opts
Esempio n. 21
0
def default_chaincom_opts( config_file=None ):
   """
   Get our default chain.com options from a config file.
   """
   
   if config_file is None:
      config_file = virtualchain.get_config_filename()
   
   parser = SafeConfigParser()
   parser.read( config_file )
   
   chaincom_opts = {}
   
   api_key_id = None 
   api_key_secret = None
   
   if parser.has_section('chain_com'):
      
      if parser.has_option('chain_com', 'api_key_id'):
         api_key_id = parser.get('chain_com', 'api_key_id')
      
      if parser.has_option('chain_com', 'api_key_secret'):
         api_key_secret = parser.get('chain_com', 'api_key_secret')
      
      chaincom_opts = {
         'api_key_id': api_key_id,
         'api_key_secret': api_key_secret
      }
      
   
   # strip Nones 
   for (k, v) in chaincom_opts.items():
      if v is None:
         del chaincom_opts[k]
   
   return chaincom_opts
Esempio n. 22
0
def default_blockstack_opts( config_file=None, virtualchain_impl=None ):
   """
   Get our default blockstack opts from a config file
   or from sane defaults.
   """

   if config_file is None:
      config_file = virtualchain.get_config_filename()

   announce_path = get_announce_filename( virtualchain.get_working_dir(impl=virtualchain_impl) )

   parser = SafeConfigParser()
   parser.read( config_file )

   blockstack_opts = {}
   contact_email = None
   announcers = "judecn.id,muneeb.id,shea256.id"
   announcements = None
   backup_frequency = 144   # once a day; 10 minute block time
   backup_max_age = 1008    # one week
   rpc_port = RPC_SERVER_PORT 
   serve_zonefiles = True
   serve_profiles = False
   serve_data = False
   zonefile_dir = os.path.join( os.path.dirname(config_file), "zonefiles")
   analytics_key = None
   zonefile_storage_drivers = "disk,dht"
   zonefile_storage_drivers_write = "disk"
   profile_storage_drivers = "disk"
   profile_storage_drivers_write = "disk"
   data_storage_drivers = "disk"
   data_storage_drivers_write = "disk"
   redirect_data = False
   data_servers = None
   server_version = None
   atlas_enabled = True
   atlas_seed_peers = "node.blockstack.org:%s" % RPC_SERVER_PORT
   atlasdb_path = os.path.join( os.path.dirname(config_file), "atlas.db" )
   atlas_blacklist = ""
   atlas_hostname = socket.gethostname()

   if parser.has_section('blockstack'):

      if parser.has_option('blockstack', 'backup_frequency'):
         backup_frequency = int( parser.get('blockstack', 'backup_frequency'))

      if parser.has_option('blockstack', 'backup_max_age'):
         backup_max_age = int( parser.get('blockstack', 'backup_max_age') )

      if parser.has_option('blockstack', 'email'):
         contact_email = parser.get('blockstack', 'email')

      if parser.has_option('blockstack', 'rpc_port'):
         rpc_port = int(parser.get('blockstack', 'rpc_port'))

      if parser.has_option('blockstack', 'serve_zonefiles'):
          serve_zonefiles = parser.get('blockstack', 'serve_zonefiles')
          if serve_zonefiles.lower() in ['1', 'yes', 'true', 'on']:
              serve_zonefiles = True
          else:
              serve_zonefiles = False

      if parser.has_option('blockstack', 'serve_profiles'):
          serve_profiles = parser.get('blockstack', 'serve_profiles')
          if serve_profiles.lower() in ['1', 'yes', 'true', 'on']:
              serve_profiles = True
          else:
              serve_profiles = False

      if parser.has_option('blockstack', 'serve_data'):
          serve_data = parser.get('blockstack', 'serve_data')
          if serve_data.lower() in ['1', 'yes', 'true', 'on']:
              serve_data = True
          else:
              serve_data = False

      if parser.has_option("blockstack", "zonefile_storage_drivers"):
          zonefile_storage_drivers = parser.get("blockstack", "zonefile_storage_drivers")

      if parser.has_option("blockstack", "zonefile_storage_drivers_write"):
          zonefile_storage_drivers_write = parser.get("blockstack", "zonefile_storage_drivers_write")

      if parser.has_option("blockstack", "profile_storage_drivers"):
          profile_storage_drivers = parser.get("blockstack", "profile_storage_drivers")

      if parser.has_option("blockstack", "profile_storage_drivers_write"):
          profile_storage_drivers_write = parser.get("blockstack", "profile_storage_drivers_write")

      if parser.has_option("blockstack", "data_storage_drivers"):
          data_storage_drivers = parser.get("blockstack", "data_storage_drivers")

      if parser.has_option("blockstack", "data_storage_drivers_write"):
          data_storage_drivers_write = parser.get("blockstack", "data_storage_drivers_write")

      if parser.has_option("blockstack", "zonefiles"):
          zonefile_dir = parser.get("blockstack", "zonefiles")
    
      if parser.has_option('blockstack', 'redirect_data'):
          redirect_data = parser.get('blockstack', 'redirect_data')
          if redirect_data.lower() in ['1', 'yes', 'true', 'on']:
              redirect_data = True
          else:
              redirect_data = False

      if parser.has_option('blockstack', 'data_servers'):
          data_servers = parser.get('blockstack', 'data_servers')

          # must be a CSV of host:port
          hostports = filter( lambda x: len(x) > 0, data_servers.split(",") )
          for hp in hostports:
              host, port = url_to_host_port( hp )
              assert host is not None and port is not None


      if parser.has_option('blockstack', 'announcers'):
         # must be a CSV of blockchain IDs
         announcer_list_str = parser.get('blockstack', 'announcers')
         announcer_list = filter( lambda x: len(x) > 0, announcer_list_str.split(",") )

         import scripts

         # validate each one
         valid = True
         for bid in announcer_list:
             if not scripts.is_name_valid( bid ):
                 log.error("Invalid blockchain ID '%s'" % bid)
                 valid = False

         if valid:
             announcers = ",".join(announcer_list)

      if parser.has_option('blockstack', 'analytics_key'):
         analytics_key = parser.get('blockstack', 'analytics_key')

      if parser.has_option('blockstack', 'server_version'):
         server_version = parser.get('blockstack', 'server_version')

      if parser.has_option('blockstack', 'atlas'):
         atlas_enabled = parser.get('blockstack', 'atlas')
         if atlas_enabled.lower() in ['true', '1', 'enabled', 'enabled', 'on']:
            atlas_enabled = True
         else:
            atlas_enabled = False

      if parser.has_option('blockstack', 'atlas_seeds'):
         atlas_seed_peers = parser.get('blockstack', 'atlas_seeds')
         
         # must be a CSV of host:port
         hostports = filter( lambda x: len(x) > 0, atlas_seed_peers.split(",") )
         for hp in hostports:
             host, port = url_to_host_port( hp )
             assert host is not None and port is not None

      if parser.has_option('blockstack', 'atlasdb_path'):
         atlasdb_path = parser.get('blockstack', 'atlasdb_path')

      if parser.has_option('blockstack', 'atlas_blacklist'):
         atlas_blacklist = parser.get('blockstack', 'atlas_blacklist')

         # must be a CSV of host:port
         hostports = filter( lambda x: len(x) > 0, atlas_blacklist.split(",") )
         for hp in hostports:
             host, port = url_to_host_port( hp )
             assert host is not None and port is not None

      if parser.has_option('blockstack', 'atlas_hostname'):
         atlas_hostname = parser.get('blockstack', 'atlas_hostname')
        

   if os.path.exists( announce_path ):
       # load announcement list
       with open( announce_path, "r" ) as f:
           announce_text = f.readlines()

       all_announcements = [ a.strip() for a in announce_text ]
       unseen_announcements = []

       # find announcements we haven't seen yet
       for a in all_announcements:
           if a not in ANNOUNCEMENTS:
               unseen_announcements.append( a )

       announcements = ",".join( unseen_announcements )

   if zonefile_dir is not None and not os.path.exists( zonefile_dir ):
       try:
           os.makedirs( zonefile_dir, 0700 )
       except:
           pass

   blockstack_opts = {
       'rpc_port': rpc_port,
       'email': contact_email,
       'announcers': announcers,
       'announcements': announcements,
       'backup_frequency': backup_frequency,
       'backup_max_age': backup_max_age,
       'serve_zonefiles': serve_zonefiles,
       'zonefile_storage_drivers': zonefile_storage_drivers,
       "zonefile_storage_drivers_write": zonefile_storage_drivers_write,
       'serve_profiles': serve_profiles,
       'profile_storage_drivers': profile_storage_drivers,
       "profile_storage_drivers_write": profile_storage_drivers_write,
       'serve_data': serve_data,
       'data_storage_drivers': data_storage_drivers,
       "data_storage_drivers_write": data_storage_drivers_write,
       'redirect_data': redirect_data,
       'data_servers': data_servers,
       'analytics_key': analytics_key,
       'server_version': server_version,
       'atlas': atlas_enabled,
       'atlas_seeds': atlas_seed_peers,
       'atlasdb_path': atlasdb_path,
       'atlas_blacklist': atlas_blacklist,
       'atlas_hostname': atlas_hostname,
       'zonefiles': zonefile_dir,
   }

   # strip Nones
   for (k, v) in blockstack_opts.items():
      if v is None:
         del blockstack_opts[k]

   return blockstack_opts
Esempio n. 23
0
def configure(config_file=None, force=False, interactive=True):
    """
   Configure blockstore:  find and store configuration parameters to the config file.
   
   Optionally prompt for missing data interactively (with interactive=True).  Or, raise an exception
   if there are any fields missing.
   
   Optionally force a re-prompting for all configuration details (with force=True)
   
   Return (bitcoind_opts, chaincom_opts)
   """

    if config_file is None:
        try:
            config_file = virtualchain.get_config_filename()
        except:
            pass

    bitcoind_message = "Blockstore does not have enough information to connect\n"
    bitcoind_message += "to bitcoind.  Please supply the following parameters:"

    bitcoind_opts = {}
    bitcoind_params = ["server", "port", "user", "passwd", "use_https"]

    chaincom_message = 'NOTE: Blockstore currently requires API access to chain.com\n'
    chaincom_message += 'for getting unspent outputs. We will add support for using\n'
    chaincom_message += 'bitcoind and/or other API providers in the next release.\n'
    chaincom_message += "\n"
    chaincom_message += "If you have not done so already, please go to https://chain.com\n"
    chaincom_message += "and register for an API key and secret.  Once you have them,"
    chaincom_message += "please enter them here."

    chaincom_opts = {}
    chaincom_params = ["api_key_id", "api_key_secret"]

    if not force:

        # get current set of bitcoind opts
        tmp_bitcoind_opts = default_bitcoind_opts(config_file=config_file)
        bitcoind_opts = opt_strip("bitcoind_", tmp_bitcoind_opts)

        # get current set of chaincom opts
        chaincom_opts = default_chaincom_opts(config_file=config_file)

    # get any missing fields
    bitcoind_opts, missing_bitcoin_opts = find_missing(
        bitcoind_message,
        bitcoind_params,
        bitcoind_opts,
        prompt_missing=interactive)
    chaincom_opts, missing_chaincom_opts = find_missing(
        chaincom_message,
        chaincom_params,
        chaincom_opts,
        prompt_missing=interactive)

    if not interactive and (len(missing_bitcoin_opts) > 0
                            or len(missing_chaincom_opts) > 0):

        # cannot continue
        raise Exception(
            "Missing configuration fields: %s" %
            (",".join(missing_bitcoin_opts + missing_chaincom_opts)))

    return (bitcoind_opts, chaincom_opts)
Esempio n. 24
0
def default_dht_opts(config_file=None):
    """
   Get our default DHT options from the config file.
   """

    global DHT_SERVER_PORT, DEFAULT_DHT_SERVERS

    if config_file is None:
        config_file = virtualchain.get_config_filename()

    defaults = {
        'disable':
        str(False),
        'port':
        str(DHT_SERVER_PORT),
        'servers':
        ",".join(
            ["%s:%s" % (host, port) for (host, port) in DEFAULT_DHT_SERVERS])
    }

    parser = SafeConfigParser(defaults)
    parser.read(config_file)

    if parser.has_section('dht'):

        disable = parser.get('dht', 'disable')
        port = parser.get('dht', 'port')
        servers = parser.get(
            'dht', 'servers')  # expect comma-separated list of host:port

        if disable is None:
            disable = False

        if port is None:
            port = DHT_SERVER_PORT

        if servers is None:
            servers = DEFAULT_DHT_SERVERS

        try:
            disable = bool(disable)
        except:
            raise Exception(
                "Invalid field value for dht.disable: expected bool")

        try:
            port = int(port)
        except:
            raise Exception("Invalid field value for dht.port: expected int")

        parsed_servers = []
        try:
            server_list = servers.split(",")
            for server in server_list:
                server_host, server_port = server.split(":")
                server_port = int(server_port)

                parsed_servers.append((server_host, server_port))

        except:
            raise Exception(
                "Invalid field value for dht.servers: expected 'HOST:PORT[,HOST:PORT...]'"
            )

        dht_opts = {
            'disable': disable,
            'port': port,
            'servers': parsed_servers
        }

        return dht_opts

    else:

        # use defaults
        dht_opts = {
            'disable': False,
            'port': DHT_SERVER_PORT,
            'servers': DEFAULT_DHT_SERVERS
        }

        return dht_opts
Esempio n. 25
0
def default_blockstack_opts( config_file=None ):
   """
   Get our default blockstack opts from a config file
   or from sane defaults.
   """

   if config_file is None:
      config_file = virtualchain.get_config_filename()

   announce_path = get_announce_filename( virtualchain.get_working_dir() )

   parser = SafeConfigParser()
   parser.read( config_file )

   blockstack_opts = {}
   contact_email = None
   announcers = "judecn.id,muneeb.id,shea256.id"
   announcements = None
   backup_frequency = 1008  # once a week; 10 minute block time
   backup_max_age = 12096   # 12 weeks
   rpc_port = RPC_SERVER_PORT 
   blockchain_proxy = False
   serve_zonefiles = True
   serve_profiles = False
   zonefile_dir = None
   analytics_key = None
   zonefile_storage_drivers = "disk"
   profile_storage_drivers = ""
   server_version = None

   if parser.has_section('blockstack'):

      if parser.has_option('blockstack', 'backup_frequency'):
         backup_frequency = int( parser.get('blockstack', 'backup_frequency'))

      if parser.has_option('blockstack', 'backup_max_age'):
         backup_max_age = int( parser.get('blockstack', 'backup_max_age') )

      if parser.has_option('blockstack', 'email'):
         contact_email = parser.get('blockstack', 'email')

      if parser.has_option('blockstack', 'rpc_port'):
         rpc_port = int(parser.get('blockstack', 'rpc_port'))

      if parser.has_option('blockstack', 'blockchain_proxy'):
         blockchain_proxy = parser.get('blockstack', 'blockchain_proxy')
         if blockchain_proxy.lower() in ['1', 'yes', 'true', 'on']:
             blockchain_proxy = True
         else:
             blockchain_proxy = False

      if parser.has_option('blockstack', 'serve_zonefiles'):
          serve_zonefiles = parser.get('blockstack', 'serve_zonefiles')
          if serve_zonefiles.lower() in ['1', 'yes', 'true', 'on']:
              serve_zonefiles = True
          else:
              serve_zonefiles = False

      if parser.has_option('blockstack', 'serve_profiles'):
          serve_profiles = parser.get('blockstack', 'serve_profiles')
          if serve_profiles.lower() in ['1', 'yes', 'true', 'on']:
              serve_profiles = True
          else:
              serve_profiles = False

      if parser.has_option("blockstack", "zonefile_storage_drivers"):
          zonefile_storage_drivers = parser.get("blockstack", "zonefile_storage_drivers")

      if parser.has_option("blockstack", "profile_storage_drivers"):
          profile_storage_drivers = parser.get("blockstack", "profile_storage_drivers")

      if parser.has_option("blockstack", "zonefiles"):
          zonefile_dir = parser.get("blockstack", "zonefiles")

      if parser.has_option('blockstack', 'announcers'):
         # must be a CSV of blockchain IDs
         announcer_list_str = parser.get('blockstack', 'announcers')
         announcer_list = announcer_list_str.split(",")

         import scripts

         # validate each one
         valid = True
         for bid in announcer_list:
             if not scripts.is_name_valid( bid ):
                 log.error("Invalid blockchain ID '%s'" % bid)
                 valid = False

         if valid:
             announcers = ",".join(announcer_list)

      if parser.has_option('blockstack', 'analytics_key'):
         analytics_key = parser.get('blockstack', 'analytics_key')

      if parser.has_option('blockstack', 'server_version'):
         server_version = parser.get('blockstack', 'server_version')


   if os.path.exists( announce_path ):
       # load announcement list
       with open( announce_path, "r" ) as f:
           announce_text = f.readlines()

       all_announcements = [ a.strip() for a in announce_text ]
       unseen_announcements = []

       # find announcements we haven't seen yet
       for a in all_announcements:
           if a not in ANNOUNCEMENTS:
               unseen_announcements.append( a )

       announcements = ",".join( unseen_announcements )

   if zonefile_dir is not None and not os.path.exists( zonefile_dir ):
       try:
           os.makedirs( zonefile_dir, 0700 )
       except:
           pass

   blockstack_opts = {
       'rpc_port': rpc_port,
       'email': contact_email,
       'announcers': announcers,
       'announcements': announcements,
       'backup_frequency': backup_frequency,
       'backup_max_age': backup_max_age,
       'blockchain_proxy': blockchain_proxy,
       'serve_zonefiles': serve_zonefiles,
       'serve_profiles': serve_profiles,
       'zonefile_storage_drivers': zonefile_storage_drivers,
       'profile_storage_drivers': profile_storage_drivers,
       'zonefiles': zonefile_dir,
       'analytics_key': analytics_key,
       'server_version': server_version
   }

   # strip Nones
   for (k, v) in blockstack_opts.items():
      if v is None:
         del blockstack_opts[k]

   return blockstack_opts
Esempio n. 26
0
def write_config_file(blockstore_opts=None,
                      bitcoind_opts=None,
                      utxo_opts=None,
                      dht_opts=None,
                      config_file=None):
    """
   Update a configuration file, given the bitcoind options and chain.com options.
   Return True on success
   Return False on failure
   """

    if config_file is None:
        try:
            config_file = virtualchain.get_config_filename()
        except:
            return False

    if config_file is None:
        return False

    parser = SafeConfigParser()
    parser.read(config_file)

    if bitcoind_opts is not None and len(bitcoind_opts) > 0:

        tmp_bitcoind_opts = opt_strip("bitcoind_", bitcoind_opts)

        if parser.has_section('bitcoind'):
            parser.remove_section('bitcoind')

        parser.add_section('bitcoind')
        for opt_name, opt_value in tmp_bitcoind_opts.items():
            if opt_value is None:
                raise Exception("%s is not defined" % opt_name)
            parser.set('bitcoind', opt_name, "%s" % opt_value)

    if utxo_opts is not None and len(utxo_opts) > 0:

        if parser.has_section(utxo_opts['utxo_provider']):
            parser.remove_section(utxo_opts['utxo_provider'])

        parser.add_section(utxo_opts['utxo_provider'])
        for opt_name, opt_value in utxo_opts.items():

            # don't log this meta-field
            if opt_name == 'utxo_provider':
                continue

            if opt_value is None:
                raise Exception("%s is not defined" % opt_name)

            parser.set(utxo_opts['utxo_provider'], opt_name, "%s" % opt_value)

    if dht_opts is not None and len(dht_opts) > 0:

        if parser.has_section("dht"):
            parser.remove_section("dht")

        parser.add_section("dht")
        for opt_name, opt_value in dht_opts.items():

            if opt_value is None:
                raise Exception("%s is not defined" % opt_name)

            parser.set("dht", opt_name, "%s" % opt_value)

    if blockstore_opts is not None and len(blockstore_opts) > 0:

        if parser.has_section("blockstore"):
            parser.remove_section("blockstore")

        parser.add_section("blockstore")
        for opt_name, opt_value in blockstore_opts.items():

            if opt_value is None:
                raise Exception("%s is not defined" % opt_name)

            parser.set("blockstore", opt_name, "%s" % opt_value)

    with open(config_file, "w") as fout:
        os.fchmod(fout.fileno(), 0600)
        parser.write(fout)

    return True
def configure( config_file=None, force=False, interactive=True ):
   """
   Configure blockstack:  find and store configuration parameters to the config file.

   Optionally prompt for missing data interactively (with interactive=True).  Or, raise an exception
   if there are any fields missing.

   Optionally force a re-prompting for all configuration details (with force=True)

   Return {'blockstack': {...}, 'bitcoind': {...}}
   """

   if config_file is None:
      try:
         # get input for everything
         config_file = virtualchain.get_config_filename()
      except:
         raise

   if not os.path.exists( config_file ):
       # definitely ask for everything
       force = True

   log.debug("Load config from '%s'" % config_file)

   # get blockstack opts
   blockstack_opts = {}
   blockstack_opts_defaults = default_blockstack_opts( config_file=config_file )
   blockstack_params = blockstack_opts_defaults.keys()

   if not force:

       # default blockstack options
       blockstack_opts = default_blockstack_opts( config_file=config_file )

   blockstack_msg = "ADVANCED USERS ONLY.\nPlease enter blockstack configuration hints."

   # NOTE: disabled
   blockstack_opts, missing_blockstack_opts, num_blockstack_opts_prompted = blockstack_client.config.find_missing( blockstack_msg, \
                                                                                                                   blockstack_params, \
                                                                                                                   blockstack_opts, \
                                                                                                                   blockstack_opts_defaults, \
                                                                                                                   prompt_missing=False )

   bitcoind_message  = "Blockstack does not have enough information to connect\n"
   bitcoind_message += "to bitcoind.  Please supply the following parameters, or\n"
   bitcoind_message += "press [ENTER] to select the default value."

   bitcoind_opts = {}
   bitcoind_opts_defaults = blockstack_client.config.default_bitcoind_opts( config_file=config_file )
   bitcoind_params = bitcoind_opts_defaults.keys()

   if not force:

      # get default set of bitcoind opts
      bitcoind_opts = blockstack_client.config.default_bitcoind_opts( config_file=config_file )


   # get any missing bitcoind fields
   bitcoind_opts, missing_bitcoin_opts, num_bitcoind_prompted = blockstack_client.config.find_missing( bitcoind_message, \
                                                                                                       bitcoind_params, \
                                                                                                       bitcoind_opts, \
                                                                                                       bitcoind_opts_defaults, \
                                                                                                       prompt_missing=interactive )

   if not interactive and (len(missing_bitcoin_opts) > 0 or len(missing_blockstack_opts) > 0):
       # cannot continue
       raise Exception("Missing configuration fields: %s" % (",".join( missing_blockstack_opts + missing_bitcoin_opts )) )

   # ask for contact info, so we can send out notifications for bugfixes and upgrades
   if blockstack_opts.get('email', None) is None:
       email_msg = "Would you like to receive notifications\n"
       email_msg+= "from the developers when there are critical\n"
       email_msg+= "updates available to install?\n\n"
       email_msg+= "If so, please enter your email address here.\n"
       email_msg+= "If not, leave this field blank.\n\n"
       email_msg+= "Your email address will be used solely\n"
       email_msg+= "for this purpose.\n"
       email_opts, _, email_prompted = blockstack_client.config.find_missing( email_msg, ['email'], {}, {'email': ''}, prompt_missing=interactive )

       # merge with blockstack section
       num_blockstack_opts_prompted += 1
       blockstack_opts['email'] = email_opts['email']

   ret = {
      'blockstack': blockstack_opts,
      'bitcoind': bitcoind_opts
   }

   # if we prompted, then save
   if num_bitcoind_prompted > 0 or num_blockstack_opts_prompted > 0:
       print >> sys.stderr, "Saving configuration to %s" % config_file
   
       # always set version when writing
       config_opts = copy.deepcopy(ret)
       if not config_opts['blockstack'].has_key('server_version'):
           config_opts['blockstack']['server_version'] = VERSION

       # if the config file doesn't exist, then set the version 
       # in ret as well, since it's what's written
       if not os.path.exists(config_file):
           ret['blockstack']['server_version'] = VERSION

       blockstack_client.config.write_config_file( config_opts, config_file )

   # prefix our bitcoind options, so they work with virtualchain
   ret['bitcoind'] = blockstack_client.config.opt_restore("bitcoind_", ret['bitcoind'])
   return ret 
Esempio n. 28
0
def configure( config_file=None, force=False, interactive=True ):
   """
   Configure blockstack:  find and store configuration parameters to the config file.

   Optionally prompt for missing data interactively (with interactive=True).  Or, raise an exception
   if there are any fields missing.

   Optionally force a re-prompting for all configuration details (with force=True)

   Return {'blockstack': {...}, 'bitcoind': {...}}
   """

   if config_file is None:
      try:
         # get input for everything
         config_file = virtualchain.get_config_filename()
      except:
         raise

   if not os.path.exists( config_file ):
       # definitely ask for everything
       force = True

   log.debug("Load config from '%s'" % config_file)

   # get blockstack opts
   blockstack_opts = {}
   blockstack_opts_defaults = default_blockstack_opts( config_file=config_file )
   blockstack_params = blockstack_opts_defaults.keys()

   if not force:

       # default blockstack options
       blockstack_opts = default_blockstack_opts( config_file=config_file )

   blockstack_msg = "ADVANCED USERS ONLY.\nPlease enter blockstack configuration hints."

   # NOTE: disabled
   blockstack_opts, missing_blockstack_opts, num_blockstack_opts_prompted = blockstack_client.config.find_missing( blockstack_msg, \
                                                                                                                   blockstack_params, \
                                                                                                                   blockstack_opts, \
                                                                                                                   blockstack_opts_defaults, \
                                                                                                                   prompt_missing=False )

   bitcoind_message  = "Blockstack does not have enough information to connect\n"
   bitcoind_message += "to bitcoind.  Please supply the following parameters, or\n"
   bitcoind_message += "press [ENTER] to select the default value."

   bitcoind_opts = {}
   bitcoind_opts_defaults = blockstack_client.config.default_bitcoind_opts( config_file=config_file )
   bitcoind_params = bitcoind_opts_defaults.keys()

   if not force:

      # get default set of bitcoind opts
      bitcoind_opts = blockstack_client.config.default_bitcoind_opts( config_file=config_file )


   # get any missing bitcoind fields
   bitcoind_opts, missing_bitcoin_opts, num_bitcoind_prompted = blockstack_client.config.find_missing( bitcoind_message, \
                                                                                                       bitcoind_params, \
                                                                                                       bitcoind_opts, \
                                                                                                       bitcoind_opts_defaults, \
                                                                                                       prompt_missing=interactive )

   if not interactive and (len(missing_bitcoin_opts) > 0 or len(missing_blockstack_opts) > 0):
       # cannot continue
       raise Exception("Missing configuration fields: %s" % (",".join( missing_blockstack_opts + missing_bitcoin_opts )) )

   # ask for contact info, so we can send out notifications for bugfixes and upgrades
   if blockstack_opts.get('email', None) is None:
       email_msg = "Would you like to receive notifications\n"
       email_msg+= "from the developers when there are critical\n"
       email_msg+= "updates available to install?\n\n"
       email_msg+= "If so, please enter your email address here.\n"
       email_msg+= "If not, leave this field blank.\n\n"
       email_msg+= "Your email address will be used solely\n"
       email_msg+= "for this purpose.\n"
       email_opts, _, email_prompted = blockstack_client.config.find_missing( email_msg, ['email'], {}, {'email': ''}, prompt_missing=interactive )

       # merge with blockstack section
       num_blockstack_opts_prompted += 1
       blockstack_opts['email'] = email_opts['email']

   ret = {
      'blockstack': blockstack_opts,
      'bitcoind': bitcoind_opts
   }

   # if we prompted, then save
   if num_bitcoind_prompted > 0 or num_blockstack_opts_prompted > 0:
       print >> sys.stderr, "Saving configuration to %s" % config_file
   
       # always set version when writing
       config_opts = copy.deepcopy(ret)
       if not config_opts['blockstack'].has_key('server_version'):
           config_opts['blockstack']['server_version'] = VERSION

       # if the config file doesn't exist, then set the version 
       # in ret as well, since it's what's written
       if not os.path.exists(config_file):
           ret['blockstack']['server_version'] = VERSION

       blockstack_client.config.write_config_file( config_opts, config_file )

   # prefix our bitcoind options, so they work with virtualchain
   ret['bitcoind'] = blockstack_client.config.opt_restore("bitcoind_", ret['bitcoind'])
   return ret 
Esempio n. 29
0
def configure(config_file=None, force=False, interactive=True, testset=False):
    """
   Configure blockstore:  find and store configuration parameters to the config file.

   Optionally prompt for missing data interactively (with interactive=True).  Or, raise an exception
   if there are any fields missing.

   Optionally force a re-prompting for all configuration details (with force=True)

   Return (bitcoind_opts, utxo_opts)
   """

    global SUPPORTED_UTXO_PROVIDERS, SUPPORTED_UTXO_PARAMS, SUPPORTED_UTXO_PROMPT_MESSAGES

    if config_file is None:
        try:
            # get input for everything
            config_file = virtualchain.get_config_filename()
        except:
            raise

    if not os.path.exists(config_file):
        # definitely ask for everything
        force = True

    # get blockstore opts
    blockstore_opts = {}
    blockstore_opts_defaults = default_blockstore_opts(config_file=config_file,
                                                       testset=testset)
    blockstore_params = blockstore_opts_defaults.keys()

    if not force:

        # default blockstore options
        blockstore_opts = default_blockstore_opts(config_file=config_file,
                                                  testset=testset)

    blockstore_msg = "ADVANCED USERS ONLY.\nPlease enter blockstore configuration hints."

    # NOTE: disabled
    blockstore_opts, missing_blockstore_opts, num_blockstore_opts_prompted = find_missing(
        blockstore_msg,
        blockstore_params,
        blockstore_opts,
        blockstore_opts_defaults,
        prompt_missing=False)

    utxo_provider = None
    if 'utxo_provider' in blockstore_opts:
        utxo_provider = blockstore_opts['utxo_provider']
    else:
        utxo_provider = default_utxo_provider(config_file=config_file)

    bitcoind_message = "Blockstore does not have enough information to connect\n"
    bitcoind_message += "to bitcoind.  Please supply the following parameters, or\n"
    bitcoind_message += "press [ENTER] to select the default value."

    bitcoind_opts = {}
    bitcoind_opts_defaults = default_bitcoind_opts(config_file=config_file)
    bitcoind_params = bitcoind_opts_defaults.keys()

    if not force:

        # get default set of bitcoind opts
        bitcoind_opts = default_bitcoind_opts(config_file=config_file)

    # get any missing bitcoind fields
    bitcoind_opts, missing_bitcoin_opts, num_bitcoind_prompted = find_missing(
        bitcoind_message,
        bitcoind_params,
        bitcoind_opts,
        bitcoind_opts_defaults,
        prompt_missing=interactive,
        strip_prefix="bitcoind_")

    # find the current utxo provider
    while utxo_provider is None or utxo_provider not in SUPPORTED_UTXO_PROVIDERS:

        # prompt for it?
        if interactive or force:

            utxo_message = 'NOTE: Blockstore currently requires an external API\n'
            utxo_message += 'for querying unspent transaction outputs.  The set of\n'
            utxo_message += 'supported providers are:\n'
            utxo_message += "\t\n".join(SUPPORTED_UTXO_PROVIDERS) + "\n"
            utxo_message += "Please get the requisite API tokens and enter them here."

            utxo_provider_dict = interactive_prompt(utxo_message,
                                                    ['utxo_provider'], {})
            utxo_provider = utxo_provider_dict['utxo_provider']

        else:
            raise Exception("No UTXO provider given")

    utxo_opts = {}
    utxo_opts_defaults = default_utxo_provider_opts(utxo_provider,
                                                    config_file=config_file)
    utxo_params = SUPPORTED_UTXO_PARAMS[utxo_provider]

    if not force:

        # get current set of utxo opts
        utxo_opts = default_utxo_provider_opts(utxo_provider,
                                               config_file=config_file)

    utxo_opts, missing_utxo_opts, num_utxo_opts_prompted = find_missing(
        SUPPORTED_UTXO_PROMPT_MESSAGES[utxo_provider],
        utxo_params,
        utxo_opts,
        utxo_opts_defaults,
        prompt_missing=interactive)
    utxo_opts['utxo_provider'] = utxo_provider

    dht_opts = {}
    dht_opts_defaults = default_dht_opts(config_file=config_file)
    dht_params = dht_opts_defaults.keys()

    if not force:

        # default DHT options
        dht_opts = default_dht_opts(config_file=config_file)

    dht_msg = "Please enter your DHT node configuration.\nUnless you plan on leaving Blockstore\nrunning, you should disable the DHT feature."

    # NOTE: disabled
    dht_opts, missing_dht_opts, num_dht_opts_prompted = find_missing(
        dht_msg, dht_params, dht_opts, dht_opts_defaults, prompt_missing=False)

    if not interactive and (len(missing_bitcoin_opts) > 0
                            or len(missing_utxo_opts) > 0
                            or len(missing_dht_opts) > 0
                            or len(missing_blockstore_opts) > 0):

        # cannot continue
        raise Exception("Missing configuration fields: %s" %
                        (",".join(missing_bitcoin_opts + missing_utxo_opts)))

    # ask for contact info, so we can send out notifications for bugfixes and upgrades
    if blockstore_opts.get('email', None) is None:
        email_msg = "Would you like to receive notifications\n"
        email_msg += "from the developers when there are critical\n"
        email_msg += "updates available to install?\n\n"
        email_msg += "If so, please enter your email address here.\n"
        email_msg += "If not, leave this field blank.\n\n"
        email_msg += "Your email address will be used solely\n"
        email_msg += "for this purpose.\n"
        email_opts, _, email_prompted = find_missing(
            email_msg, ['email'], {}, {'email': ''},
            prompt_missing=interactive)

        # merge with blockstore section
        num_blockstore_opts_prompted += 1
        blockstore_opts['email'] = email_opts['email']

    # if we prompted, then save
    if num_bitcoind_prompted > 0 or num_utxo_opts_prompted > 0 or num_dht_opts_prompted > 0 or num_blockstore_opts_prompted > 0:
        print >> sys.stderr, "Saving configuration to %s" % config_file
        write_config_file(bitcoind_opts=bitcoind_opts,
                          utxo_opts=utxo_opts,
                          dht_opts=dht_opts,
                          blockstore_opts=blockstore_opts,
                          config_file=config_file)

    return (blockstore_opts, bitcoind_opts, utxo_opts, dht_opts)
def default_blockstack_opts( config_file=None, virtualchain_impl=None ):
   """
   Get our default blockstack opts from a config file
   or from sane defaults.
   """

   if config_file is None:
      config_file = virtualchain.get_config_filename()

   announce_path = get_announce_filename( virtualchain.get_working_dir(impl=virtualchain_impl) )

   parser = SafeConfigParser()
   parser.read( config_file )

   blockstack_opts = {}
   contact_email = None
   announcers = "judecn.id,muneeb.id,shea256.id"
   announcements = None
   backup_frequency = 144   # once a day; 10 minute block time
   backup_max_age = 1008    # one week
   rpc_port = RPC_SERVER_PORT 
   serve_zonefiles = True
   serve_profiles = False
   serve_data = False
   zonefile_dir = os.path.join( os.path.dirname(config_file), "zonefiles")
   analytics_key = None
   zonefile_storage_drivers = "disk,dht"
   zonefile_storage_drivers_write = "disk"
   profile_storage_drivers = "disk"
   profile_storage_drivers_write = "disk"
   data_storage_drivers = "disk"
   data_storage_drivers_write = "disk"
   redirect_data = False
   data_servers = None
   server_version = None
   atlas_enabled = True
   atlas_seed_peers = "node.blockstack.org:%s" % RPC_SERVER_PORT
   atlasdb_path = os.path.join( os.path.dirname(config_file), "atlas.db" )
   atlas_blacklist = ""
   atlas_hostname = socket.gethostname()

   if parser.has_section('blockstack'):

      if parser.has_option('blockstack', 'backup_frequency'):
         backup_frequency = int( parser.get('blockstack', 'backup_frequency'))

      if parser.has_option('blockstack', 'backup_max_age'):
         backup_max_age = int( parser.get('blockstack', 'backup_max_age') )

      if parser.has_option('blockstack', 'email'):
         contact_email = parser.get('blockstack', 'email')

      if parser.has_option('blockstack', 'rpc_port'):
         rpc_port = int(parser.get('blockstack', 'rpc_port'))

      if parser.has_option('blockstack', 'serve_zonefiles'):
          serve_zonefiles = parser.get('blockstack', 'serve_zonefiles')
          if serve_zonefiles.lower() in ['1', 'yes', 'true', 'on']:
              serve_zonefiles = True
          else:
              serve_zonefiles = False

      if parser.has_option('blockstack', 'serve_profiles'):
          serve_profiles = parser.get('blockstack', 'serve_profiles')
          if serve_profiles.lower() in ['1', 'yes', 'true', 'on']:
              serve_profiles = True
          else:
              serve_profiles = False

      if parser.has_option('blockstack', 'serve_data'):
          serve_data = parser.get('blockstack', 'serve_data')
          if serve_data.lower() in ['1', 'yes', 'true', 'on']:
              serve_data = True
          else:
              serve_data = False

      if parser.has_option("blockstack", "zonefile_storage_drivers"):
          zonefile_storage_drivers = parser.get("blockstack", "zonefile_storage_drivers")

      if parser.has_option("blockstack", "zonefile_storage_drivers_write"):
          zonefile_storage_drivers_write = parser.get("blockstack", "zonefile_storage_drivers_write")

      if parser.has_option("blockstack", "profile_storage_drivers"):
          profile_storage_drivers = parser.get("blockstack", "profile_storage_drivers")

      if parser.has_option("blockstack", "profile_storage_drivers_write"):
          profile_storage_drivers_write = parser.get("blockstack", "profile_storage_drivers_write")

      if parser.has_option("blockstack", "data_storage_drivers"):
          data_storage_drivers = parser.get("blockstack", "data_storage_drivers")

      if parser.has_option("blockstack", "data_storage_drivers_write"):
          data_storage_drivers_write = parser.get("blockstack", "data_storage_drivers_write")

      if parser.has_option("blockstack", "zonefiles"):
          zonefile_dir = parser.get("blockstack", "zonefiles")
    
      if parser.has_option('blockstack', 'redirect_data'):
          redirect_data = parser.get('blockstack', 'redirect_data')
          if redirect_data.lower() in ['1', 'yes', 'true', 'on']:
              redirect_data = True
          else:
              redirect_data = False

      if parser.has_option('blockstack', 'data_servers'):
          data_servers = parser.get('blockstack', 'data_servers')

          # must be a CSV of host:port
          hostports = filter( lambda x: len(x) > 0, data_servers.split(",") )
          for hp in hostports:
              host, port = url_to_host_port( hp )
              assert host is not None and port is not None


      if parser.has_option('blockstack', 'announcers'):
         # must be a CSV of blockchain IDs
         announcer_list_str = parser.get('blockstack', 'announcers')
         announcer_list = filter( lambda x: len(x) > 0, announcer_list_str.split(",") )

         import scripts

         # validate each one
         valid = True
         for bid in announcer_list:
             if not scripts.is_name_valid( bid ):
                 log.error("Invalid blockchain ID '%s'" % bid)
                 valid = False

         if valid:
             announcers = ",".join(announcer_list)

      if parser.has_option('blockstack', 'analytics_key'):
         analytics_key = parser.get('blockstack', 'analytics_key')

      if parser.has_option('blockstack', 'server_version'):
         server_version = parser.get('blockstack', 'server_version')

      if parser.has_option('blockstack', 'atlas'):
         atlas_enabled = parser.get('blockstack', 'atlas')
         if atlas_enabled.lower() in ['true', '1', 'enabled', 'enabled', 'on']:
            atlas_enabled = True
         else:
            atlas_enabled = False

      if parser.has_option('blockstack', 'atlas_seeds'):
         atlas_seed_peers = parser.get('blockstack', 'atlas_seeds')
         
         # must be a CSV of host:port
         hostports = filter( lambda x: len(x) > 0, atlas_seed_peers.split(",") )
         for hp in hostports:
             host, port = url_to_host_port( hp )
             assert host is not None and port is not None

      if parser.has_option('blockstack', 'atlasdb_path'):
         atlasdb_path = parser.get('blockstack', 'atlasdb_path')

      if parser.has_option('blockstack', 'atlas_blacklist'):
         atlas_blacklist = parser.get('blockstack', 'atlas_blacklist')

         # must be a CSV of host:port
         hostports = filter( lambda x: len(x) > 0, atlas_blacklist.split(",") )
         for hp in hostports:
             host, port = url_to_host_port( hp )
             assert host is not None and port is not None

      if parser.has_option('blockstack', 'atlas_hostname'):
         atlas_hostname = parser.get('blockstack', 'atlas_hostname')
        

   if os.path.exists( announce_path ):
       # load announcement list
       with open( announce_path, "r" ) as f:
           announce_text = f.readlines()

       all_announcements = [ a.strip() for a in announce_text ]
       unseen_announcements = []

       # find announcements we haven't seen yet
       for a in all_announcements:
           if a not in ANNOUNCEMENTS:
               unseen_announcements.append( a )

       announcements = ",".join( unseen_announcements )

   if zonefile_dir is not None and not os.path.exists( zonefile_dir ):
       try:
           os.makedirs( zonefile_dir, 0700 )
       except:
           pass

   blockstack_opts = {
       'rpc_port': rpc_port,
       'email': contact_email,
       'announcers': announcers,
       'announcements': announcements,
       'backup_frequency': backup_frequency,
       'backup_max_age': backup_max_age,
       'serve_zonefiles': serve_zonefiles,
       'zonefile_storage_drivers': zonefile_storage_drivers,
       "zonefile_storage_drivers_write": zonefile_storage_drivers_write,
       'serve_profiles': serve_profiles,
       'profile_storage_drivers': profile_storage_drivers,
       "profile_storage_drivers_write": profile_storage_drivers_write,
       'serve_data': serve_data,
       'data_storage_drivers': data_storage_drivers,
       "data_storage_drivers_write": data_storage_drivers_write,
       'redirect_data': redirect_data,
       'data_servers': data_servers,
       'analytics_key': analytics_key,
       'server_version': server_version,
       'atlas': atlas_enabled,
       'atlas_seeds': atlas_seed_peers,
       'atlasdb_path': atlasdb_path,
       'atlas_blacklist': atlas_blacklist,
       'atlas_hostname': atlas_hostname,
       'zonefiles': zonefile_dir,
   }

   # strip Nones
   for (k, v) in blockstack_opts.items():
      if v is None:
         del blockstack_opts[k]

   return blockstack_opts
Esempio n. 31
0
def default_blockstack_opts( config_file=None, testset=False ):
   """
   Get our default blockstack opts from a config file
   or from sane defaults.
   """

   if config_file is None:
      config_file = virtualchain.get_config_filename()

   testset_path = get_testset_filename( virtualchain.get_working_dir() )
   announce_path = get_announce_filename( virtualchain.get_working_dir() )

   parser = SafeConfigParser()
   parser.read( config_file )

   blockstack_opts = {}
   tx_broadcaster = None
   utxo_provider = None
   testset_first_block = None
   max_subsidy = 0
   contact_email = None
   announcers = "judecn.id,muneeb.id,shea256.id"
   announcements = None

   if parser.has_section('blockstack'):

      if parser.has_option('blockstack', 'tx_broadcaster'):
         tx_broadcaster = parser.get('blockstack', 'tx_broadcaster')

      if parser.has_option('blockstack', 'utxo_provider'):
         utxo_provider = parser.get('blockstack', 'utxo_provider')

      if parser.has_option('blockstack', 'testset_first_block'):
         testset_first_block = int( parser.get('blockstack', 'testset_first_block') )

      if parser.has_option('blockstack', 'max_subsidy'):
         max_subsidy = int( parser.get('blockstack', 'max_subsidy'))

      if parser.has_option('blockstack', 'email'):
         contact_email = parser.get('blockstack', 'email')

      if parser.has_option('blockstack', 'announcers'):
         # must be a CSV of blockchain IDs
         announcer_list_str = parser.get('blockstack', 'announcers')
         announcer_list = announcer_list_str.split(",")

         import scripts

         # validate each one
         valid = True
         for bid in announcer_list:
             if not scripts.is_name_valid( bid ):
                 log.error("Invalid blockchain ID '%s'" % bid)
                 valid = False

         if valid:
             announcers = ",".join(announcer_list)

   if os.path.exists( testset_path ):
       # testset file flag set
       testset = True

   if os.path.exists( announce_path ):
       # load announcement list
       with open( announce_path, "r" ) as f:
           announce_text = f.readlines()

       all_announcements = [ a.strip() for a in announce_text ]
       unseen_announcements = []

       # find announcements we haven't seen yet
       for a in all_announcements:
           if a not in ANNOUNCEMENTS:
               unseen_announcements.append( a )

       announcements = ",".join( unseen_announcements )

   blockstack_opts = {
       'tx_broadcaster': tx_broadcaster,
       'utxo_provider': utxo_provider,
       'testset': testset,
       'testset_first_block': testset_first_block,
       'max_subsidy': max_subsidy,
       'email': contact_email,
       'announcers': announcers,
       'announcements': announcements
   }

   # strip Nones
   for (k, v) in blockstack_opts.items():
      if v is None:
         del blockstack_opts[k]

   return blockstack_opts
Esempio n. 32
0
def default_bitcoind_utxo_opts( config_file=None ):
   """
   Get our default bitcoind UTXO options from a config file.
   """
   
   if config_file is None:
       config_file = virtualchain.get_config_filename()
       
   parser = SafeConfigParser()
   parser.read( config_file )
   
   bitcoind_utxo_opts = {}
   
   server = None 
   port = None 
   rpc_username = None 
   rpc_password = None 
   use_https = None 
   version_byte = None
   
   if parser.has_section("bitcoind_utxo"):
       
       if parser.has_option("bitcoind_utxo", "server"):
           server = parser.get("bitcoind_utxo", "server")
           
       if parser.has_option("bitcoind_utxo", "port"):
           port = int( parser.get("bitcoind_utxo", "port") )
                      
       if parser.has_option("bitcoind_utxo", "rpc_username"):
           rpc_username = parser.get("bitcoind_utxo", "rpc_username")
           
       if parser.has_option("bitcoind_utxo", "rpc_password"):
           rpc_password = parser.get("bitcoind_utxo", "rpc_password")
       
       if parser.has_option("bitcoind_utxo", "use_https"):
           use_https = bool( parser.get("bitcoind_utxo", "use_https") )
           
       if parser.has_option("bitcoind_utxo", "version_byte"):
           version_byte = int(parser.get("bitcoind_utxo", "version_byte"))
           
           
   if use_https is None:
       use_https = True 
   
   if version_byte is None:
       version_byte = 0 
       
   if server is None:
       server = '127.0.0.1'
   
   if port is None:
       port = 8332 
       
   bitcoind_utxo_opts = {
       "utxo_provider": "bitcoind_utxo",
       "rpc_username": rpc_username,
       "rpc_password": rpc_password,
       "server": server,
       "port": port,
       "use_https": use_https,
       "version_byte": version_byte
   }
   
   # strip Nones 
   for (k, v) in bitcoind_utxo_opts.items():
      if v is None:
         del bitcoind_utxo_opts[k]
   
   return bitcoind_utxo_opts
Esempio n. 33
0
def default_blockstore_opts(config_file=None, testset=False):
    """
   Get our default blockstore opts from a config file
   or from sane defaults.
   """

    if config_file is None:
        config_file = virtualchain.get_config_filename()

    testset_path = get_testset_filename(virtualchain.get_working_dir())
    announce_path = get_announce_filename(virtualchain.get_working_dir())

    parser = SafeConfigParser()
    parser.read(config_file)

    blockstore_opts = {}
    tx_broadcaster = None
    utxo_provider = None
    testset_first_block = None
    max_subsidy = 0
    contact_email = None
    announcers = "judecn.id,muneeb.id,shea256.id"
    announcements = None

    if parser.has_section('blockstore'):

        if parser.has_option('blockstore', 'tx_broadcaster'):
            tx_broadcaster = parser.get('blockstore', 'tx_broadcaster')

        if parser.has_option('blockstore', 'utxo_provider'):
            utxo_provider = parser.get('blockstore', 'utxo_provider')

        if parser.has_option('blockstore', 'testset_first_block'):
            testset_first_block = int(
                parser.get('blockstore', 'testset_first_block'))

        if parser.has_option('blockstore', 'max_subsidy'):
            max_subsidy = int(parser.get('blockstore', 'max_subsidy'))

        if parser.has_option('blockstore', 'email'):
            contact_email = parser.get('blockstore', 'email')

        if parser.has_option('blockstore', 'announcers'):
            # must be a CSV of blockchain IDs
            announcer_list_str = parser.get('blockstore', 'announcers')
            announcer_list = announcer_list_str.split(",")

            import scripts

            # validate each one
            valid = True
            for bid in announcer_list:
                if not scripts.is_name_valid(bid):
                    log.error("Invalid blockchain ID '%s'" % bid)
                    valid = False

            if valid:
                announcers = ",".join(announcer_list)

    if os.path.exists(testset_path):
        # testset file flag set
        testset = True

    if os.path.exists(announce_path):
        # load announcement list
        with open(announce_path, "r") as f:
            announce_text = f.readlines()

        all_announcements = [a.strip() for a in announce_text]
        unseen_announcements = []

        # find announcements we haven't seen yet
        for a in all_announcements:
            if a not in ANNOUNCEMENTS:
                unseen_announcements.append(a)

        announcements = ",".join(unseen_announcements)

    blockstore_opts = {
        'tx_broadcaster': tx_broadcaster,
        'utxo_provider': utxo_provider,
        'testset': testset,
        'testset_first_block': testset_first_block,
        'max_subsidy': max_subsidy,
        'email': contact_email,
        'announcers': announcers,
        'announcements': announcements
    }

    # strip Nones
    for (k, v) in blockstore_opts.items():
        if v is None:
            del blockstore_opts[k]

    return blockstore_opts
Esempio n. 34
0
def configure( config_file=None, force=False, interactive=True ):
   """
   Configure blockstore:  find and store configuration parameters to the config file.
   
   Optionally prompt for missing data interactively (with interactive=True).  Or, raise an exception
   if there are any fields missing.
   
   Optionally force a re-prompting for all configuration details (with force=True)
   
   Return (bitcoind_opts, utxo_opts)
   """
   
   global SUPPORTED_UTXO_PROVIDERS, SUPPORTED_UTXO_PARAMS, SUPPORTED_UTXO_PROMPT_MESSAGES
   
   if config_file is None:
      try:
         # get input for everything
         config_file = virtualchain.get_config_filename()
      except:
         pass 
   
   if not os.path.exists( config_file ):
       # definitely ask for everything
       force = True 
       
   # get blockstore opts 
   blockstore_opts = {}
   blockstore_opts_defaults = default_blockstore_opts( config_file=config_file )
   blockstore_params = blockstore_opts_defaults.keys()
   
   if not force:
       
       # default blockstore options 
       blockstore_opts = default_blockstore_opts( config_file=config_file )
       
   blockstore_msg = "ADVANCED USERS ONLY.\nPlease enter blockstore configuration hints."
   blockstore_opts, missing_blockstore_opts, num_blockstore_opts_prompted = find_missing( blockstore_msg, blockstore_params, blockstore_opts, blockstore_opts_defaults, prompt_missing=False )
   
   utxo_provider = None 
   if 'utxo_provider' in blockstore_opts:
       utxo_provider = blockstore_opts['utxo_provider']
   else:
       utxo_provider = default_utxo_provider( config_file=config_file )
   
   bitcoind_message  = "Blockstore does not have enough information to connect\n"
   bitcoind_message += "to bitcoind.  Please supply the following parameters, or"
   bitcoind_message += "press [ENTER] to select the default value."
   
   bitcoind_opts = {}
   bitcoind_opts_defaults = default_bitcoind_opts( config_file=config_file )
   bitcoind_params = bitcoind_opts_defaults.keys()
   
   if not force:
       
      # get default set of bitcoind opts
      bitcoind_opts = default_bitcoind_opts( config_file=config_file )
      
       
   # get any missing bitcoind fields 
   bitcoind_opts, missing_bitcoin_opts, num_bitcoind_prompted = find_missing( bitcoind_message, bitcoind_params, bitcoind_opts, bitcoind_opts_defaults, prompt_missing=interactive, strip_prefix="bitcoind_" )
   
   # find the current utxo provider 
   while utxo_provider is None or utxo_provider not in SUPPORTED_UTXO_PROVIDERS:
       
       # prompt for it? 
       if interactive or force:
                    
           utxo_message  = 'NOTE: Blockstore currently requires an external API\n'
           utxo_message += 'for querying unspent transaction outputs.  The set of\n'
           utxo_message += 'supported providers are:\n'
           utxo_message += "\t\n".join( SUPPORTED_UTXO_PROVIDERS ) + "\n"
           utxo_message += "Please get the requisite API tokens and enter them here."
           
           utxo_provider_dict = interactive_prompt( utxo_message, ['utxo_provider'], {} )
           utxo_provider = utxo_provider_dict['utxo_provider']
           
       else:
           raise Exception("No UTXO provider given")
       
   
   utxo_opts = {}
   utxo_opts_defaults = default_utxo_provider_opts( utxo_provider, config_file=config_file )
   utxo_params = SUPPORTED_UTXO_PARAMS[ utxo_provider ]
   
   if not force:
      
      # get current set of utxo opts 
      utxo_opts = default_utxo_provider_opts( utxo_provider, config_file=config_file )
      
   utxo_opts, missing_utxo_opts, num_utxo_opts_prompted = find_missing( SUPPORTED_UTXO_PROMPT_MESSAGES[utxo_provider], utxo_params, utxo_opts, utxo_opts_defaults, prompt_missing=interactive )
   utxo_opts['utxo_provider'] = utxo_provider 
   
   dht_opts = {}
   dht_opts_defaults = default_dht_opts( config_file=config_file )
   dht_params = dht_opts_defaults.keys()
   
   if not force:
       
       # default DHT options
       dht_opts = default_dht_opts( config_file=config_file )
       
   dht_msg = "Please enter your DHT node configuration.\nUnless you plan on leaving Blockstore\nrunning, you should disable the DHT feature."
   dht_opts, missing_dht_opts, num_dht_opts_prompted = find_missing( dht_msg, dht_params, dht_opts, dht_opts_defaults, prompt_missing=False )
   
   if not interactive and (len(missing_bitcoin_opts) > 0 or len(missing_utxo_opts) > 0 or len(missing_dht_opts) > 0 or len(missing_blockstore_opts) > 0):
       
       # cannot continue 
       raise Exception("Missing configuration fields: %s" % (",".join( missing_bitcoin_opts + missing_utxo_opts )) )
                       
   # if we prompted, then save 
   if num_bitcoind_prompted > 0 or num_utxo_opts_prompted > 0 or num_dht_opts_prompted > 0 or num_blockstore_opts_prompted > 0:
       print >> sys.stderr, "Saving configuration to %s" % config_file
       write_config_file( bitcoind_opts=bitcoind_opts, utxo_opts=utxo_opts, dht_opts=dht_opts, blockstore_opts=blockstore_opts, config_file=config_file )
       
   return (blockstore_opts, bitcoind_opts, utxo_opts, dht_opts)
Esempio n. 35
0
def configure( config_file=None, force=False, interactive=True, testset=False ):
   """
   Configure blockstack:  find and store configuration parameters to the config file.

   Optionally prompt for missing data interactively (with interactive=True).  Or, raise an exception
   if there are any fields missing.

   Optionally force a re-prompting for all configuration details (with force=True)

   Return (bitcoind_opts, utxo_opts)
   """

   global SUPPORTED_UTXO_PROVIDERS, SUPPORTED_UTXO_PARAMS, SUPPORTED_UTXO_PROMPT_MESSAGES

   if config_file is None:
      try:
         # get input for everything
         config_file = virtualchain.get_config_filename()
      except:
         raise

   if not os.path.exists( config_file ):
       # definitely ask for everything
       force = True

   # get blockstack opts
   blockstack_opts = {}
   blockstack_opts_defaults = default_blockstack_opts( config_file=config_file, testset=testset )
   blockstack_params = blockstack_opts_defaults.keys()

   if not force:

       # default blockstack options
       blockstack_opts = default_blockstack_opts( config_file=config_file, testset=testset )

   blockstack_msg = "ADVANCED USERS ONLY.\nPlease enter blockstack configuration hints."

   # NOTE: disabled
   blockstack_opts, missing_blockstack_opts, num_blockstack_opts_prompted = find_missing( blockstack_msg, blockstack_params, blockstack_opts, blockstack_opts_defaults, prompt_missing=False )

   utxo_provider = None
   if 'utxo_provider' in blockstack_opts:
       utxo_provider = blockstack_opts['utxo_provider']
   else:
       utxo_provider = default_utxo_provider( config_file=config_file )

   bitcoind_message  = "Blockstack does not have enough information to connect\n"
   bitcoind_message += "to bitcoind.  Please supply the following parameters, or\n"
   bitcoind_message += "press [ENTER] to select the default value."

   bitcoind_opts = {}
   bitcoind_opts_defaults = default_bitcoind_opts( config_file=config_file )
   bitcoind_params = bitcoind_opts_defaults.keys()

   if not force:

      # get default set of bitcoind opts
      bitcoind_opts = default_bitcoind_opts( config_file=config_file )


   # get any missing bitcoind fields
   bitcoind_opts, missing_bitcoin_opts, num_bitcoind_prompted = find_missing( bitcoind_message, bitcoind_params, bitcoind_opts, bitcoind_opts_defaults, prompt_missing=interactive, strip_prefix="bitcoind_" )

   # find the current utxo provider
   while utxo_provider is None or utxo_provider not in SUPPORTED_UTXO_PROVIDERS:

       # prompt for it?
       if interactive or force:

           utxo_message  = 'NOTE: Blockstack currently requires an external API\n'
           utxo_message += 'for querying unspent transaction outputs.  The set of\n'
           utxo_message += 'supported providers are:\n'
           utxo_message += "\t\n".join( SUPPORTED_UTXO_PROVIDERS ) + "\n"
           utxo_message += "Please get the requisite API tokens and enter them here."

           utxo_provider_dict = interactive_prompt( utxo_message, ['utxo_provider'], {} )
           utxo_provider = utxo_provider_dict['utxo_provider']

       else:
           raise Exception("No UTXO provider given")

   utxo_opts = {}
   utxo_opts_defaults = default_utxo_provider_opts( utxo_provider, config_file=config_file )
   utxo_params = SUPPORTED_UTXO_PARAMS[ utxo_provider ]

   if not force:

      # get current set of utxo opts
      utxo_opts = default_utxo_provider_opts( utxo_provider, config_file=config_file )

   utxo_opts, missing_utxo_opts, num_utxo_opts_prompted = find_missing( SUPPORTED_UTXO_PROMPT_MESSAGES[utxo_provider], utxo_params, utxo_opts, utxo_opts_defaults, prompt_missing=interactive )
   utxo_opts['utxo_provider'] = utxo_provider

   dht_opts = {}
   dht_opts_defaults = default_dht_opts( config_file=config_file )
   dht_params = dht_opts_defaults.keys()

   if not force:

       # default DHT options
       dht_opts = default_dht_opts( config_file=config_file )

   dht_msg = "Please enter your DHT node configuration.\nUnless you plan on leaving Blockstack\nrunning, you should disable the DHT feature."

   # NOTE: disabled
   dht_opts, missing_dht_opts, num_dht_opts_prompted = find_missing( dht_msg, dht_params, dht_opts, dht_opts_defaults, prompt_missing=False )

   if not interactive and (len(missing_bitcoin_opts) > 0 or len(missing_utxo_opts) > 0 or len(missing_dht_opts) > 0 or len(missing_blockstack_opts) > 0):

       # cannot continue
       raise Exception("Missing configuration fields: %s" % (",".join( missing_bitcoin_opts + missing_utxo_opts )) )

   # ask for contact info, so we can send out notifications for bugfixes and upgrades
   if blockstack_opts.get('email', None) is None:
       email_msg = "Would you like to receive notifications\n"
       email_msg+= "from the developers when there are critical\n"
       email_msg+= "updates available to install?\n\n"
       email_msg+= "If so, please enter your email address here.\n"
       email_msg+= "If not, leave this field blank.\n\n"
       email_msg+= "Your email address will be used solely\n"
       email_msg+= "for this purpose.\n"
       email_opts, _, email_prompted = find_missing( email_msg, ['email'], {}, {'email': ''}, prompt_missing=interactive )

       # merge with blockstack section
       num_blockstack_opts_prompted += 1
       blockstack_opts['email'] = email_opts['email']

   # if we prompted, then save
   if num_bitcoind_prompted > 0 or num_utxo_opts_prompted > 0 or num_dht_opts_prompted > 0 or num_blockstack_opts_prompted > 0:
       print >> sys.stderr, "Saving configuration to %s" % config_file
       write_config_file( bitcoind_opts=bitcoind_opts, utxo_opts=utxo_opts, dht_opts=dht_opts, blockstack_opts=blockstack_opts, config_file=config_file )

   return (blockstack_opts, bitcoind_opts, utxo_opts, dht_opts)
Esempio n. 36
0
def default_dht_opts( config_file=None ):
   """
   Get our default DHT options from the config file.
   """
   
   global DHT_SERVER_PORT, DEFAULT_DHT_SERVERS
   
   if config_file is None:
      config_file = virtualchain.get_config_filename()
   
   
   defaults = {
      'disable': str(True),
      'port': str(DHT_SERVER_PORT),
      'servers': ",".join( ["%s:%s" % (host, port) for (host, port) in DEFAULT_DHT_SERVERS] )
   }
   
   parser = SafeConfigParser( defaults )
   parser.read( config_file )
   
   if parser.has_section('dht'):
      
      disable = parser.get('dht', 'disable')
      port = parser.get('dht', 'port')
      servers = parser.get('dht', 'servers')     # expect comma-separated list of host:port
      
      if disable is None:
         disable = True 
         
      if port is None:
         port = DHT_SERVER_PORT
         
      if servers is None:
         servers = DEFAULT_DHT_SERVERS
         
      try:
         disable = bool(disable)
      except:
         raise Exception("Invalid field value for dht.disable: expected bool")
      
      try:
         port = int(port)
      except:
         raise Exception("Invalid field value for dht.port: expected int")
      
      parsed_servers = []
      try:
         server_list = servers.split(",")
         for server in server_list:
            server_host, server_port = server.split(":")
            server_port = int(server_port)
            
            parsed_servers.append( (server_host, server_port) )
            
      except:
         raise Exception("Invalid field value for dht.servers: expected 'HOST:PORT[,HOST:PORT...]'")
      
      dht_opts = {
         'disable': disable,
         'port': port,
         'servers': ",".join( ["%s:%s" % (host, port) for (host, port) in DEFAULT_DHT_SERVERS] )
      }
      
      return dht_opts 
   
   else:
      
      # use defaults
      dht_opts = {
         'disable': True,
         'port': DHT_SERVER_PORT,
         'servers': ",".join( ["%s:%s" % (host, port) for (host, port) in DEFAULT_DHT_SERVERS] )
      }
         
      return dht_opts
Esempio n. 37
0
def default_bitcoind_utxo_opts(config_file=None):
    """
   Get our default bitcoind UTXO options from a config file.
   """

    if config_file is None:
        config_file = virtualchain.get_config_filename()

    parser = SafeConfigParser()
    parser.read(config_file)

    bitcoind_utxo_opts = {}

    server = None
    port = None
    rpc_username = None
    rpc_password = None
    use_https = None
    version_byte = None

    if parser.has_section("bitcoind_utxo"):

        if parser.has_option("bitcoind_utxo", "server"):
            server = parser.get("bitcoind_utxo", "server")

        if parser.has_option("bitcoind_utxo", "port"):
            port = int(parser.get("bitcoind_utxo", "port"))

        if parser.has_option("bitcoind_utxo", "rpc_username"):
            rpc_username = parser.get("bitcoind_utxo", "rpc_username")

        if parser.has_option("bitcoind_utxo", "rpc_password"):
            rpc_password = parser.get("bitcoind_utxo", "rpc_password")

        if parser.has_option("bitcoind_utxo", "use_https"):

            if parser.get("bitcoind_utxo",
                          "use_https").lower() in ["y", "yes", "true"]:
                use_https = True
            else:
                use_https = False

        if parser.has_option("bitcoind_utxo", "version_byte"):
            version_byte = int(parser.get("bitcoind_utxo", "version_byte"))

    if use_https is None:
        use_https = True

    if version_byte is None:
        version_byte = 0

    if server is None:
        server = '127.0.0.1'

    if port is None:
        port = 8332

    bitcoind_utxo_opts = {
        "utxo_provider": "bitcoind_utxo",
        "rpc_username": rpc_username,
        "rpc_password": rpc_password,
        "server": server,
        "port": port,
        "use_https": use_https,
        "version_byte": version_byte
    }

    # strip Nones
    for (k, v) in bitcoind_utxo_opts.items():
        if v is None:
            del bitcoind_utxo_opts[k]

    return bitcoind_utxo_opts
Esempio n. 38
0
def write_config_file( blockstore_opts=None, bitcoind_opts=None, utxo_opts=None, dht_opts=None, config_file=None ):
   """
   Update a configuration file, given the bitcoind options and chain.com options.
   Return True on success 
   Return False on failure
   """
   
   print dht_opts 
   if config_file is None:
      try:
         config_file = virtualchain.get_config_filename()
      except:
         return False
      
   if config_file is None:
      return False 
   
   parser = SafeConfigParser()
   parser.read(config_file)
   
   if bitcoind_opts is not None and len(bitcoind_opts) > 0:
      
      tmp_bitcoind_opts = opt_strip( "bitcoind_", bitcoind_opts )
      
      if parser.has_section('bitcoind'):
          parser.remove_section('bitcoind')
          
      parser.add_section( 'bitcoind' )
      for opt_name, opt_value in tmp_bitcoind_opts.items():
         if opt_value is None:
             raise Exception("%s is not defined" % opt_name)
         parser.set( 'bitcoind', opt_name, "%s" % opt_value )
      
   if utxo_opts is not None and len(utxo_opts) > 0:
      
      if parser.has_section( utxo_opts['utxo_provider'] ):
          parser.remove_section( utxo_opts['utxo_provider'] )
          
      parser.add_section( utxo_opts['utxo_provider'] )
      for opt_name, opt_value in utxo_opts.items():
         
         # don't log this meta-field 
         if opt_name == 'utxo_provider':
             continue 
         
         if opt_value is None:
             raise Exception("%s is not defined" % opt_name)
         
         parser.set( utxo_opts['utxo_provider'], opt_name, "%s" % opt_value )
      
   if dht_opts is not None and len(dht_opts) > 0:
      
      if parser.has_section("dht"):
          parser.remove_section("dht")
      
      parser.add_section( "dht" )
      for opt_name, opt_value in dht_opts.items():
          
          if opt_value is None:
              raise Exception("%s is not defined" % opt_name )
          
          parser.set( "dht", opt_name, "%s" % opt_value )
       
   
   if blockstore_opts is not None and len(blockstore_opts) > 0:
      
      if parser.has_section("blockstore"):
          parser.remove_section("blockstore")
      
      parser.add_section( "blockstore" )
      for opt_name, opt_value in blockstore_opts.items():
          
          if opt_value is None:
              raise Exception("%s is not defined" % opt_name )
          
          parser.set( "blockstore", opt_name, "%s" % opt_value )
          
          
   with open(config_file, "w") as fout:
      os.fchmod( fout.fileno(), 0600 )
      parser.write( fout )
   
   return True
Esempio n. 39
0
def default_dht_opts(config_file=None):
    """
   Get our default DHT options from the config file.
   """

    global DHT_SERVER_PORT, DEFAULT_DHT_SERVERS

    if config_file is None:
        config_file = virtualchain.get_config_filename()

    defaults = {
        "disable": str(True),
        "port": str(DHT_SERVER_PORT),
        "servers": ",".join(["%s:%s" % (host, port) for (host, port) in DEFAULT_DHT_SERVERS]),
    }

    parser = SafeConfigParser(defaults)
    parser.read(config_file)

    if parser.has_section("dht"):

        disable = parser.get("dht", "disable")
        port = parser.get("dht", "port")
        servers = parser.get("dht", "servers")  # expect comma-separated list of host:port

        if disable is None:
            disable = True

        if port is None:
            port = DHT_SERVER_PORT

        if servers is None:
            servers = DEFAULT_DHT_SERVERS

        if disable.lower() in ["no", "n", "0", "false"]:
            disable = False
        else:
            disable = True

        try:
            port = int(port)
        except:
            raise Exception("Invalid field value for dht.port: expected int")

        parsed_servers = []
        try:
            server_list = servers.split(",")
            for server in server_list:
                server_host, server_port = server.split(":")
                server_port = int(server_port)

                parsed_servers.append((server_host, server_port))

        except:
            raise Exception("Invalid field value for dht.servers: expected 'HOST:PORT[,HOST:PORT...]'")

        dht_opts = {
            "disable": disable,
            "port": port,
            "servers": ",".join(["%s:%s" % (host, port) for (host, port) in DEFAULT_DHT_SERVERS]),
        }

        return dht_opts

    else:

        # use defaults
        dht_opts = {
            "disable": True,
            "port": DHT_SERVER_PORT,
            "servers": ",".join(["%s:%s" % (host, port) for (host, port) in DEFAULT_DHT_SERVERS]),
        }

        return dht_opts