nym_credential_proxy_lib/storage/
models.rs

1// Copyright 2024 Nym Technologies SA <contact@nymtech.net>
2// SPDX-License-Identifier: GPL-3.0-only
3
4use nym_crypto::asymmetric::ed25519;
5use serde::{Deserialize, Serialize};
6use sqlx::sqlite::SqliteRow;
7use sqlx::{FromRow, Row, Type};
8use strum_macros::{Display, EnumString};
9use time::{Date, OffsetDateTime};
10use zeroize::Zeroizing;
11
12pub(crate) struct StorableEcashDeposit {
13    pub(crate) deposit_id: u32,
14    pub(crate) deposit_tx_hash: String,
15    pub(crate) requested_on: OffsetDateTime,
16    pub(crate) deposit_amount: String,
17    pub(crate) ed25519_deposit_private_key: Zeroizing<[u8; ed25519::SECRET_KEY_LENGTH]>,
18}
19
20impl<'r> FromRow<'r, SqliteRow> for StorableEcashDeposit {
21    fn from_row(row: &'r SqliteRow) -> Result<Self, sqlx::Error> {
22        let deposit_id = row.try_get("deposit_id")?;
23        let deposit_tx_hash = row.try_get("deposit_tx_hash")?;
24        let requested_on = row.try_get("requested_on")?;
25        let deposit_amount = row.try_get("deposit_amount")?;
26        let ed25519_deposit_private_key: Vec<u8> = row.try_get("ed25519_deposit_private_key")?;
27        if ed25519_deposit_private_key.len() != ed25519::SECRET_KEY_LENGTH {
28            return Err(sqlx::Error::decode(
29                "stored ed25519_deposit_private_key has invalid length",
30            ));
31        }
32
33        // SAFETY: we just checked the length is correct
34        #[allow(clippy::unwrap_used)]
35        let ed25519_deposit_private_key: [u8; ed25519::SECRET_KEY_LENGTH] =
36            ed25519_deposit_private_key.try_into().unwrap();
37
38        Ok(StorableEcashDeposit {
39            deposit_id,
40            deposit_tx_hash,
41            requested_on,
42            deposit_amount,
43            ed25519_deposit_private_key: Zeroizing::new(ed25519_deposit_private_key),
44        })
45    }
46}
47
48#[derive(Serialize, Deserialize, Debug, Clone, EnumString, Type, PartialEq, Display)]
49#[sqlx(rename_all = "snake_case")]
50#[strum(serialize_all = "snake_case")]
51pub enum BlindedSharesStatus {
52    Pending,
53    Issued,
54    Error,
55}
56
57#[derive(Serialize, Deserialize, Debug, Clone, FromRow)]
58pub struct BlindedShares {
59    pub id: i64,
60    pub request_uuid: String,
61    pub status: BlindedSharesStatus,
62    pub device_id: String,
63    pub credential_id: String,
64    pub available_shares: i64,
65    pub error_message: Option<String>,
66    pub created: OffsetDateTime,
67    pub updated: OffsetDateTime,
68}
69
70#[derive(FromRow)]
71pub struct RawExpirationDateSignatures {
72    pub serialised_signatures: Vec<u8>,
73    pub serialization_revision: u8,
74}
75
76#[derive(FromRow)]
77pub struct RawCoinIndexSignatures {
78    #[allow(dead_code)]
79    pub epoch_id: u32,
80    pub serialised_signatures: Vec<u8>,
81    pub serialization_revision: u8,
82}
83
84#[derive(FromRow)]
85pub struct RawVerificationKey {
86    #[allow(dead_code)]
87    pub epoch_id: u32,
88    pub serialised_key: Vec<u8>,
89    pub serialization_revision: u8,
90}
91
92#[derive(FromRow)]
93pub struct WalletShare {
94    #[allow(dead_code)]
95    pub corresponding_deposit: i64,
96    pub node_id: i64,
97    #[allow(dead_code)]
98    pub created: OffsetDateTime,
99    pub blinded_signature: Vec<u8>,
100}
101
102#[derive(FromRow)]
103pub struct MinimalWalletShare {
104    pub epoch_id: i64,
105    pub expiration_date: Date,
106    pub node_id: i64,
107    pub blinded_signature: Vec<u8>,
108}
109
110impl From<MinimalWalletShare>
111    for nym_credential_proxy_requests::api::v1::ticketbook::models::WalletShare
112{
113    fn from(value: MinimalWalletShare) -> Self {
114        nym_credential_proxy_requests::api::v1::ticketbook::models::WalletShare {
115            node_index: value.node_id as u64,
116            bs58_encoded_share: bs58::encode(&value.blinded_signature).into_string(),
117        }
118    }
119}