vls_frontend/external_persist/
lss.rs1use super::{Error, ExternalPersist, Info};
2use async_trait::async_trait;
3use bitcoin::PublicKey;
4use lightning_signer::bitcoin;
5use lightning_signer::persist::Mutations;
6use lightning_storage_server::client::{Auth as LssAuth, Client as LssClient, ClientError};
7use lightning_storage_server::Value as LssValue;
8use log::error;
9use tokio::sync::Mutex;
10
11impl From<ClientError> for Error {
12 fn from(e: ClientError) -> Self {
13 match e {
14 ClientError::Connect(e) => {
15 error!("LSS connect error: {}", e);
16 Error::NotAvailable
17 }
18 ClientError::Tonic(e) => {
19 error!("LSS transport error: {}", e);
20 Error::NotAvailable
21 }
22 ClientError::InvalidResponse => {
23 error!("LSS invalid response");
24 Error::NotAvailable
25 }
26 ClientError::InvalidHmac(key, value) => {
27 error!("LSS invalid HMAC for key {} version {}", key, value);
28 Error::NotAuthorized
29 }
30 ClientError::InvalidServerHmac() => {
31 error!("LSS invalid server HMAC");
32 Error::NotAuthorized
33 }
34 ClientError::PutConflict(c) => {
35 error!("LSS put conflict: {:?}", c);
36 Error::Conflicts(c.into_iter().map(|(k, v)| (k, v.version as u64)).collect())
37 }
38 }
39 }
40}
41
42pub struct Client {
44 client: Mutex<LssClient>,
45 server_public_key: PublicKey,
46 uri: String,
47}
48
49impl Client {
50 pub async fn get_server_pubkey(uri: &str) -> Result<PublicKey, Error> {
57 let pubkey = LssClient::get_info(uri).await?.0;
58 Ok(PublicKey::new(pubkey))
59 }
60
61 pub async fn new(
69 uri: &str,
70 server_public_key: &PublicKey,
71 auth: LssAuth,
72 ) -> Result<Self, Error> {
73 let (pubkey, _version) = LssClient::get_info(uri).await?;
74
75 assert_eq!(pubkey, server_public_key.inner, "server public key mismatch");
76 let client = LssClient::new(uri, auth).await?;
77 Ok(Self {
78 client: Mutex::new(client),
79 server_public_key: server_public_key.clone(),
80 uri: uri.to_string(),
81 })
82 }
83}
84
85#[async_trait]
86impl ExternalPersist for Client {
87 async fn put(&self, mutations: Mutations, client_hmac: &[u8]) -> Result<Vec<u8>, Error> {
88 let mut client = self.client.lock().await;
89 let kvs = mutations
90 .into_iter()
91 .map(|(k, (version, value))| (k, LssValue { version: version as i64, value }))
92 .collect();
93 let server_hmac = client.put(kvs, client_hmac).await?;
94 Ok(server_hmac)
95 }
96
97 async fn get(&self, key_prefix: String, nonce: &[u8]) -> Result<(Mutations, Vec<u8>), Error> {
98 let mut client = self.client.lock().await;
99 let (kvs, received_hmac) = client.get(key_prefix, nonce).await?;
100 let mutations = Mutations::from_vec(
101 kvs.into_iter().map(|(k, v)| (k, (v.version as u64, v.value))).collect(),
102 );
103 Ok((mutations, received_hmac))
104 }
105
106 async fn info(&self) -> Result<Info, Error> {
107 let (server_public_key, version) = LssClient::get_info(&self.uri).await?;
108 assert_eq!(self.server_public_key.inner, server_public_key, "server public key mismatch");
109
110 Ok(Info { version, pubkey: server_public_key.clone() })
111 }
112}