feat(server): introducle table separation in preparation of shamir secret sharing vault

This commit is contained in:
Skipper
2026-04-19 14:04:27 +02:00
parent 2b44570ab4
commit 5f239c426d
9 changed files with 85 additions and 35 deletions

View File

@@ -50,6 +50,7 @@ subtle = "2.6.1"
x25519-dalek.workspace = true
k256.workspace = true
kameo_actors.workspace = true
blahaj = "0.6.0"
[dev-dependencies]
proptest = "1.11.0"

View File

@@ -43,13 +43,25 @@ create table if not exists arbiter_settings (
insert into arbiter_settings (id) values (1) on conflict do nothing;
-- ensure singleton row exists
create table if not exists operator_client (
create table if not exists operator_identity (
id integer not null primary key,
public_key blob not null,
created_at integer not null default(unixepoch ('now')),
updated_at integer not null default(unixepoch ('now'))
) STRICT;
create unique index if not exists uniq_operator_client_public_key on operator_client (public_key);
create unique index if not exists uniq_operator_client_public_key on operator_identity (public_key);
create table if not exists operator (
id integer primary key references operator_identity(id) on delete restrict, -- same id as operator_identity
share blob not null,
share_nonce blob not null,
created_at integer not null default(unixepoch ('now')),
updated_at integer not null default(unixepoch ('now'))
) STRICT;
create table if not exists client_metadata (
id integer not null primary key,

View File

@@ -48,7 +48,7 @@ impl Bootstrapper {
let row_count: i64 = {
let mut conn = db.get().await?;
schema::operator_client::table
schema::operator_identity::table
.count()
.get_result(&mut conn)
.await?

View File

@@ -248,14 +248,25 @@ pub struct ProgramClient {
}
#[derive(Queryable, Debug)]
#[diesel(table_name = schema::operator_client, check_for_backend(Sqlite))]
pub struct OperatorClient {
#[diesel(table_name = schema::operator_identity, check_for_backend(Sqlite))]
pub struct OperatorIdentity {
pub id: i32,
pub public_key: Vec<u8>,
pub created_at: SqliteTimestamp,
pub updated_at: SqliteTimestamp,
}
#[derive(Queryable, Debug)]
#[diesel(table_name = schema::operator, check_for_backend(Sqlite))]
pub struct Operator {
pub id: i32,
pub share: Vec<u8>,
pub share_nonce: Vec<u8>,
pub created_at: SqliteTimestamp,
pub updated_at: SqliteTimestamp,
}
#[derive(Models, Queryable, Debug, Insertable, Selectable)]
#[diesel(table_name = evm_ether_transfer_limit, check_for_backend(Sqlite))]
#[view(

View File

@@ -152,6 +152,25 @@ diesel::table! {
}
}
diesel::table! {
operator (id) {
id -> Nullable<Integer>,
share -> Binary,
share_nonce -> Binary,
created_at -> Integer,
updated_at -> Integer,
}
}
diesel::table! {
operator_identity (id) {
id -> Integer,
public_key -> Binary,
created_at -> Integer,
updated_at -> Integer,
}
}
diesel::table! {
program_client (id) {
id -> Integer,
@@ -185,15 +204,6 @@ diesel::table! {
}
}
diesel::table! {
operator_client (id) {
id -> Integer,
public_key -> Binary,
created_at -> Integer,
updated_at -> Integer,
}
}
diesel::joinable!(aead_encrypted -> root_key_history (associated_root_key_id));
diesel::joinable!(arbiter_settings -> root_key_history (root_key_id));
diesel::joinable!(arbiter_settings -> tls_history (tls_id));
@@ -212,6 +222,7 @@ diesel::joinable!(evm_transaction_log -> evm_wallet_access (wallet_access_id));
diesel::joinable!(evm_wallet -> aead_encrypted (aead_encrypted_id));
diesel::joinable!(evm_wallet_access -> evm_wallet (wallet_id));
diesel::joinable!(evm_wallet_access -> program_client (client_id));
diesel::joinable!(operator -> operator_identity (id));
diesel::joinable!(program_client -> client_metadata (metadata_id));
diesel::allow_tables_to_appear_in_same_query!(
@@ -230,8 +241,9 @@ diesel::allow_tables_to_appear_in_same_query!(
evm_wallet,
evm_wallet_access,
integrity_envelope,
operator,
operator_identity,
program_client,
root_key_history,
tls_history,
operator_client,
);

View File

@@ -4,7 +4,7 @@ use super::{
};
use crate::{
actors::bootstrap::ConsumeToken,
db::{DatabasePool, schema::operator_client},
db::{DatabasePool, schema::operator_identity},
peers::operator::auth::Outbound,
};
use arbiter_crypto::authn::{self, AuthChallenge, OPERATOR_CONTEXT};
@@ -44,9 +44,9 @@ async fn get_client_id(db: &DatabasePool, pubkey: &authn::PublicKey) -> Result<O
Error::internal("Database unavailable")
})?;
operator_client::table
.filter(operator_client::public_key.eq(pubkey.to_bytes()))
.select(operator_client::id)
operator_identity::table
.filter(operator_identity::public_key.eq(pubkey.to_bytes()))
.select(operator_identity::id)
.first::<i32>(&mut conn)
.await
.optional()
@@ -63,9 +63,9 @@ async fn register_key(db: &DatabasePool, pubkey: &authn::PublicKey) -> Result<i3
Error::internal("Database unavailable")
})?;
let id: i32 = diesel::insert_into(operator_client::table)
.values((operator_client::public_key.eq(pubkey_bytes),))
.returning(operator_client::id)
let id: i32 = diesel::insert_into(operator_identity::table)
.values((operator_identity::public_key.eq(pubkey_bytes),))
.returning(operator_identity::id)
.get_result(&mut conn)
.await
.map_err(|e| {

View File

@@ -86,8 +86,8 @@ async fn insert_bootstrap_sentinel_operator(db: &db::DatabasePool) {
.0
.to_vec();
insert_into(schema::operator_client::table)
.values((schema::operator_client::public_key.eq(sentinel_key),))
insert_into(schema::operator_identity::table)
.values((schema::operator_identity::public_key.eq(sentinel_key),))
.execute(&mut conn)
.await
.unwrap();

View File

@@ -206,8 +206,8 @@ pub async fn bootstrap_token_auth() {
task.await.unwrap().unwrap();
let mut conn = db.get().await.unwrap();
let stored_pubkey: Vec<u8> = schema::operator_client::table
.select(schema::operator_client::public_key)
let stored_pubkey: Vec<u8> = schema::operator_identity::table
.select(schema::operator_identity::public_key)
.first::<Vec<u8>>(&mut conn)
.await
.unwrap();
@@ -259,7 +259,7 @@ pub async fn bootstrap_invalid_token_auth() {
));
let mut conn = db.get().await.unwrap();
let count: i64 = schema::operator_client::table
let count: i64 = schema::operator_identity::table
.count()
.get_result::<i64>(&mut conn)
.await
@@ -285,9 +285,9 @@ pub async fn challenge_auth() {
{
let mut conn = db.get().await.unwrap();
let id: i32 = insert_into(schema::operator_client::table)
.values((schema::operator_client::public_key.eq(pubkey_bytes.clone()),))
.returning(schema::operator_client::id)
let id: i32 = insert_into(schema::operator_identity::table)
.values((schema::operator_identity::public_key.eq(pubkey_bytes.clone()),))
.returning(schema::operator_identity::id)
.get_result(&mut conn)
.await
.unwrap();
@@ -371,8 +371,8 @@ pub async fn challenge_auth_rejects_integrity_tag_mismatch_when_unsealed() {
{
let mut conn = db.get().await.unwrap();
insert_into(schema::operator_client::table)
.values((schema::operator_client::public_key.eq(pubkey_bytes.clone()),))
insert_into(schema::operator_identity::table)
.values((schema::operator_identity::public_key.eq(pubkey_bytes.clone()),))
.execute(&mut conn)
.await
.unwrap();
@@ -444,9 +444,9 @@ pub async fn challenge_auth_rejects_invalid_signature() {
{
let mut conn = db.get().await.unwrap();
let id: i32 = insert_into(schema::operator_client::table)
.values((schema::operator_client::public_key.eq(pubkey_bytes.clone()),))
.returning(schema::operator_client::id)
let id: i32 = insert_into(schema::operator_identity::table)
.values((schema::operator_identity::public_key.eq(pubkey_bytes.clone()),))
.returning(schema::operator_identity::id)
.get_result(&mut conn)
.await
.unwrap();