diff --git a/crates/client-api/src/lib.rs b/crates/client-api/src/lib.rs index f0c5dadb1e4..23d783bc573 100644 --- a/crates/client-api/src/lib.rs +++ b/crates/client-api/src/lib.rs @@ -131,7 +131,7 @@ pub trait ControlStateWriteAccess: Send + Sync { async fn register_tld(&self, identity: &Identity, tld: Tld) -> anyhow::Result; async fn create_dns_record( &self, - identity: &Identity, + owner_identity: &Identity, domain: &DomainName, database_identity: &Identity, ) -> anyhow::Result; diff --git a/crates/client-api/src/routes/database.rs b/crates/client-api/src/routes/database.rs index a2a8342074d..e51c3d7aee3 100644 --- a/crates/client-api/src/routes/database.rs +++ b/crates/client-api/src/routes/database.rs @@ -384,17 +384,17 @@ pub async fn info( State(worker_ctx): State, Path(InfoParams { name_or_identity }): Path, ) -> axum::response::Result { - log::trace!("Trying to resolve address: {:?}", name_or_identity); - let address = name_or_identity.resolve(&worker_ctx).await?.into(); - log::trace!("Resolved address to: {address:?}"); - let database = worker_ctx_find_database(&worker_ctx, &address) + log::trace!("Trying to resolve database identity: {:?}", name_or_identity); + let database_identity = name_or_identity.resolve(&worker_ctx).await?.into(); + log::trace!("Resolved identity to: {database_identity:?}"); + let database = worker_ctx_find_database(&worker_ctx, &database_identity) .await? .ok_or((StatusCode::NOT_FOUND, "No such database."))?; - log::trace!("Fetched database from the worker db for address: {address:?}"); + log::trace!("Fetched database from the worker db for address: {database_identity:?}"); let host_type: &str = database.host_type.as_ref(); let response_json = json!({ - "address": database.database_identity, + "database_identity": database.database_identity, "owner_identity": database.owner_identity, "host_type": host_type, "initial_program": database.initial_program, @@ -679,13 +679,14 @@ pub async fn publish( // You should not be able to publish to a database that you do not own // so, unless you are the owner, this will fail. - let (db_addr, db_name) = match name_or_identity { + let (database_identity, db_name) = match name_or_identity { Some(noa) => match noa.try_resolve(&ctx).await? { Ok(resolved) => resolved.into(), Err(domain) => { // `name_or_address` was a `NameOrAddress::Name`, but no record // exists yet. Create it now with a fresh address. - let database_identity = Identity::placeholder(); + let database_auth = SpacetimeAuth::alloc(&ctx).await?; + let database_identity = database_auth.identity; ctx.create_dns_record(&auth.identity, &domain, &database_identity) .await .map_err(log_and_500)?; @@ -693,18 +694,22 @@ pub async fn publish( } }, None => { - let database_identity = Identity::placeholder(); + let database_auth = SpacetimeAuth::alloc(&ctx).await?; + let database_identity = database_auth.identity; (database_identity, None) } }; - log::trace!("Publishing to the address: {}", db_addr.to_hex()); + log::trace!("Publishing to the address: {}", database_identity.to_hex()); let op = { - let exists = ctx.get_database_by_identity(&db_addr).map_err(log_and_500)?.is_some(); + let exists = ctx + .get_database_by_identity(&database_identity) + .map_err(log_and_500)? + .is_some(); if clear && exists { - ctx.delete_database(&auth.identity, &db_addr) + ctx.delete_database(&auth.identity, &database_identity) .await .map_err(log_and_500)?; } @@ -720,7 +725,7 @@ pub async fn publish( .publish_database( &auth.identity, DatabaseDef { - database_identity: db_addr, + database_identity, program_bytes: body.into(), num_replicas: 1, host_type: HostType::Wasm, @@ -747,7 +752,7 @@ pub async fn publish( Ok(axum::Json(PublishResult::Success { domain: db_name.as_ref().map(ToString::to_string), - database_identity: db_addr, + database_identity, op, })) } @@ -783,14 +788,14 @@ pub async fn set_name( State(ctx): State, Query(SetNameQueryParams { domain, - database_identity: address, + database_identity, }): Query, Extension(auth): Extension, ) -> axum::response::Result { - let address = Identity::from(address); + let database_identity = Identity::from(database_identity); let database = ctx - .get_database_by_identity(&address) + .get_database_by_identity(&database_identity) .map_err(log_and_500)? .ok_or((StatusCode::NOT_FOUND, "No such database."))?; @@ -800,7 +805,7 @@ pub async fn set_name( let domain = domain.parse().map_err(|_| DomainParsingRejection)?; let response = ctx - .create_dns_record(&auth.identity, &domain, &address) + .create_dns_record(&auth.identity, &domain, &database_identity) .await // TODO: better error code handling .map_err(log_and_500)?; diff --git a/crates/client-api/src/util.rs b/crates/client-api/src/util.rs index 27c222fe73e..652906a2c74 100644 --- a/crates/client-api/src/util.rs +++ b/crates/client-api/src/util.rs @@ -91,16 +91,16 @@ impl NameOrIdentity { ctx: &(impl ControlStateReadAccess + ?Sized), ) -> axum::response::Result> { Ok(match self { - Self::Identity(addr) => Ok(ResolvedIdentity { - identity: Identity::from(*addr), + Self::Identity(identity) => Ok(ResolvedIdentity { + identity: Identity::from(*identity), domain: None, }), Self::Name(name) => { let domain = name.parse().map_err(|_| DomainParsingRejection)?; - let address = ctx.lookup_identity(&domain).map_err(log_and_500)?; - match address { - Some(address) => Ok(ResolvedIdentity { - identity: address, + let identity = ctx.lookup_identity(&domain).map_err(log_and_500)?; + match identity { + Some(identity) => Ok(ResolvedIdentity { + identity, domain: Some(domain), }), None => Err(domain), diff --git a/crates/lib/src/identity.rs b/crates/lib/src/identity.rs index 6a93027010e..eed44fa74ee 100644 --- a/crates/lib/src/identity.rs +++ b/crates/lib/src/identity.rs @@ -1,8 +1,6 @@ use crate::from_hex_pad; use blake3; use core::mem; -use rand; -use rand::Rng; use spacetimedb_bindings_macro::{Deserialize, Serialize}; use spacetimedb_sats::hex::HexString; use spacetimedb_sats::{hash, impl_st, u256, AlgebraicType, AlgebraicValue}; @@ -53,13 +51,6 @@ impl spacetimedb_metrics::typed_prometheus::AsPrometheusLabel for Identity { impl Identity { pub const ZERO: Self = Self::from_u256(u256::ZERO); - pub fn placeholder() -> Self { - // Generate a random identity. - let mut rng = rand::thread_rng(); - let mut random_bytes = [0u8; 32]; - rng.fill(&mut random_bytes); - Identity::from_byte_array(random_bytes) - } /// Returns an `Identity` defined as the given `bytes` byte array. pub const fn from_byte_array(bytes: [u8; 32]) -> Self { // SAFETY: The transmute is an implementation of `u256::from_ne_bytes`, diff --git a/crates/testing/src/modules.rs b/crates/testing/src/modules.rs index c82dfd5a629..711298ee32a 100644 --- a/crates/testing/src/modules.rs +++ b/crates/testing/src/modules.rs @@ -6,6 +6,7 @@ use std::time::Instant; use spacetimedb::messages::control_db::HostType; use spacetimedb::Identity; +use spacetimedb_client_api::auth::SpacetimeAuth; use spacetimedb_client_api::routes::subscribe::generate_random_address; use spacetimedb_lib::ser::serde::SerializeWrapper; use tokio::runtime::{Builder, Runtime}; @@ -152,7 +153,7 @@ impl CompiledModule { let env = spacetimedb_standalone::StandaloneEnv::init(config).await.unwrap(); // TODO: Fix this when we update identity generation. let identity = Identity::ZERO; - let db_identity = Identity::placeholder(); + let db_identity = SpacetimeAuth::alloc(&env).await.unwrap().identity; let client_address = generate_random_address(); let program_bytes = self diff --git a/smoketests/__init__.py b/smoketests/__init__.py index 83a8e32b1fa..5520cc1ebbf 100644 --- a/smoketests/__init__.py +++ b/smoketests/__init__.py @@ -159,20 +159,20 @@ def spacetime(cls, *args, **kwargs): return spacetime(*args, **kwargs) def _check_published(self): - if not hasattr(self, "address"): + if not hasattr(self, "database_identity"): raise Exception("Cannot use this function without publishing a module") def call(self, reducer, *args, anon=False): self._check_published() anon = ["--anonymous"] if anon else [] - self.spacetime("call", *anon, "--", self.address, reducer, *map(json.dumps, args)) + self.spacetime("call", *anon, "--", self.database_identity, reducer, *map(json.dumps, args)) def logs(self, n): return [log["message"] for log in self.log_records(n)] def log_records(self, n): self._check_published() - logs = self.spacetime("logs", "--format=json", "-n", str(n), "--", self.address) + logs = self.spacetime("logs", "--format=json", "-n", str(n), "--", self.database_identity) return list(map(json.loads, logs.splitlines())) def publish_module(self, domain=None, *, clear=True, capture_stderr=True): @@ -184,7 +184,7 @@ def publish_module(self, domain=None, *, clear=True, capture_stderr=True): capture_stderr=capture_stderr, ) self.resolved_identity = re.search(r"identity: ([0-9a-fA-F]+)", publish_output)[1] - self.address = domain if domain is not None else self.resolved_identity + self.database_identity = domain if domain is not None else self.resolved_identity @classmethod def reset_config(cls): @@ -215,7 +215,7 @@ def subscribe(self, *queries, n): env = os.environ.copy() env["SPACETIME_CONFIG_FILE"] = str(self.config_path) - args = [SPACETIME_BIN, "subscribe", self.address, "-t", "60", "-n", str(n), "--print-initial-update", "--", *queries] + args = [SPACETIME_BIN, "subscribe", self.database_identity, "-t", "60", "-n", str(n), "--print-initial-update", "--", *queries] fake_args = ["spacetime", *args[1:]] log_cmd(fake_args) @@ -273,19 +273,19 @@ def setUpClass(cls): def tearDown(self): # if this single test method published a database, clean it up now - if "address" in self.__dict__: + if "database_identity" in self.__dict__: try: # TODO: save the credentials in publish_module() - self.spacetime("delete", self.address) + self.spacetime("delete", self.database_identity) except Exception: pass @classmethod def tearDownClass(cls): - if hasattr(cls, "address"): + if hasattr(cls, "database_identity"): try: # TODO: save the credentials in publish_module() - cls.spacetime("delete", cls.address) + cls.spacetime("delete", cls.database_identity) except Exception: pass diff --git a/smoketests/tests/auto_migration.py b/smoketests/tests/auto_migration.py index 57900167797..bad7a3d1a8c 100644 --- a/smoketests/tests/auto_migration.py +++ b/smoketests/tests/auto_migration.py @@ -66,7 +66,7 @@ class AddTableAutoMigration(Smoketest): def assertSql(self, sql, expected): self.maxDiff = None - sql_out = self.spacetime("sql", self.address, sql) + sql_out = self.spacetime("sql", self.database_identity, sql) sql_out = "\n".join([line.rstrip() for line in sql_out.splitlines()]) expected = "\n".join([line.rstrip() for line in expected.splitlines()]) self.assertMultiLineEqual(sql_out, expected) @@ -98,7 +98,7 @@ def test_add_table_auto_migration(self): ) self.write_module_code(self.MODULE_CODE_UPDATED) - self.publish_module(self.address, clear=False) + self.publish_module(self.database_identity, clear=False) logging.info("Updated") @@ -176,6 +176,6 @@ def test_reject_schema_changes(self): with self.assertRaises(Exception): self.write_module_code(self.MODULE_CODE_UPDATED) - self.publish_module(self.address, clear=False) + self.publish_module(self.database_identity, clear=False) logging.info("Rejected as expected.") diff --git a/smoketests/tests/describe.py b/smoketests/tests/describe.py index 69be3cb9601..30a5a07317c 100644 --- a/smoketests/tests/describe.py +++ b/smoketests/tests/describe.py @@ -26,6 +26,6 @@ class ModuleDescription(Smoketest): def test_describe(self): """Check describing a module""" - self.spacetime("describe", self.address) - self.spacetime("describe", self.address, "reducer", "say_hello") - self.spacetime("describe", self.address, "table", "person") + self.spacetime("describe", self.database_identity) + self.spacetime("describe", self.database_identity, "reducer", "say_hello") + self.spacetime("describe", self.database_identity, "table", "person") diff --git a/smoketests/tests/domains.py b/smoketests/tests/domains.py index bd72eaabbf1..4b4d39997c0 100644 --- a/smoketests/tests/domains.py +++ b/smoketests/tests/domains.py @@ -42,9 +42,9 @@ def test_set_name(self): rand_name = random_string() self.spacetime("dns", "register-tld", rand_name) - self.spacetime("dns", "set-name", rand_name, self.address) + self.spacetime("dns", "set-name", rand_name, self.database_identity) lookup_result = self.spacetime("dns", "lookup", rand_name).strip() - self.assertEqual(lookup_result, self.address) + self.assertEqual(lookup_result, self.database_identity) - names = self.spacetime("dns", "reverse-lookup", self.address).splitlines() + names = self.spacetime("dns", "reverse-lookup", self.database_identity).splitlines() self.assertIn(rand_name, names) \ No newline at end of file diff --git a/smoketests/tests/new_user_flow.py b/smoketests/tests/new_user_flow.py index 567a77f8e9d..dcfd7f5bb8f 100644 --- a/smoketests/tests/new_user_flow.py +++ b/smoketests/tests/new_user_flow.py @@ -43,7 +43,7 @@ def test_new_user_flow(self): self.assertEqual(self.logs(5).count("Hello, World!"), 2) self.assertEqual(self.logs(5).count("Hello, Tyler!"), 1) - out = self.spacetime("sql", self.address, "SELECT * FROM person") + out = self.spacetime("sql", self.database_identity, "SELECT * FROM person") # The spaces after the name are important self.assertMultiLineEqual(out, """\ name diff --git a/smoketests/tests/permissions.py b/smoketests/tests/permissions.py index df842bb7155..3d145b76716 100644 --- a/smoketests/tests/permissions.py +++ b/smoketests/tests/permissions.py @@ -32,7 +32,7 @@ def test_delete(self): self.reset_config() with self.assertRaises(Exception): - self.spacetime("delete", self.address) + self.spacetime("delete", self.database_identity) def test_describe(self): """Ensure that anyone can describe any database""" @@ -42,7 +42,7 @@ def test_describe(self): self.reset_config() self.new_identity() - self.spacetime("describe", self.address) + self.spacetime("describe", self.database_identity) def test_logs(self): """Ensure that we are not able to view the logs of a module that we don't have permission to view""" @@ -57,7 +57,7 @@ def test_logs(self): self.reset_config() identity = self.new_identity(default=True) with self.assertRaises(Exception): - self.spacetime("logs", self.address, "-n", "10000") + self.spacetime("logs", self.database_identity, "-n", "10000") def test_publish(self): """This test checks to make sure that you cannot publish to an address that you do not own.""" @@ -68,11 +68,11 @@ def test_publish(self): self.reset_config() with self.assertRaises(Exception): - self.spacetime("publish", self.address, "--project-path", self.project_path, "--clear-database", "--yes") + self.spacetime("publish", self.database_identity, "--project-path", self.project_path, "--clear-database", "--yes") # Check that this holds without `--clear-database`, too. with self.assertRaises(Exception): - self.spacetime("publish", self.address, "--project-path", self.project_path) + self.spacetime("publish", self.database_identity, "--project-path", self.project_path) class PrivateTablePermissions(Smoketest): @@ -104,7 +104,7 @@ class PrivateTablePermissions(Smoketest): def test_private_table(self): """Ensure that a private table can only be queried by the database owner""" - out = self.spacetime("sql", self.address, "select * from secret") + out = self.spacetime("sql", self.database_identity, "select * from secret") self.assertMultiLineEqual(out, """\ answer -------- @@ -115,7 +115,7 @@ def test_private_table(self): self.new_identity() with self.assertRaises(Exception): - self.spacetime("sql", self.address, "select * from secret") + self.spacetime("sql", self.database_identity, "select * from secret") with self.assertRaises(Exception): self.subscribe("SELECT * FROM secret", n=0) diff --git a/smoketests/tests/sql.py b/smoketests/tests/sql.py index 6ad8bfa1165..9ba491d9d22 100644 --- a/smoketests/tests/sql.py +++ b/smoketests/tests/sql.py @@ -90,7 +90,7 @@ class SqlFormat(Smoketest): def assertSql(self, sql, expected): self.maxDiff = None - sql_out = self.spacetime("sql", self.address, sql) + sql_out = self.spacetime("sql", self.database_identity, sql) sql_out = "\n".join([line.rstrip() for line in sql_out.splitlines()]) expected = "\n".join([line.rstrip() for line in expected.splitlines()]) self.assertMultiLineEqual(sql_out, expected) diff --git a/smoketests/tests/zz_docker.py b/smoketests/tests/zz_docker.py index 0bb9a452113..a5d236cda67 100644 --- a/smoketests/tests/zz_docker.py +++ b/smoketests/tests/zz_docker.py @@ -130,7 +130,7 @@ def test_restart_module(self): restart_docker() - sql_out = self.spacetime("sql", self.address, "SELECT name FROM person WHERE id = 3") + sql_out = self.spacetime("sql", self.database_identity, "SELECT name FROM person WHERE id = 3") self.assertMultiLineEqual(sql_out, """ name \n------------\n "Samantha" \n""") @requires_docker