Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 161
Enable using VssStore with VssHeaderProvider.#369
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -65,7 +65,9 @@ use bitcoin::secp256k1::PublicKey; | ||
| use bitcoin::{BlockHash, Network}; | ||
| #[cfg(any(vss, vss_test))] | ||
| use bitcoin::bip32::ChildNumber; | ||
| use bitcoin::bip32::{ChildNumber, Xpriv}; | ||
| #[cfg(any(vss, vss_test))] | ||
| use std::collections::HashMap; | ||
| use std::convert::TryInto; | ||
| use std::default::Default; | ||
| use std::fmt; | ||
| @@ -74,6 +76,8 @@ use std::path::PathBuf; | ||
| use std::sync::atomic::AtomicBool; | ||
| use std::sync::{Arc, Mutex, RwLock}; | ||
| use std::time::SystemTime; | ||
| #[cfg(any(vss, vss_test))] | ||
| use vss_client::headers::{FixedHeaders, LnurlAuthToJwtProvider, VssHeaderProvider}; | ||
| #[derive(Debug, Clone)] | ||
| enum ChainDataSourceConfig { | ||
| @@ -357,10 +361,28 @@ impl NodeBuilder { | ||
| self.build_with_store(kv_store) | ||
| } | ||
| /// Builds a [`Node`] instance with a [`VssStore`] backend and according to the options | ||
| /// Builds a [`Node`] instance with a [VSS] backend and according to the options | ||
| /// previously configured. | ||
| /// | ||
| /// Uses [LNURL-auth] based authentication scheme as default method for authentication/authorization. | ||
| /// | ||
| /// The LNURL challenge will be retrieved by making a request to the given `lnurl_auth_server_url`. | ||
| /// The returned JWT token in response to the signed LNURL request, will be used for | ||
| /// authentication/authorization of all the requests made to VSS. | ||
| /// | ||
| /// `fixed_headers` are included as it is in all the requests made to VSS and LNURL auth server. | ||
| /// | ||
| /// **Caution**: VSS support is in **alpha** and is considered experimental. | ||
| /// Using VSS (or any remote persistence) may cause LDK to panic if persistence failures are | ||
| /// unrecoverable, i.e., if they remain unresolved after internal retries are exhausted. | ||
| /// | ||
| /// [VSS]: https://github.com/lightningdevkit/vss-server/blob/main/README.md | ||
| /// [LNURL-auth]: https://github.com/lnurl/luds/blob/luds/04.md | ||
| #[cfg(any(vss, vss_test))] | ||
| pub fn build_with_vss_store(&self, url: String, store_id: String) -> Result<Node, BuildError> { | ||
| pub fn build_with_vss_store( | ||
| &self, vss_url: String, store_id: String, lnurl_auth_server_url: String, | ||
| fixed_headers: HashMap<String, String>, | ||
| ) -> Result<Node, BuildError> { | ||
| use bitcoin::key::Secp256k1; | ||
| let logger = setup_logger(&self.config)?; | ||
| @@ -370,23 +392,81 @@ impl NodeBuilder { | ||
| self.entropy_source_config.as_ref(), | ||
| Arc::clone(&logger), | ||
| )?; | ||
| let config = Arc::new(self.config.clone()); | ||
| let xprv = bitcoin::bip32::Xpriv::new_master(config.network, &seed_bytes).map_err(|e| { | ||
| log_error!(logger, "Failed to derive master secret: {}", e); | ||
| BuildError::InvalidSeedBytes | ||
| })?; | ||
| let vss_xprv = derive_vss_xprv(config, &seed_bytes, Arc::clone(&logger))?; | ||
| let vss_xprv = xprv | ||
| .derive_priv(&Secp256k1::new(), &[ChildNumber::Hardened { index: 877 }]) | ||
| let lnurl_auth_xprv = vss_xprv | ||
| .derive_priv(&Secp256k1::new(), &[ChildNumber::Hardened { index: 138 }]) | ||
tnull marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| .map_err(|e| { | ||
| log_error!(logger, "Failed to derive VSS secret: {}", e); | ||
| BuildError::KVStoreSetupFailed | ||
| })?; | ||
| let lnurl_auth_jwt_provider = | ||
| LnurlAuthToJwtProvider::new(lnurl_auth_xprv, lnurl_auth_server_url, fixed_headers) | ||
G8XSU marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| .map_err(|e| { | ||
| log_error!(logger, "Failed to create LnurlAuthToJwtProvider: {}", e); | ||
| BuildError::KVStoreSetupFailed | ||
| })?; | ||
| let header_provider = Arc::new(lnurl_auth_jwt_provider); | ||
| self.build_with_vss_store_and_header_provider(vss_url, store_id, header_provider) | ||
| } | ||
| /// Builds a [`Node`] instance with a [VSS] backend and according to the options | ||
| /// previously configured. | ||
| /// | ||
| /// Uses [`FixedHeaders`] as default method for authentication/authorization. | ||
| /// | ||
| /// Given `fixed_headers` are included as it is in all the requests made to VSS. | ||
| /// | ||
| /// **Caution**: VSS support is in **alpha** and is considered experimental. | ||
| /// Using VSS (or any remote persistence) may cause LDK to panic if persistence failures are | ||
| /// unrecoverable, i.e., if they remain unresolved after internal retries are exhausted. | ||
| /// | ||
| /// [VSS]: https://github.com/lightningdevkit/vss-server/blob/main/README.md | ||
| #[cfg(any(vss, vss_test))] | ||
| pub fn build_with_vss_store_and_fixed_headers( | ||
| &self, vss_url: String, store_id: String, fixed_headers: HashMap<String, String>, | ||
| ) -> Result<Node, BuildError> { | ||
| let header_provider = Arc::new(FixedHeaders::new(fixed_headers)); | ||
| self.build_with_vss_store_and_header_provider(vss_url, store_id, header_provider) | ||
| } | ||
| /// Builds a [`Node`] instance with a [VSS] backend and according to the options | ||
| /// previously configured. | ||
| /// | ||
| /// Given `header_provider` is used to attach headers to every request made | ||
| /// to VSS. | ||
| /// | ||
| /// **Caution**: VSS support is in **alpha** and is considered experimental. | ||
| /// Using VSS (or any remote persistence) may cause LDK to panic if persistence failures are | ||
| /// unrecoverable, i.e., if they remain unresolved after internal retries are exhausted. | ||
| /// | ||
| /// [VSS]: https://github.com/lightningdevkit/vss-server/blob/main/README.md | ||
| #[cfg(any(vss, vss_test))] | ||
| pub fn build_with_vss_store_and_header_provider( | ||
G8XSU marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| &self, vss_url: String, store_id: String, header_provider: Arc<dyn VssHeaderProvider>, | ||
| ) -> Result<Node, BuildError> { | ||
| let logger = setup_logger(&self.config)?; | ||
| let seed_bytes = seed_bytes_from_config( | ||
| &self.config, | ||
| self.entropy_source_config.as_ref(), | ||
| Arc::clone(&logger), | ||
| )?; | ||
| let config = Arc::new(self.config.clone()); | ||
tnull marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| let vss_xprv = derive_vss_xprv(config.clone(), &seed_bytes, Arc::clone(&logger))?; | ||
| let vss_seed_bytes: [u8; 32] = vss_xprv.private_key.secret_bytes(); | ||
| let vss_store = Arc::new(VssStore::new(url, store_id, vss_seed_bytes)); | ||
| let vss_store = Arc::new(VssStore::new(vss_url, store_id, vss_seed_bytes, header_provider)); | ||
| build_with_store_internal( | ||
| config, | ||
| self.chain_data_source_config.as_ref(), | ||
| @@ -551,6 +631,80 @@ impl ArcedNodeBuilder { | ||
| self.inner.read().unwrap().build_with_fs_store().map(Arc::new) | ||
| } | ||
| /// Builds a [`Node`] instance with a [VSS] backend and according to the options | ||
| /// previously configured. | ||
| /// | ||
| /// Uses [LNURL-auth] based authentication scheme as default method for authentication/authorization. | ||
| /// | ||
| /// The LNURL challenge will be retrieved by making a request to the given `lnurl_auth_server_url`. | ||
| /// The returned JWT token in response to the signed LNURL request, will be used for | ||
| /// authentication/authorization of all the requests made to VSS. | ||
| /// | ||
| /// `fixed_headers` are included as it is in all the requests made to VSS and LNURL auth server. | ||
| /// | ||
| /// **Caution**: VSS support is in **alpha** and is considered experimental. | ||
| /// Using VSS (or any remote persistence) may cause LDK to panic if persistence failures are | ||
| /// unrecoverable, i.e., if they remain unresolved after internal retries are exhausted. | ||
| /// | ||
| /// [VSS]: https://github.com/lightningdevkit/vss-server/blob/main/README.md | ||
| /// [LNURL-auth]: https://github.com/lnurl/luds/blob/luds/04.md | ||
| #[cfg(any(vss, vss_test))] | ||
| pub fn build_with_vss_store( | ||
| &self, vss_url: String, store_id: String, lnurl_auth_server_url: String, | ||
| fixed_headers: HashMap<String, String>, | ||
| ) -> Result<Arc<Node>, BuildError> { | ||
| self.inner | ||
| .read() | ||
| .unwrap() | ||
| .build_with_vss_store(vss_url, store_id, lnurl_auth_server_url, fixed_headers) | ||
| .map(Arc::new) | ||
| } | ||
| /// Builds a [`Node`] instance with a [VSS] backend and according to the options | ||
| /// previously configured. | ||
| /// | ||
| /// Uses [`FixedHeaders`] as default method for authentication/authorization. | ||
| /// | ||
| /// Given `fixed_headers` are included as it is in all the requests made to VSS. | ||
| /// | ||
| /// **Caution**: VSS support is in **alpha** and is considered experimental. | ||
| /// Using VSS (or any remote persistence) may cause LDK to panic if persistence failures are | ||
| /// unrecoverable, i.e., if they remain unresolved after internal retries are exhausted. | ||
| /// | ||
| /// [VSS]: https://github.com/lightningdevkit/vss-server/blob/main/README.md | ||
| #[cfg(any(vss, vss_test))] | ||
| pub fn build_with_vss_store_and_fixed_headers( | ||
| &self, vss_url: String, store_id: String, fixed_headers: HashMap<String, String>, | ||
| ) -> Result<Arc<Node>, BuildError> { | ||
| self.inner | ||
| .read() | ||
| .unwrap() | ||
| .build_with_vss_store_and_fixed_headers(vss_url, store_id, fixed_headers) | ||
| .map(Arc::new) | ||
| } | ||
| /// Builds a [`Node`] instance with a [VSS] backend and according to the options | ||
| /// previously configured. | ||
| /// | ||
| /// Given `header_provider` is used to attach headers to every request made | ||
| /// to VSS. | ||
| /// | ||
| /// **Caution**: VSS support is in **alpha** and is considered experimental. | ||
| /// Using VSS (or any remote persistence) may cause LDK to panic if persistence failures are | ||
| /// unrecoverable, i.e., if they remain unresolved after internal retries are exhausted. | ||
| /// | ||
| /// [VSS]: https://github.com/lightningdevkit/vss-server/blob/main/README.md | ||
| #[cfg(any(vss, vss_test))] | ||
| pub fn build_with_vss_store_and_header_provider( | ||
| &self, vss_url: String, store_id: String, header_provider: Arc<dyn VssHeaderProvider>, | ||
| ) -> Result<Arc<Node>, BuildError> { | ||
| self.inner | ||
| .read() | ||
| .unwrap() | ||
| .build_with_vss_store_and_header_provider(vss_url, store_id, header_provider) | ||
| .map(Arc::new) | ||
| } | ||
| /// Builds a [`Node`] instance according to the options previously configured. | ||
| pub fn build_with_store(&self, kv_store: Arc<DynStore>) -> Result<Arc<Node>, BuildError> { | ||
| self.inner.read().unwrap().build_with_store(kv_store).map(Arc::new) | ||
| @@ -1079,6 +1233,23 @@ fn seed_bytes_from_config( | ||
| } | ||
| } | ||
| #[cfg(any(vss, vss_test))] | ||
| fn derive_vss_xprv( | ||
| config: Arc<Config>, seed_bytes: &[u8; 64], logger: Arc<FilesystemLogger>, | ||
| ) -> Result<Xpriv, BuildError> { | ||
| use bitcoin::key::Secp256k1; | ||
| let xprv = Xpriv::new_master(config.network, seed_bytes).map_err(|e| { | ||
| log_error!(logger, "Failed to derive master secret: {}", e); | ||
| BuildError::InvalidSeedBytes | ||
| })?; | ||
| xprv.derive_priv(&Secp256k1::new(), &[ChildNumber::Hardened { index: 877 }]).map_err(|e| { | ||
| log_error!(logger, "Failed to derive VSS secret: {}", e); | ||
| BuildError::KVStoreSetupFailed | ||
| }) | ||
| } | ||
| /// Sanitize the user-provided node alias to ensure that it is a valid protocol-specified UTF-8 string. | ||
| pub(crate) fn sanitize_alias(alias_str: &str) -> Result<NodeAlias, BuildError> { | ||
| let alias = alias_str.trim(); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -8,6 +8,7 @@ | ||
| use lightning::io::{self, Error, ErrorKind}; | ||
| #[cfg(test)] | ||
| use std::panic::RefUnwindSafe; | ||
| use std::sync::Arc; | ||
| use std::time::Duration; | ||
| use crate::io::utils::check_namespace_key_validity; | ||
| @@ -17,6 +18,7 @@ use rand::RngCore; | ||
| use tokio::runtime::Runtime; | ||
| use vss_client::client::VssClient; | ||
| use vss_client::error::VssError; | ||
| use vss_client::headers::VssHeaderProvider; | ||
| use vss_client::types::{ | ||
| DeleteObjectRequest, GetObjectRequest, KeyValue, ListKeyVersionsRequest, PutObjectRequest, | ||
| Storable, | ||
| @@ -43,7 +45,10 @@ pub struct VssStore { | ||
| } | ||
| impl VssStore { | ||
| pub(crate) fn new(base_url: String, store_id: String, data_encryption_key: [u8; 32]) -> Self { | ||
| pub(crate) fn new( | ||
| base_url: String, store_id: String, data_encryption_key: [u8; 32], | ||
| header_provider: Arc<dyn VssHeaderProvider>, | ||
G8XSU marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| ) -> Self { | ||
| let runtime = tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap(); | ||
| let storable_builder = StorableBuilder::new(data_encryption_key, RandEntropySource); | ||
| let retry_policy = ExponentialBackoffRetryPolicy::new(Duration::from_millis(100)) | ||
| @@ -59,7 +64,7 @@ impl VssStore { | ||
| ) | ||
| }) as _); | ||
| let client = VssClient::new(base_url, retry_policy); | ||
| let client = VssClient::new_with_headers(base_url, retry_policy, header_provider); | ||
| Self { client, store_id, runtime, storable_builder } | ||
| } | ||
| @@ -238,6 +243,8 @@ mod tests { | ||
| use crate::io::test_utils::do_read_write_remove_list_persist; | ||
| use rand::distributions::Alphanumeric; | ||
| use rand::{thread_rng, Rng, RngCore}; | ||
| use std::collections::HashMap; | ||
| use vss_client::headers::FixedHeaders; | ||
| #[test] | ||
| fn read_write_remove_list_persist() { | ||
| @@ -246,7 +253,9 @@ mod tests { | ||
| let rand_store_id: String = (0..7).map(|_| rng.sample(Alphanumeric) as char).collect(); | ||
| let mut data_encryption_key = [0u8; 32]; | ||
| rng.fill_bytes(&mut data_encryption_key); | ||
| let vss_store = VssStore::new(vss_base_url, rand_store_id, data_encryption_key); | ||
| let header_provider = Arc::new(FixedHeaders::new(HashMap::new())); | ||
| let vss_store = | ||
| VssStore::new(vss_base_url, rand_store_id, data_encryption_key, header_provider); | ||
| do_read_write_remove_list_persist(&vss_store); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.