Skip to main content

p2panda_store/key_registry/
sqlite.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3use p2panda_core::VerifyingKey;
4use p2panda_core::cbor::{decode_cbor, encode_cbor};
5use p2panda_encryption::key_registry::KeyRegistryState;
6use sqlx::{query, query_scalar};
7
8use crate::key_registry::traits::KeyRegistryStore;
9use crate::{SqliteError, SqliteStore};
10
11// Constant identifier used to provide a primary key for the database table.
12// This makes it possible to use INSERT OR REPLACE to update the key registry state.
13const DEFAULT_KEY_REGISTRY: &str = "default";
14
15impl KeyRegistryStore for SqliteStore {
16    type Error = SqliteError;
17
18    async fn get_key_registry(
19        &self,
20    ) -> Result<Option<KeyRegistryState<VerifyingKey>>, Self::Error> {
21        let state_bytes: Option<Vec<u8>> = self
22            .execute(async |pool| {
23                query_scalar(
24                    "
25                    SELECT
26                        state
27                    FROM
28                        key_registry_v1
29                    WHERE
30                        id = ?
31                    ",
32                )
33                .bind(DEFAULT_KEY_REGISTRY)
34                .fetch_optional(pool)
35                .await
36                .map_err(SqliteError::Sqlite)
37            })
38            .await?;
39
40        if let Some(bytes) = state_bytes {
41            let state = decode_cbor(&bytes[..])
42                .map_err(|err| SqliteError::Decode("state".into(), err.into()))?;
43            Ok(Some(state))
44        } else {
45            Ok(None)
46        }
47    }
48
49    async fn set_key_registry(
50        &self,
51        state: &KeyRegistryState<VerifyingKey>,
52    ) -> Result<(), Self::Error> {
53        self.tx(async |tx| {
54            query(
55                "
56                INSERT OR REPLACE
57                    INTO
58                        key_registry_v1(id, state)
59                    VALUES
60                        (?, ?)
61                ",
62            )
63            .bind(DEFAULT_KEY_REGISTRY)
64            .bind(encode_cbor(&state).map_err(|err| SqliteError::Encode("state".to_string(), err))?)
65            .execute(&mut **tx)
66            .await
67            .map_err(SqliteError::Sqlite)
68        })
69        .await?;
70
71        Ok(())
72    }
73}