extend the configuration section to include [blockstack-api]

This commit is contained in:
Jude Nelson
2018-03-22 19:23:11 -04:00
parent 60c24e5c04
commit 7be1628903

View File

@@ -39,6 +39,13 @@ VERSION = __version__
# namespace version bits
NAMESPACE_VERSION_PAY_TO_BURN = 0x1
NAMESPACE_VERSION_PAY_TO_CREATOR = 0x2
NAMESPACE_VERSION_PAY_WITH_STACKS = 0x3
NAMESPACE_VERSIONS_SUPPORTED = [
NAMESPACE_VERSION_PAY_TO_BURN,
NAMESPACE_VERSION_PAY_TO_CREATOR,
NAMESPACE_VERSION_PAY_WITH_STACKS,
]
""" constants
"""
@@ -66,23 +73,30 @@ FAST_SYNC_DEFAULT_URL = 'http://fast-sync.blockstack.org/snapshot.bsk'
""" name price configs
"""
NAME_COST_UNIT = 100 # minimum name cost in BTC is 100 satoshis, or about USD $0.00026 in September 2015 BTC
NAME_COST_UNIT_STACKS = 1733 # minimum name cost in STACKs is 1733 microSTACKs, or about $0.00026 with 1 STACK = USD $0.15
# BTC namespace costs (assumes ~USD $260/BTC)
# units in satoshis
SATOSHIS_PER_BTC = 10**8
PRICE_FOR_1LETTER_NAMES = 10*SATOSHIS_PER_BTC
PRICE_DROP_PER_LETTER = 10
PRICE_DROP_FOR_NON_ALPHABETIC = 10
ALPHABETIC_PRICE_FLOOR = 10**4
NAME_COST_UNIT = 100 # 100 satoshis
NAMESPACE_1_CHAR_COST = 400.0 * SATOSHIS_PER_BTC # ~$96,000
NAMESPACE_23_CHAR_COST = 40.0 * SATOSHIS_PER_BTC # ~$9,600
NAMESPACE_4567_CHAR_COST = 4.0 * SATOSHIS_PER_BTC # ~$960
NAMESPACE_8UP_CHAR_COST = 0.4 * SATOSHIS_PER_BTC # ~$96
NAMESPACE_8UP_CHAR_COST = 0.4 * SATOSHIS_PER_BTC # ~$96
# STACKS namespace costs
# units in microSTACKs
STACKS_PRICE = 0.15 # USD $0.15
STACKS_PER_MICROSTACKS = 10**-6
MICROSTACKS_PER_STACKS = 10**6
NAMESPACE_1_CHAR_COST_STACKS = int((96000.0 * MICROSTACKS_PER_STACKS) / STACKS_PRICE)
NAMESPACE_23_CHAR_COST_STACKS = int((9600.0 * MICROSTACKS_PER_STACKS) / STACKS_PRICE)
NAMESPACE_4567_CHAR_COST_STACKS = int((960.0 * MICROSTACKS_PER_STACKS) / STACKS_PRICE)
NAMESPACE_8UP_CHAR_COST_STACKS = int((96.0 * MICROSTACKS_PER_STACKS) / STACKS_PRICE)
NAMESPACE_PREORDER_EXPIRE = BLOCKS_PER_DAY # namespace preorders expire after 1 day, if not revealed
NAMESPACE_REVEAL_EXPIRE = BLOCKS_PER_YEAR # namespace reveals expire after 1 year, if not readied.
""" blockstack configs
"""
BLOCKSTACK_TEST = os.environ.get('BLOCKSTACK_TEST', None)
@@ -95,6 +109,18 @@ BLOCKSTACK_TESTNET_FIRST_BLOCK = os.environ.get("BLOCKSTACK_TESTNET_FIRST_BLOCK"
BLOCKSTACK_DRY_RUN = os.environ.get('BLOCKSTACK_DRY_RUN', None)
BLOCKSTACK_TEST_SUBDOMAINS_FIRST_BLOCK = os.environ.get('BLOCKSTACK_TEST_SUBDOMAINS_FIRST_BLOCK', None)
if BLOCKSTACK_TEST:
# test environment can override these deadlines
if os.environ.get('BLOCKSTACK_TEST_NAMESPACE_PREORDER_EXPIRE'):
NAMESPACE_PREORDER_EXPIRE = int(os.environ['BLOCKSTACK_TEST_NAMESPACE_PREORDER_EXPIRE'])
if os.environ.get('BLOCKSTACK_TEST_NAMESPACE_REVEAL_EXPIRE'):
NAMESPACE_REVEAL_EXPIRE = int(os.environ['BLOCKSTACK_TEST_NAMESPACE_REVEAL_EXPIRE'])
if os.environ.get("BLOCKSTACK_TEST_NAME_PREORDER_EXPIRE"):
NAME_PREORDER_EXPIRE = int(os.environ['BLOCKSTACK_TEST_NAME_PREORDER_EXPIRE'])
MAX_NAMES_PER_SENDER = 25 # a single sender script can own up to this many names
if BLOCKSTACK_TEST is not None:
@@ -137,6 +163,11 @@ if BLOCKSTACK_TEST is not None:
else:
RPC_SERVER_PORT = 6264
DEFAULT_API_HOST = 'localhost'
DEFAULT_API_PORT = 6270 # API endpoint port
if BLOCKSTACK_TEST:
DEFAULT_API_PORT = 16268
RPC_DEFAULT_TIMEOUT = 30 # in secs
RPC_MAX_ZONEFILE_LEN = 40960 # 40KB
RPC_MAX_INDEXING_DELAY = 2 * 3600 # 2 hours; maximum amount of time before the absence of new blocks causes the node to stop responding
@@ -176,6 +207,23 @@ GENESIS_SNAPSHOT = {
str(FIRST_BLOCK_MAINNET-1): "17ac43c1d8549c3181b200f1bf97eb7d",
}
GENESIS_BLOCK = [] # TODO
# when testing, you can pass in a genesis block as a JSON string or as a file
if BLOCKSTACK_TEST:
if os.environ.get("BLOCKSTACK_TEST_GENESIS_BLOCK") is not None:
try:
GENESIS_BLOCK = json.loads(os.environ['BLOCKSTACK_TEST_GENESIS_BLOCK'])
except:
GENESIS_BLOCK = []
if os.environ.get("BLOCKSTACK_TEST_GENESIS_BLOCK_FILE") is not None:
if os.path.exists(os.environ['BLOCKSTACK_TEST_GENESIS_BLOCK_FILE']):
try:
GENESIS_BLOCK = json.loads(open(os.environ['BLOCKSTACK_TEST_GENESIS_BLOCK_FILE']).read())
except:
GENESIS_BLOCK = []
"""
Epoch constants govern externally-adjusted behaviors over different time intervals.
Specifically:
@@ -201,37 +249,63 @@ EPOCH_FEATURE_SEGWIT = "BLOCKSTACK_SEGWIT"
EPOCH_FEATURE_OP_REGISTER_UPDATE = "BLOCKSTACK_OP_REGISTER_UPDATE"
EPOCH_FEATURE_OP_RENEW_TRANSFER_UPDATE = "BLOCKSTACK_OP_RENEW_TRANSFER_UPDATE"
EPOCH_FEATURE_NAMESPACE_BURN_TO_CREATOR = "BLOCKSTACK_NAMESPACE_BURN_TO_CREATOR"
EPOCH_FEATURE_NAMESPACE_PAY_WITH_STACKS = "BLOCKSTACK_NAMESPACE_PAY_WITH_STACKS"
EPOCH_FEATURE_STACKS_BUY_NAMESPACES = "BLOCKSTACK_STACKS_BUY_NAMESPACES"
EPOCH_FEATURE_NAMEOPS_COST_TOKENS = "BLOCKSTACK_NAMEOPS_COST_TOKENS"
EPOCH_FEATURE_FIX_PREORDER_EXPIRE = "BLOCKSTACK_PREORDER_EXPIRE"
EPOCH_FEATURE_FIX_RENEWAL_CONSENSUS_HASH = "BLOCKSTACK_RENEWAL_CONSENSUS_HASH"
EPOCH_FEATURE_FIX_REGISTER_CONSENSUS_HASH = "BLOCKSTACK_REGISTER_CONSENSUS_HASH"
# when epochs end (-1 means "never")
EPOCH_NOW = -1
EPOCH_1_END_BLOCK = 436650 # F-Day 2016
EPOCH_2_END_BLOCK = 488500 # F-day 2017
EPOCH_3_END_BLOCK = 541843 # F-day 2018 (TODO)
EPOCH_3_END_BLOCK = 541843 # F-day 2018 (TODO: this is the beginning of STACKs Phase 1)
EPOCH_4_END_BLOCK = EPOCH_NOW # end of STACKS Phase 1; beginning of STACKs Phase 2
EPOCH_1_NAMESPACE_LIFETIME_MULTIPLIER_id = 1
EPOCH_2_NAMESPACE_LIFETIME_MULTIPLIER_id = 2
EPOCH_3_NAMESPACE_LIFETIME_MULTIPLIER_id = 2
EPOCH_4_NAMESPACE_LIFETIME_MULTIPLIER_id = 2
EPOCH_1_NAMESPACE_LIFETIME_GRACE_PERIOD_id = 0
EPOCH_2_NAMESPACE_LIFETIME_GRACE_PERIOD_id = 0
EPOCH_3_NAMESPACE_LIFETIME_GRACE_PERIOD_id = 5000 # about 30 days
EPOCH_4_NAMESPACE_LIFETIME_GRACE_PERIOD_id = 5000 # about 30 days
EPOCH_1_PRICE_MULTIPLIER_id = 1.0
EPOCH_2_PRICE_MULTIPLIER_id = 1.0
EPOCH_3_PRICE_MULTIPLIER_id = 0.1
EPOCH_4_PRICE_MULTIPLIER_id = 0.1
EPOCH_1_PRICE_MULTIPLIER_STACKS = 1.0
EPOCH_2_PRICE_MULTIPLIER_STACKS = 1.0
EPOCH_3_PRICE_MULTIPLIER_STACKS = 1.0
EPOCH_4_PRICE_MULTIPLIER_STACKS = 1.0
EPOCH_1_NAMESPACE_RECEIVE_FEES_PERIOD_id = 0
EPOCH_2_NAMESPACE_RECEIVE_FEES_PERIOD_id = 0
EPOCH_3_NAMESPACE_RECEIVE_FEES_PERIOD_id = BLOCKS_PER_YEAR
EPOCH_4_NAMESPACE_RECEIVE_FEES_PERIOD_id = BLOCKS_PER_YEAR
EPOCH_1_FEATURES = []
EPOCH_2_FEATURES = [EPOCH_FEATURE_MULTISIG]
EPOCH_3_FEATURES = [EPOCH_FEATURE_MULTISIG, EPOCH_FEATURE_SEGWIT, EPOCH_FEATURE_OP_REGISTER_UPDATE, EPOCH_FEATURE_OP_RENEW_TRANSFER_UPDATE, EPOCH_FEATURE_NAMESPACE_BURN_TO_CREATOR]
EPOCH_4_FEATURES = [
EPOCH_FEATURE_MULTISIG,
EPOCH_FEATURE_SEGWIT,
EPOCH_FEATURE_OP_REGISTER_UPDATE,
EPOCH_FEATURE_OP_RENEW_TRANSFER_UPDATE,
EPOCH_FEATURE_NAMESPACE_BURN_TO_CREATOR,
EPOCH_FEATURE_NAMESPACE_PAY_WITH_STACKS,
EPOCH_FEATURE_STACKS_BUY_NAMESPACES,
EPOCH_FEATURE_FIX_PREORDER_EXPIRE,
EPOCH_FEATURE_FIX_RENEWAL_CONSENSUS_HASH,
EPOCH_FEATURE_FIX_REGISTER_CONSENSUS_HASH,
EPOCH_FEATURE_NAMEOPS_COST_TOKENS,
]
# minimum block height at which this server can run
EPOCH_MINIMUM = EPOCH_1_END_BLOCK + 1
NUM_EPOCHS = 3
NUM_EPOCHS = 4
for i in xrange(1, NUM_EPOCHS+1):
# epoch lengths can be altered by the test framework, for ease of tests
if os.environ.get("BLOCKSTACK_EPOCH_%s_END_BLOCK" % i, None) is not None and BLOCKSTACK_TEST:
@@ -268,12 +342,14 @@ EPOCHS = [
"NAMESPACE_LIFETIME_MULTIPLIER": EPOCH_1_NAMESPACE_LIFETIME_MULTIPLIER_id,
"NAMESPACE_LIFETIME_GRACE_PERIOD": EPOCH_1_NAMESPACE_LIFETIME_GRACE_PERIOD_id,
"PRICE_MULTIPLIER": EPOCH_1_PRICE_MULTIPLIER_id,
"PRICE_MULTIPLIER_STACKS": EPOCH_1_PRICE_MULTIPLIER_STACKS,
"NAMESPACE_RECEIVE_FEES_PERIOD": EPOCH_1_NAMESPACE_RECEIVE_FEES_PERIOD_id,
},
"*": {
"NAMESPACE_LIFETIME_MULTIPLIER": EPOCH_1_NAMESPACE_LIFETIME_MULTIPLIER_id,
"NAMESPACE_LIFETIME_GRACE_PERIOD": EPOCH_1_NAMESPACE_LIFETIME_GRACE_PERIOD_id,
"PRICE_MULTIPLIER": EPOCH_1_PRICE_MULTIPLIER_id,
"PRICE_MULTIPLIER_STACKS": EPOCH_1_PRICE_MULTIPLIER_STACKS,
"NAMESPACE_RECEIVE_FEES_PERIOD": EPOCH_1_NAMESPACE_RECEIVE_FEES_PERIOD_id,
},
},
@@ -299,6 +375,8 @@ EPOCHS = [
NAMESPACE_8UP_CHAR_COST, # 18-character cost
NAMESPACE_8UP_CHAR_COST, # 19-character cost
],
"namespace_prices_stacks": None,
"namespace_price_units": "BTC",
"features": EPOCH_1_FEATURES
},
{
@@ -309,12 +387,14 @@ EPOCHS = [
"NAMESPACE_LIFETIME_MULTIPLIER": EPOCH_2_NAMESPACE_LIFETIME_MULTIPLIER_id,
"NAMESPACE_LIFETIME_GRACE_PERIOD": EPOCH_2_NAMESPACE_LIFETIME_GRACE_PERIOD_id,
"PRICE_MULTIPLIER": EPOCH_2_PRICE_MULTIPLIER_id,
"PRICE_MULTIPLIER_STACKS": EPOCH_2_PRICE_MULTIPLIER_STACKS,
"NAMESPACE_RECEIVE_FEES_PERIOD": EPOCH_2_NAMESPACE_RECEIVE_FEES_PERIOD_id,
},
"*": {
"NAMESPACE_LIFETIME_MULTIPLIER": EPOCH_2_NAMESPACE_LIFETIME_MULTIPLIER_id,
"NAMESPACE_LIFETIME_GRACE_PERIOD": EPOCH_2_NAMESPACE_LIFETIME_GRACE_PERIOD_id,
"PRICE_MULTIPLIER": EPOCH_2_PRICE_MULTIPLIER_id,
"PRICE_MULTIPLIER_STACKS": EPOCH_2_PRICE_MULTIPLIER_STACKS,
"NAMESPACE_RECEIVE_FEES_PERIOD": EPOCH_2_NAMESPACE_RECEIVE_FEES_PERIOD_id,
},
},
@@ -340,6 +420,8 @@ EPOCHS = [
NAMESPACE_8UP_CHAR_COST, # 18-character cost
NAMESPACE_8UP_CHAR_COST, # 19-character cost
],
"namespace_prices_stacks": None,
"namespace_price_units": "BTC",
"features": EPOCH_2_FEATURES,
},
{
@@ -350,12 +432,14 @@ EPOCHS = [
"NAMESPACE_LIFETIME_MULTIPLIER": EPOCH_3_NAMESPACE_LIFETIME_MULTIPLIER_id,
"NAMESPACE_LIFETIME_GRACE_PERIOD": EPOCH_3_NAMESPACE_LIFETIME_GRACE_PERIOD_id,
"PRICE_MULTIPLIER": EPOCH_3_PRICE_MULTIPLIER_id,
"PRICE_MULTIPLIER_STACKS": EPOCH_3_PRICE_MULTIPLIER_STACKS,
"NAMESPACE_RECEIVE_FEES_PERIOD": EPOCH_3_NAMESPACE_RECEIVE_FEES_PERIOD_id,
},
"*": {
"NAMESPACE_LIFETIME_MULTIPLIER": EPOCH_3_NAMESPACE_LIFETIME_MULTIPLIER_id,
"NAMESPACE_LIFETIME_GRACE_PERIOD": EPOCH_3_NAMESPACE_LIFETIME_GRACE_PERIOD_id,
"PRICE_MULTIPLIER": EPOCH_3_PRICE_MULTIPLIER_id,
"PRICE_MULTIPLIER_STACKS": EPOCH_3_PRICE_MULTIPLIER_STACKS,
"NAMESPACE_RECEIVE_FEES_PERIOD": EPOCH_3_NAMESPACE_RECEIVE_FEES_PERIOD_id,
},
},
@@ -381,8 +465,55 @@ EPOCHS = [
NAMESPACE_8UP_CHAR_COST / 10, # 18-character cost
NAMESPACE_8UP_CHAR_COST / 10, # 19-character cost
],
"namespace_prices_stacks": None,
"namespace_price_units": "BTC",
"features": EPOCH_3_FEATURES,
},
{
# epoch 4
"end_block": EPOCH_4_END_BLOCK,
"namespaces": {
"id": {
"NAMESPACE_LIFETIME_MULTIPLIER": EPOCH_4_NAMESPACE_LIFETIME_MULTIPLIER_id,
"NAMESPACE_LIFETIME_GRACE_PERIOD": EPOCH_4_NAMESPACE_LIFETIME_GRACE_PERIOD_id,
"PRICE_MULTIPLIER": EPOCH_4_PRICE_MULTIPLIER_id,
"PRICE_MULTIPLIER_STACKS": EPOCH_4_PRICE_MULTIPLIER_STACKS,
"NAMESPACE_RECEIVE_FEES_PERIOD": EPOCH_4_NAMESPACE_RECEIVE_FEES_PERIOD_id,
},
"*": {
"NAMESPACE_LIFETIME_MULTIPLIER": EPOCH_4_NAMESPACE_LIFETIME_MULTIPLIER_id,
"NAMESPACE_LIFETIME_GRACE_PERIOD": EPOCH_4_NAMESPACE_LIFETIME_GRACE_PERIOD_id,
"PRICE_MULTIPLIER": EPOCH_4_PRICE_MULTIPLIER_id,
"PRICE_MULTIPLIER_STACKS": EPOCH_4_PRICE_MULTIPLIER_STACKS,
"NAMESPACE_RECEIVE_FEES_PERIOD": EPOCH_4_NAMESPACE_RECEIVE_FEES_PERIOD_id,
},
},
"namespace_prices": None,
"namespace_prices_stacks": [
None,
NAMESPACE_1_CHAR_COST_STACKS,
NAMESPACE_23_CHAR_COST_STACKS,
NAMESPACE_23_CHAR_COST_STACKS,
NAMESPACE_4567_CHAR_COST_STACKS,
NAMESPACE_4567_CHAR_COST_STACKS,
NAMESPACE_4567_CHAR_COST_STACKS,
NAMESPACE_4567_CHAR_COST_STACKS,
NAMESPACE_8UP_CHAR_COST_STACKS,
NAMESPACE_8UP_CHAR_COST_STACKS,
NAMESPACE_8UP_CHAR_COST_STACKS,
NAMESPACE_8UP_CHAR_COST_STACKS,
NAMESPACE_8UP_CHAR_COST_STACKS,
NAMESPACE_8UP_CHAR_COST_STACKS,
NAMESPACE_8UP_CHAR_COST_STACKS,
NAMESPACE_8UP_CHAR_COST_STACKS,
NAMESPACE_8UP_CHAR_COST_STACKS,
NAMESPACE_8UP_CHAR_COST_STACKS,
NAMESPACE_8UP_CHAR_COST_STACKS,
NAMESPACE_8UP_CHAR_COST_STACKS,
],
"namespace_price_units": "STACKS",
"features": EPOCH_4_FEATURES,
},
]
# if we're testing, then add the same rules for the 'test' namespace
@@ -512,7 +643,8 @@ LENGTHS = {
'blockchain_id_namespace_id': 19,
'namespace_id': 19, # same as above
'announce': 20,
'max_op_length': 80
'max_op_length': 80,
'tokens_burnt': 8,
}
MIN_OP_LENGTHS = {
@@ -653,8 +785,12 @@ if BLOCKSTACK_TESTNET:
SUBDOMAIN_ADDRESS_VERSION_BYTES = [SUBDOMAIN_ADDRESS_VERSION_BYTE, SUBDOMAIN_ADDRESS_MULTISIG_VERSION_BYTE]
# built-in token types
TOKEN_TYPE_STACKS = "STACKS"
# global mutable state
blockstack_opts = None
blockstack_api_opts = None
bitcoin_opts = None
running = False
@@ -713,15 +849,18 @@ def get_epoch_namespace_lifetime_grace_period( block_height, namespace_id ):
return epoch_config['namespaces']['*']['NAMESPACE_LIFETIME_GRACE_PERIOD']
def get_epoch_price_multiplier( block_height, namespace_id ):
def get_epoch_price_multiplier( block_height, namespace_id, units ):
"""
what's the name price multiplier for this epoch?
"""
assert units in ['STACKS', 'BTC'], 'Unknown units {}'.format(units)
multiplier = 'PRICE_MULTIPLIER' if units == 'BTC' else 'PRICE_MULTIPLIER_STACKS'
epoch_config = get_epoch_config( block_height )
if epoch_config['namespaces'].has_key(namespace_id):
return epoch_config['namespaces'][namespace_id]['PRICE_MULTIPLIER']
return epoch_config['namespaces'][namespace_id][multiplier]
else:
return epoch_config['namespaces']['*']['PRICE_MULTIPLIER']
return epoch_config['namespaces']['*'][multiplier]
def get_epoch_namespace_receive_fees_period( block_height, namespace_id ):
@@ -735,12 +874,26 @@ def get_epoch_namespace_receive_fees_period( block_height, namespace_id ):
return epoch_config['namespaces']['*']['NAMESPACE_RECEIVE_FEES_PERIOD']
def get_epoch_namespace_prices( block_height ):
def get_epoch_namespace_prices( block_height, units ):
"""
get the list of namespace prices by block height
"""
assert units in ['BTC', 'STACKS'], 'Invalid unit {}'.format(units)
epoch_config = get_epoch_config( block_height )
return epoch_config['namespace_prices']
if units == 'BTC':
return epoch_config['namespace_prices']
else:
return epoch_config['namespace_prices_stacks']
def get_epoch_namespace_price_units(block_height):
"""
Get the units to use to pay for namespaces in this epoch
"""
epoch_config = get_epoch_config(block_height)
return epoch_config['namespace_price_units']
def get_epoch_features( block_height ):
@@ -823,7 +976,6 @@ def get_bitcoin_opts():
"""
Get the bitcoind connection arguments.
"""
global bitcoin_opts
return bitcoin_opts
@@ -836,6 +988,14 @@ def get_blockstack_opts():
return blockstack_opts
def get_blockstack_api_opts():
"""
Get the blockstack RESTful API configuration options
"""
global blockstack_api_opts
return blockstack_api_opts
def set_bitcoin_opts( new_bitcoin_opts ):
"""
Set new global bitcoind operations
@@ -852,6 +1012,14 @@ def set_blockstack_opts( new_opts ):
blockstack_opts = new_opts
def set_blockstack_api_opts( new_opts ):
"""
Set new RESTful API opts
"""
global blockstack_api_opts
blockstack_api_opts = new_opts
def get_indexing_lockfile(working_dir):
"""
Return path to the indexing lockfile
@@ -1073,8 +1241,11 @@ def default_blockstack_opts( working_dir, config_file=None ):
atlas_hostname = RPC_SERVER_IP
atlas_port = RPC_SERVER_PORT
subdomaindb_path = os.path.join( os.path.dirname(config_file), "subdomains.db" )
run_indexer = True
if parser.has_section('blockstack'):
if parser.has_option('blockstack', 'enabled'):
run_indexer = parser.get('blockstack', 'enabled').lower() in ['1', 'true', 'on']
if parser.has_option('blockstack', 'backup_frequency'):
backup_frequency = int( parser.get('blockstack', 'backup_frequency'))
@@ -1187,6 +1358,7 @@ def default_blockstack_opts( working_dir, config_file=None ):
'atlas_port': atlas_port,
'zonefiles': zonefile_dir,
'subdomaindb_path': subdomaindb_path,
'enabled': run_indexer
}
# strip Nones
@@ -1197,6 +1369,63 @@ def default_blockstack_opts( working_dir, config_file=None ):
return blockstack_opts
def default_blockstack_api_opts(working_dir, config_file=None):
"""
Get our default blockstack RESTful API opts from a config file,
or from sane defaults.
"""
from .util import url_to_host_port, url_protocol
if config_file is None:
config_file = virtualchain.get_config_filename(get_default_virtualchain_impl(), working_dir)
parser = SafeConfigParser()
parser.read(config_file)
blockstack_api_opts = {}
indexer_url = None
api_port = DEFAULT_API_PORT
api_host = DEFAULT_API_HOST
run_api = True
if parser.has_section('blockstack-api'):
if parser.has_option('blockstack-api', 'enabled'):
run_api = parser.get('blockstack-api', 'enabled').lower() in ['true', '1', 'on']
if parser.has_option('blockstack-api', 'api_port'):
api_port = int(parser.get('blockstack-api', 'api_port'))
if parser.has_option('blockstack-api', 'api_host'):
api_host = parser.get('blockstack-api', 'api_host')
if parser.has_option('blockstack-api', 'indexer_url'):
indexer_host, indexer_port = url_to_host_port(parser.get('blockstack-api', 'indexer_url'))
indexer_protocol = url_protocol(parser.get('blockstack-api', 'indexer_url'))
if indexer_protocol is None:
indexer_protocol = 'http'
indexer_url = parser.get('blockstack-api', 'indexer_url')
if indexer_url is None:
# try defaults
indexer_url = 'http://localhost:{}'.format(RPC_SERVER_PORT)
blockstack_api_opts = {
'indexer_url': indexer_url,
'api_host': api_host,
'api_port': api_port,
'enabled': run_api
}
# strip Nones
for (k, v) in blockstack_api_opts.items():
if v is None:
del blockstack_api_opts[k]
return blockstack_api_opts
def interactive_prompt(message, parameters, default_opts):
"""
Prompt the user for a series of parameters
@@ -1321,7 +1550,7 @@ def configure( working_dir, config_file=None, force=False, interactive=True ):
Optionally force a re-prompting for all configuration details (with force=True)
Return {'blockstack': {...}, 'bitcoind': {...}}
Return {'blockstack': {...}, 'bitcoind': {...}, 'blockstack-api': {...}}
"""
if config_file is None:
@@ -1343,19 +1572,35 @@ def configure( working_dir, config_file=None, force=False, interactive=True ):
blockstack_params = blockstack_opts_defaults.keys()
if not force:
# default blockstack options
blockstack_opts = default_blockstack_opts(working_dir, config_file=config_file )
blockstack_msg = "ADVANCED USERS ONLY.\nPlease enter blockstack configuration hints."
# NOTE: disabled
# NOTE: interactive prompt disabled
blockstack_opts, missing_blockstack_opts, num_blockstack_opts_prompted = find_missing( blockstack_msg, \
blockstack_params, \
blockstack_opts, \
blockstack_opts_defaults, \
prompt_missing=False )
blockstack_api_opts = {}
blockstack_api_defaults = default_blockstack_api_opts(working_dir, config_file=config_file)
blockstack_api_params = blockstack_api_defaults.keys()
if not force:
# default blockstack API options
blockstack_api_opts = default_blockstack_api_opts(working_dir, config_file=config_file)
blockstack_api_msg = "ADVANCED USERS ONLY.\nPlease enter blockstack RESTful API configuration hints."
# NOTE: interactive prompt disabled
blockstack_api_opts, missing_blockstack_api_opts, num_blockstack_api_opts_prompted = find_missing( blockstack_api_msg, \
blockstack_api_params, \
blockstack_api_opts, \
blockstack_api_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."
@@ -1377,17 +1622,18 @@ def configure( working_dir, config_file=None, force=False, interactive=True ):
bitcoind_opts_defaults, \
prompt_missing=interactive )
if not interactive and (len(missing_bitcoin_opts) > 0 or len(missing_blockstack_opts) > 0):
if not interactive and (len(missing_bitcoin_opts) > 0 or len(missing_blockstack_opts) > 0 or len(missing_blockstack_api_opts) > 0):
# cannot continue
raise Exception("Missing configuration fields: %s" % (",".join( missing_blockstack_opts + missing_bitcoin_opts )) )
raise Exception("Missing configuration fields: %s" % (",".join( missing_blockstack_opts + missing_bitcoin_opts + missing_blockstack_api_opts )) )
ret = {
'blockstack': blockstack_opts,
'bitcoind': bitcoind_opts
'bitcoind': bitcoind_opts,
'blockstack-api': blockstack_api_opts
}
# if we prompted, then save
if num_bitcoind_prompted > 0 or num_blockstack_opts_prompted > 0:
if num_bitcoind_prompted > 0 or num_blockstack_opts_prompted > 0 or num_blockstack_api_opts_prompted:
print >> sys.stderr, "Saving configuration to %s" % config_file
# always set version when writing
@@ -1395,10 +1641,14 @@ def configure( working_dir, config_file=None, force=False, interactive=True ):
if not config_opts['blockstack'].has_key('server_version'):
config_opts['blockstack']['server_version'] = VERSION
if not config_opts['blockstack-api'].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
ret['blockstack-api']['server_version'] = VERSION
write_config_file( config_opts, config_file )