diff --git a/bin/blockstack-subdomain-registrar b/bin/blockstack-subdomain-registrar deleted file mode 100644 index 8d8981d7d..000000000 --- a/bin/blockstack-subdomain-registrar +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python2 -# -*- coding: utf-8 -*- -""" - Blockstack - ~~~~~ - copyright: (c) 2017 by Blockstack.org - - This file is part of Blockstack - - Blockstack is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Blockstack is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with Blockstack. If not, see . -""" - -from subdomain_registrar import subdomains_registrar - -if __name__ == "__main__": - subdomains_registrar.main_entry() diff --git a/blockstack/lib/rpc.py b/blockstack/lib/rpc.py index ba493ee98..4c75ffc50 100644 --- a/blockstack/lib/rpc.py +++ b/blockstack/lib/rpc.py @@ -431,14 +431,46 @@ class BlockstackAPIEndpointHandler(SimpleHTTPRequestHandler): except ValueError: return self._reply_json({'error': 'Invalid argument: not a well-formed name or subdomain'}, status_code=400) + if 'error' in name_rec: if 'not found' in name_rec['error'].lower(): return self._reply_json({'status': 'available'}, status_code=404) + elif 'failed to load subdomain' in name_rec['error'].lower(): - return self._reply_json({'status': 'available'}, status_code=404) + + # try to redirect to resolver, if given + _, _, domain_name = blockstackd_scripts.is_address_subdomain(name) + domain_rec = blockstackd_client.get_name_record(domain_name, include_history=False, hostport=blockstackd_url) + + if 'error' in domain_rec or 'zonefile' not in domain_rec: + # could not look up on-chain name, or no zone file + return self._reply_json({'status': 'available', 'more': 'failed to lookup parent domain'}, status_code=404) + + # see if there's a _resolver URI record + domain_zf_txt = base64.b64decode(domain_rec['zonefile']) + domain_zf_json = blockstackd_client.decode_name_zonefile(domain_name, domain_zf_txt) + matching_uris = [ x['target'] for x in domain_zf_json['uri'] if x['name'] == '_resolver' ] + + if len(matching_uris) == 0: + # no _resolver + return self._reply_json({'status': 'available', 'more': 'failed to find parent domain\'s resolver'}, status_code=404) + + # go with the first _resolver (TODO: maybe use weight?) + resolver_target = matching_uris[0].rstrip('/') + redirect_location = resolver_target + '/v1/names/' + name + + log.debug("Redirect lookup on {} to {}".format(name, redirect_location)) + + self._send_headers(status_code=301, more_headers={ 'Location': redirect_location }) + return self.wfile.write(json.dumps({'status': 'redirect'})) + + elif 'expired' in name_rec['error'].lower(): + return self._reply_json({'error': name_rec['error']}, status_code=404) + else: return self._reply_json({'error': 'Blockstack daemon error: {}'.format(name_rec['error'])}, status_code=name_rec.get('http_status', 500)) + zonefile_txt = None if 'zonefile' in name_rec: diff --git a/integration_tests/blockstack_integration_tests/scenarios/subdomain_registrar_redirect_test.py b/integration_tests/blockstack_integration_tests/scenarios/subdomain_registrar_redirect_test.py index 17e96dd3b..c54a4df86 100644 --- a/integration_tests/blockstack_integration_tests/scenarios/subdomain_registrar_redirect_test.py +++ b/integration_tests/blockstack_integration_tests/scenarios/subdomain_registrar_redirect_test.py @@ -48,24 +48,14 @@ wallets = [ consensus = "17ac43c1d8549c3181b200f1bf97eb7d" -TRANSACTION_BROADCAST_LOCATION = os.environ.get('BSK_TRANSACTION_BROADCAST_LOCATION', - '/src/transaction-broadcaster') - SUBDOMAIN_REGISTRAR_LOCATION = os.environ.get('BSK_SUBDOMAIN_REGISTRAR_LOCATION', - '/src/subdomain-registrar') + '/usr/bin/blockstack-subdomain-registrar') -def start_transaction_broadcaster(): - try: - os.rename('/tmp/transaction_broadcaster.db', '/tmp/transaction_broadcaster.db.last') - except OSError: - pass - env = {'BSK_TRANSACTION_BROADCAST_DEVELOP' : '1'} - if os.environ.get('BLOCKSTACK_TEST_CLIENT_RPC_PORT', False): - env['BLOCKSTACK_TEST_CLIENT_RPC_PORT'] = os.environ.get('BLOCKSTACK_TEST_CLIENT_RPC_PORT') - Popen(['node', TRANSACTION_BROADCAST_LOCATION + '/lib/index.js'], - env = env) +SUBDOMAIN_PROC = None def start_subdomain_registrar(): + global SUBDOMAIN_PROC + try: os.rename('/tmp/subdomain_registrar.db', '/tmp/subdomain_registrar.last') except OSError: @@ -73,11 +63,13 @@ def start_subdomain_registrar(): env = {'BSK_SUBDOMAIN_REGTEST' : '1'} if os.environ.get('BLOCKSTACK_TEST_CLIENT_RPC_PORT', False): env['BLOCKSTACK_TEST_CLIENT_RPC_PORT'] = os.environ.get('BLOCKSTACK_TEST_CLIENT_RPC_PORT') - Popen(['node', SUBDOMAIN_REGISTRAR_LOCATION + '/lib/index.js'], env = env) + + SUBDOMAIN_PROC = Popen(['node', SUBDOMAIN_REGISTRAR_LOCATION], env = env) + testlib.add_cleanup(lambda: SUBDOMAIN_PROC.kill()) + def scenario( wallets, **kw ): - start_transaction_broadcaster() start_subdomain_registrar() testlib.blockstack_namespace_preorder( "id", wallets[1].addr, wallets[0].privkey ) @@ -89,34 +81,7 @@ def scenario( wallets, **kw ): testlib.blockstack_namespace_ready( "id", wallets[1].privkey ) testlib.next_block( **kw ) - wallet = testlib.blockstack_client_initialize_wallet( "0123456789abcdef", wallets[2].privkey, wallets[3].privkey, wallets[4].privkey ) - resp = testlib.blockstack_cli_register( "foo.id", "0123456789abcdef" ) - if 'error' in resp: - print >> sys.stderr, json.dumps(resp, indent=4, sort_keys=True) - return False - - # wait for the preorder to get confirmed - for i in xrange(0, 12): - testlib.next_block( **kw ) - - # wait for the poller to pick it up - print >> sys.stderr, "Waiting 10 seconds for the backend to submit the register" - time.sleep(10) - - # wait for the register to get confirmed - for i in xrange(0, 12): - testlib.next_block( **kw ) - - print >> sys.stderr, "Waiting 10 seconds for the backend to acknowledge registration" - time.sleep(10) - - # wait for update to get confirmed - for i in xrange(0, 12): - testlib.next_block( **kw ) - - print >> sys.stderr, "Waiting 10 seconds for the backend to acknowledge update" - time.sleep(10) - + testlib.blockstack_register_user("foo.id", wallets[2].privkey, wallets[3].privkey, **kw) # now, queue a registration.