def subdomain_record_to_profile(my_rec): owner_addr = my_rec.address assert isinstance(my_rec.zonefile_str, (str, unicode)) parsed_zf = bs_zonefile.decode_name_zonefile(my_rec.subdomain_name, my_rec.zonefile_str) urls = user_db.user_zonefile_urls(parsed_zf) # try to get pubkey from zonefile, or default to ``owner`` pubkey user_data_pubkey = None try: user_data_pubkey = user_db.user_zonefile_data_pubkey(parsed_zf) if user_data_pubkey is not None: user_data_pubkey = str(user_data_pubkey) except ValueError: pass # no pubkey defined in zonefile try: user_profile = storage.get_mutable_data( None, user_data_pubkey, blockchain_id=None, data_address=owner_addr, owner_address=None, urls=urls, drivers=None, decode=True, ) except: user_profile = None if user_profile is None: user_profile = {'error' : 'Error fetching the data for subdomain {}'.format(my_rec.get_fqn())} data = { 'profile' : user_profile, 'zonefile' : parsed_zf } return data
def test_basic_with_multisig(self): test_zf = """$ORIGIN bar.id $TTL 3600 pubkey TXT "pubkey:data:0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" registrar URI 10 1 "bsreg://foo.com:8234" foo TXT "owner={}" "seqn=3" "parts=0" """ my_keys = [keylib.ECPrivateKey() for _ in range(3)] my_pubkeys = [k.public_key().to_hex() for k in my_keys] owner_addr = virtualchain.make_multisig_address(my_pubkeys, 3) test_zf = test_zf.format(owner_addr) domain_name = "bar.id" zf_json = zonefile.decode_name_zonefile(domain_name, test_zf) self.assertEqual(zf_json['$origin'], domain_name) subds = subdomains.parse_zonefile_subdomains(domain_name, zf_json) self.assertEqual(len(subds), 1) sub = subds[0] self.assertEqual(sub.n, 3) self.assertEqual(sub.sig, None) self.assertEqual(sub.subdomain_name, "foo")
def test_basic(self): test_zf = """$ORIGIN bar.id $TTL 3600 pubkey TXT "pubkey:data:0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" registrar URI 10 1 "bsreg://foo.com:8234" foo TXT "owner={}" "seqn=3" "parts=0" """ fake_privkey_hex = "5512612ed6ef10ea8c5f9839c63f62107c73db7306b98588a46d0cd2c3d15ea5" sk = keylib.ECPrivateKey(fake_privkey_hex) pk = sk.public_key() test_zf = test_zf.format(subdomains.encode_pubkey_entry(pk)) domain_name = "bar.id" zf_json = zonefile.decode_name_zonefile(domain_name, test_zf) self.assertEqual(zf_json['$origin'], domain_name) subds = subdomains.parse_zonefile_subdomains(domain_name, zf_json) self.assertEqual(len(subds), 1) sub = subds[0] self.assertEqual(sub.n, 3) self.assertEqual(sub.sig, None) self.assertEqual(sub.subdomain_name, "foo")
def test_sigs(self): fake_privkey_hex = "5512612ed6ef10ea8c5f9839c63f62107c73db7306b98588a46d0cd2c3d15ea5" sk = keylib.ECPrivateKey(fake_privkey_hex) pk = sk.public_key() for t in ["foo", "bar", "bassoon"]: self.assertTrue( subdomains.verify(pk.address(), t, subdomains.sign(sk, t)), t) subdomain = subdomains.Subdomain("bar.id", "foo", subdomains.encode_pubkey_entry(sk), 3, "") user_zf = {'$origin': 'foo', '$ttl': 3600, 'txt': [], 'uri': []} user_zf['uri'].append( zonefile.url_to_uri_record("https://foo_foo.com/profile.json")) jsonschema.validate(user_zf, USER_ZONEFILE_SCHEMA) subdomain.zonefile_str = blockstack_zones.make_zone_file(user_zf) subdomain.add_signature(sk) self.assertTrue(subdomain.verify_signature(pk.address())) parsed_zf = zonefile.decode_name_zonefile(subdomain.subdomain_name, subdomain.zonefile_str) urls = user_db.user_zonefile_urls(parsed_zf) self.assertEqual(len(urls), 1) self.assertIn("https://foo_foo.com/profile.json", urls) self.assertRaises( NotImplementedError, lambda: subdomains.encode_pubkey_entry(fake_privkey_hex))
def _build_subdomain_db(domain_fqas, zonefiles, subdomain_db=None, txids=None): if subdomain_db is None: subdomain_db = {} if txids is None: txids = [None for x in zonefiles] for zf, domain_fqa, txid in zip(zonefiles, domain_fqas, txids): if isinstance(zf, dict): assert "zonefile" not in zf zf_json = zf else: assert isinstance(zf, (str, unicode)) zf_json = bs_zonefile.decode_name_zonefile(domain_fqa, zf) assert "zonefile" not in zf_json subdomains = parse_zonefile_subdomains(domain_fqa, zf_json) for subdomain in subdomains: if txid: subdomain.last_txid = txid if subdomain.get_fqn() in subdomain_db: previous = subdomain_db[subdomain.get_fqn()] if _transition_valid(previous, subdomain): subdomain_db[subdomain.get_fqn()] = subdomain else: log.warn("Failed subdomain transition for {} on N:{}->{}". format(subdomain.get_fqn(), previous.n, subdomain.n)) else: if subdomain.n != 0: log.warn("First sight of subdomain {} with N={}".format( subdomain.get_fqn(), subdomain.n)) continue subdomain_db[subdomain.get_fqn()] = subdomain return subdomain_db
def _build_subdomain_db(domain_fqas, zonefiles, subdomain_db = None, txids = None): if subdomain_db is None: subdomain_db = {} if txids is None: txids = [None for x in zonefiles] for zf, domain_fqa, txid in zip(zonefiles, domain_fqas, txids): if isinstance(zf, dict): assert "zonefile" not in zf zf_json = zf else: assert isinstance(zf, (str, unicode)) zf_json = bs_zonefile.decode_name_zonefile(domain_fqa, zf) assert "zonefile" not in zf_json subdomains = parse_zonefile_subdomains(domain_fqa, zf_json) for subdomain in subdomains: if txid: subdomain.last_txid = txid if subdomain.get_fqn() in subdomain_db: previous = subdomain_db[subdomain.get_fqn()] if _transition_valid(previous, subdomain): subdomain_db[subdomain.get_fqn()] = subdomain else: log.warn("Failed subdomain transition for {} on N:{}->{}".format( subdomain.get_fqn(), previous.n, subdomain.n)) else: if subdomain.n != 0: log.warn("First sight of subdomain {} with N={}".format( subdomain.get_fqn(), subdomain.n)) continue subdomain_db[subdomain.get_fqn()] = subdomain return subdomain_db
def test_sigs(self): fake_privkey_hex = "5512612ed6ef10ea8c5f9839c63f62107c73db7306b98588a46d0cd2c3d15ea5" sk = keylib.ECPrivateKey(fake_privkey_hex) pk = sk.public_key() for t in ["foo", "bar", "bassoon"]: self.assertTrue(subdomains.verify(pk.address(), t, subdomains.sign(sk, t)), t) subdomain = subdomains.Subdomain("bar.id", "foo", subdomains.encode_pubkey_entry(sk), 3, "") user_zf = { '$origin': 'foo', '$ttl': 3600, 'txt' : [], 'uri' : [] } user_zf['uri'].append(zonefile.url_to_uri_record("https://foo_foo.com/profile.json")) jsonschema.validate(user_zf, USER_ZONEFILE_SCHEMA) subdomain.zonefile_str = blockstack_zones.make_zone_file(user_zf) subdomain.add_signature(sk) self.assertTrue(subdomain.verify_signature(pk.address())) parsed_zf = zonefile.decode_name_zonefile(subdomain.subdomain_name, subdomain.zonefile_str) urls = user_db.user_zonefile_urls(parsed_zf) self.assertEqual(len(urls), 1) self.assertIn("https://foo_foo.com/profile.json", urls) self.assertRaises( NotImplementedError, lambda : subdomains.encode_pubkey_entry( fake_privkey_hex ) )
def test_basic_with_multisig(self): test_zf = """$ORIGIN bar.id $TTL 3600 pubkey TXT "pubkey:data:0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" registrar URI 10 1 "bsreg://foo.com:8234" foo TXT "owner={}" "seqn=3" "parts=0" """ my_keys = [ keylib.ECPrivateKey() for _ in range(3) ] my_pubkeys = [ k.public_key().to_hex() for k in my_keys ] owner_addr = virtualchain.make_multisig_address(my_pubkeys, 3) test_zf = test_zf.format(owner_addr) domain_name = "bar.id" zf_json = zonefile.decode_name_zonefile(domain_name, test_zf) self.assertEqual(zf_json['$origin'], domain_name) subds = subdomains.parse_zonefile_subdomains(domain_name, zf_json) self.assertEqual(len(subds), 1) sub = subds[0] self.assertEqual(sub.n, 3) self.assertEqual(sub.sig, None) self.assertEqual(sub.subdomain_name, "foo")
def test_basic(self): test_zf = """$ORIGIN bar.id $TTL 3600 pubkey TXT "pubkey:data:0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" registrar URI 10 1 "bsreg://foo.com:8234" foo TXT "owner={}" "seqn=3" "parts=0" """ fake_privkey_hex = "5512612ed6ef10ea8c5f9839c63f62107c73db7306b98588a46d0cd2c3d15ea5" sk = keylib.ECPrivateKey(fake_privkey_hex) pk = sk.public_key() test_zf = test_zf.format(subdomains.encode_pubkey_entry(pk)) domain_name = "bar.id" zf_json = zonefile.decode_name_zonefile(domain_name, test_zf) self.assertEqual(zf_json['$origin'], domain_name) subds = subdomains.parse_zonefile_subdomains(domain_name, zf_json) self.assertEqual(len(subds), 1) sub = subds[0] self.assertEqual(sub.n, 3) self.assertEqual(sub.sig, None) self.assertEqual(sub.subdomain_name, "foo")
def test_large_zonefile(self): empty_zf = """$ORIGIN registrar.id $TTL 3600 pubkey TXT "pubkey:data:0" registrar URI 10 1 "bsreg://foo.com:8234" """ domain_name = "registrar.id" zf_js = zonefile.decode_name_zonefile(domain_name, empty_zf)
def test_large_zonefile(self): empty_zf = """$ORIGIN registrar.id $TTL 3600 pubkey TXT "pubkey:data:0" registrar URI 10 1 "bsreg://foo.com:8234" """ domain_name = "registrar.id" zf_js = zonefile.decode_name_zonefile(domain_name, empty_zf)
def test_parse_errs(self): zf = """$ORIGIN bar.id $TTL 3600 pubkey TXT "pubkey:data:0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" registrar URI 10 1 "bsreg://foo.com:8234" foo TXT should_not_parse """ domain_name = "bar.id" zf_json = zonefile.decode_name_zonefile(domain_name, zf) self.assertEqual(len(subdomains.parse_zonefile_subdomains(domain_name, zf_json)), 0) zf = """$ORIGIN bar.id $TTL 3600 pubkey TXT "pubkey:data:0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" registrar URI 10 1 "bsreg://foo.com:8234" foo TXT "owner={}" "seqn=3" "should_not_parse" """ zf_json = zonefile.decode_name_zonefile(domain_name, zf) self.assertEqual(len(subdomains.parse_zonefile_subdomains(domain_name, zf_json)), 0)
def test_parse_errs(self): zf = """$ORIGIN bar.id $TTL 3600 pubkey TXT "pubkey:data:0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" registrar URI 10 1 "bsreg://foo.com:8234" foo TXT should_not_parse """ domain_name = "bar.id" zf_json = zonefile.decode_name_zonefile(domain_name, zf) self.assertEqual( len(subdomains.parse_zonefile_subdomains(domain_name, zf_json)), 0) zf = """$ORIGIN bar.id $TTL 3600 pubkey TXT "pubkey:data:0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" registrar URI 10 1 "bsreg://foo.com:8234" foo TXT "owner={}" "seqn=3" "should_not_parse" """ zf_json = zonefile.decode_name_zonefile(domain_name, zf) self.assertEqual( len(subdomains.parse_zonefile_subdomains(domain_name, zf_json)), 0)
def test_db_builder_bad_transitions(self): history = [ """$ORIGIN bar.id $TTL 3600 pubkey TXT "pubkey:data:0" registrar URI 10 1 "bsreg://foo.com:8234" foo TXT "owner={}" "seqn=0" "parts=0" """, """$ORIGIN bar.id $TTL 3600 pubkey TXT "pubkey:data:0" registrar URI 10 1 "bsreg://foo.com:8234" bar TXT "owner={}" "seqn=0" "parts=0" """, ] foo_bar_sk = keylib.ECPrivateKey() bar_bar_sk = keylib.ECPrivateKey() history[0] = history[0].format( subdomains.encode_pubkey_entry(foo_bar_sk)) history[1] = history[1].format( subdomains.encode_pubkey_entry(bar_bar_sk)) domain_name = "bar.id" empty_zf = """$ORIGIN bar.id $TTL 3600 pubkey TXT "pubkey:data:0" registrar URI 10 1 "bsreg://foo.com:8234" """ zf_json = zonefile.decode_name_zonefile(domain_name, empty_zf) self.assertEqual(zf_json['$origin'], domain_name) # bad transition n=0 -> n=0 sub1 = subdomains.Subdomain("foo", domain_name, subdomains.encode_pubkey_entry(foo_bar_sk), 0, "") subdomain_util._extend_with_subdomain(zf_json, sub1) history.append(blockstack_zones.make_zone_file(zf_json)) # bad transition bad sig. zf_json = zonefile.decode_name_zonefile(domain_name, empty_zf) self.assertEqual(zf_json['$origin'], domain_name) sub2 = subdomains.Subdomain("foo", domain_name, subdomains.encode_pubkey_entry(bar_bar_sk), 1, "") subdomain_util._extend_with_subdomain(zf_json, sub2) history.append(blockstack_zones.make_zone_file(zf_json)) subdomain_db = subdomains._build_subdomain_db( ["bar.id" for x in range(1)], history[:1]) self.assertEqual(subdomain_db["foo.bar.id"].n, 0) self.assertNotIn("bar.bar.id", subdomain_db) subdomain_db = subdomains._build_subdomain_db( ["bar.id" for x in range(2)], history[:2]) self.assertIn("bar.bar.id", subdomain_db) self.assertEqual(subdomain_db["bar.bar.id"].n, 0) subdomain_db = subdomains._build_subdomain_db( ["bar.id" for x in range(3)], history[:3]) self.assertEqual(subdomain_db["foo.bar.id"].n, 0) self.assertEqual(subdomain_db["bar.bar.id"].n, 0) # handle repeated zonefile subdomain_db = subdomains._build_subdomain_db( ["bar.id" for x in range(3)], history[:3]) self.assertEqual(subdomain_db["foo.bar.id"].n, 0) self.assertEqual(subdomain_db["bar.bar.id"].n, 0) subdomains._build_subdomain_db(["bar.id" for x in range(3)], history[:3], subdomain_db=subdomain_db) self.assertEqual(subdomain_db["foo.bar.id"].n, 0) self.assertEqual(subdomain_db["bar.bar.id"].n, 0)
def test_db_builder(self): history = [ """$ORIGIN bar.id $TTL 3600 pubkey TXT "pubkey:data:0" registrar URI 10 1 "bsreg://foo.com:8234" foo TXT "owner={}" "seqn=0" "parts=0" """, """$ORIGIN bar.id $TTL 3600 pubkey TXT "pubkey:data:0" registrar URI 10 1 "bsreg://foo.com:8234" bar TXT "owner={}" "seqn=0" "parts=0" """, ] foo_bar_sk = keylib.ECPrivateKey() bar_bar_sk = keylib.ECPrivateKey() history[0] = history[0].format( subdomains.encode_pubkey_entry(foo_bar_sk)) history[1] = history[1].format( subdomains.encode_pubkey_entry(bar_bar_sk)) domain_name = "bar.id" empty_zf = """$ORIGIN bar.id $TTL 3600 pubkey TXT "pubkey:data:0" registrar URI 10 1 "bsreg://foo.com:8234" """ zf_json = zonefile.decode_name_zonefile(domain_name, empty_zf) self.assertEqual(zf_json['$origin'], domain_name) sub1 = subdomains.Subdomain(domain_name, "foo", subdomains.encode_pubkey_entry(foo_bar_sk), 1, "") sub2 = subdomains.Subdomain(domain_name, "bar", subdomains.encode_pubkey_entry(bar_bar_sk), 1, "") sub1.add_signature(foo_bar_sk) sub2.add_signature(bar_bar_sk) subdomain_util._extend_with_subdomain(zf_json, sub2) history.append(blockstack_zones.make_zone_file(zf_json)) zf_json = zonefile.decode_name_zonefile(domain_name, empty_zf) subdomain_util._extend_with_subdomain(zf_json, sub1) history.append(blockstack_zones.make_zone_file(zf_json)) subdomain_db = subdomains._build_subdomain_db( ["bar.id" for x in range(1)], history[:1]) self.assertIn("foo.bar.id", subdomain_db, "Contents actually: {}".format(subdomain_db.keys())) self.assertEqual(subdomain_db["foo.bar.id"].n, 0) self.assertNotIn("bar.bar.id", subdomain_db) subdomain_db = subdomains._build_subdomain_db( ["bar.id" for x in range(2)], history[:2]) self.assertIn("bar.bar.id", subdomain_db) self.assertEqual(subdomain_db["bar.bar.id"].n, 0) subdomain_db = subdomains._build_subdomain_db( ["bar.id" for x in range(3)], history[:3]) self.assertEqual(subdomain_db["foo.bar.id"].n, 0) self.assertEqual(subdomain_db["bar.bar.id"].n, 1) subdomain_db = subdomains._build_subdomain_db( ["bar.id" for x in range(len(history))], history) self.assertEqual(subdomain_db["foo.bar.id"].n, 1) self.assertEqual(subdomain_db["bar.bar.id"].n, 1)
def test_db_builder_bad_transitions(self): history = [ """$ORIGIN bar.id $TTL 3600 pubkey TXT "pubkey:data:0" registrar URI 10 1 "bsreg://foo.com:8234" foo TXT "owner={}" "seqn=0" "parts=0" """, """$ORIGIN bar.id $TTL 3600 pubkey TXT "pubkey:data:0" registrar URI 10 1 "bsreg://foo.com:8234" bar TXT "owner={}" "seqn=0" "parts=0" """, ] foo_bar_sk = keylib.ECPrivateKey() bar_bar_sk = keylib.ECPrivateKey() history[0] = history[0].format(subdomains.encode_pubkey_entry(foo_bar_sk)) history[1] = history[1].format(subdomains.encode_pubkey_entry(bar_bar_sk)) domain_name = "bar.id" empty_zf = """$ORIGIN bar.id $TTL 3600 pubkey TXT "pubkey:data:0" registrar URI 10 1 "bsreg://foo.com:8234" """ zf_json = zonefile.decode_name_zonefile(domain_name, empty_zf) self.assertEqual(zf_json['$origin'], domain_name) # bad transition n=0 -> n=0 sub1 = subdomains.Subdomain("foo", domain_name, subdomains.encode_pubkey_entry(foo_bar_sk), 0, "") subdomain_util._extend_with_subdomain(zf_json, sub1) history.append(blockstack_zones.make_zone_file(zf_json)) # bad transition bad sig. zf_json = zonefile.decode_name_zonefile(domain_name, empty_zf) self.assertEqual(zf_json['$origin'], domain_name) sub2 = subdomains.Subdomain("foo", domain_name, subdomains.encode_pubkey_entry(bar_bar_sk), 1, "") subdomain_util._extend_with_subdomain(zf_json, sub2) history.append(blockstack_zones.make_zone_file(zf_json)) subdomain_db = subdomains._build_subdomain_db(["bar.id" for x in range(1)], history[:1]) self.assertEqual(subdomain_db["foo.bar.id"].n, 0) self.assertNotIn("bar.bar.id", subdomain_db) subdomain_db = subdomains._build_subdomain_db(["bar.id" for x in range(2)], history[:2]) self.assertIn("bar.bar.id", subdomain_db) self.assertEqual(subdomain_db["bar.bar.id"].n, 0) subdomain_db = subdomains._build_subdomain_db(["bar.id" for x in range(3)], history[:3]) self.assertEqual(subdomain_db["foo.bar.id"].n, 0) self.assertEqual(subdomain_db["bar.bar.id"].n, 0) # handle repeated zonefile subdomain_db = subdomains._build_subdomain_db(["bar.id" for x in range(3)], history[:3]) self.assertEqual(subdomain_db["foo.bar.id"].n, 0) self.assertEqual(subdomain_db["bar.bar.id"].n, 0) subdomains._build_subdomain_db(["bar.id" for x in range(3)], history[:3], subdomain_db = subdomain_db) self.assertEqual(subdomain_db["foo.bar.id"].n, 0) self.assertEqual(subdomain_db["bar.bar.id"].n, 0)
def test_db_builder(self): history = [ """$ORIGIN bar.id $TTL 3600 pubkey TXT "pubkey:data:0" registrar URI 10 1 "bsreg://foo.com:8234" foo TXT "owner={}" "seqn=0" "parts=0" """, """$ORIGIN bar.id $TTL 3600 pubkey TXT "pubkey:data:0" registrar URI 10 1 "bsreg://foo.com:8234" bar TXT "owner={}" "seqn=0" "parts=0" """, ] foo_bar_sk = keylib.ECPrivateKey() bar_bar_sk = keylib.ECPrivateKey() history[0] = history[0].format(subdomains.encode_pubkey_entry(foo_bar_sk)) history[1] = history[1].format(subdomains.encode_pubkey_entry(bar_bar_sk)) domain_name = "bar.id" empty_zf = """$ORIGIN bar.id $TTL 3600 pubkey TXT "pubkey:data:0" registrar URI 10 1 "bsreg://foo.com:8234" """ zf_json = zonefile.decode_name_zonefile(domain_name, empty_zf) self.assertEqual(zf_json['$origin'], domain_name) sub1 = subdomains.Subdomain(domain_name, "foo", subdomains.encode_pubkey_entry(foo_bar_sk), 1, "") sub2 = subdomains.Subdomain(domain_name, "bar", subdomains.encode_pubkey_entry(bar_bar_sk), 1, "") sub1.add_signature(foo_bar_sk) sub2.add_signature(bar_bar_sk) subdomain_util._extend_with_subdomain(zf_json, sub2) history.append(blockstack_zones.make_zone_file(zf_json)) zf_json = zonefile.decode_name_zonefile(domain_name, empty_zf) subdomain_util._extend_with_subdomain(zf_json, sub1) history.append(blockstack_zones.make_zone_file(zf_json)) subdomain_db = subdomains._build_subdomain_db(["bar.id" for x in range(1)], history[:1]) self.assertIn("foo.bar.id", subdomain_db, "Contents actually: {}".format(subdomain_db.keys())) self.assertEqual(subdomain_db["foo.bar.id"].n, 0) self.assertNotIn("bar.bar.id", subdomain_db) subdomain_db = subdomains._build_subdomain_db(["bar.id" for x in range(2)], history[:2]) self.assertIn("bar.bar.id", subdomain_db) self.assertEqual(subdomain_db["bar.bar.id"].n, 0) subdomain_db = subdomains._build_subdomain_db(["bar.id" for x in range(3)], history[:3]) self.assertEqual(subdomain_db["foo.bar.id"].n, 0) self.assertEqual(subdomain_db["bar.bar.id"].n, 1) subdomain_db = subdomains._build_subdomain_db(["bar.id" for x in range(len(history))], history) self.assertEqual(subdomain_db["foo.bar.id"].n, 1) self.assertEqual(subdomain_db["bar.bar.id"].n, 1)