Skip to content

Commit 3eb5ebe

Browse files
committed
Expose KVStoreBuilder.
We allow users to build KVStore by exposing KVStoreBuilder, this also enables user to execute simple utility methods for KVStore migrations.
1 parent 0a911f0 commit 3eb5ebe

File tree

1 file changed

+143
-1
lines changed

1 file changed

+143
-1
lines changed

src/builder.rs

Lines changed: 143 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ use lightning::routing::scoring::{
4646
use lightning::sign::EntropySource;
4747

4848
use lightning::util::persist::{
49-
read_channel_monitors, CHANNEL_MANAGER_PERSISTENCE_KEY,
49+
read_channel_monitors, KVStore, CHANNEL_MANAGER_PERSISTENCE_KEY,
5050
CHANNEL_MANAGER_PERSISTENCE_PRIMARY_NAMESPACE, CHANNEL_MANAGER_PERSISTENCE_SECONDARY_NAMESPACE,
5151
};
5252
use lightning::util::ser::ReadableArgs;
@@ -579,6 +579,148 @@ impl NodeBuilder {
579579
}
580580
}
581581

582+
#[derive(Debug)]
583+
pub struct KVStoreBuilder {
584+
config: Config,
585+
entropy_source_config: Option<EntropySourceConfig>,
586+
log_writer_config: Option<LogWriterConfig>,
587+
}
588+
589+
impl KVStoreBuilder {
590+
/// Creates a new builder instance with the default configuration.
591+
pub fn new() -> Self {
592+
let config = Config::default();
593+
Self::from_config(config)
594+
}
595+
596+
/// Creates a new builder instance from an [`Config`].
597+
pub fn from_config(config: Config) -> Self {
598+
let entropy_source_config = None;
599+
let log_writer_config = None;
600+
Self { config, entropy_source_config, log_writer_config }
601+
}
602+
603+
//TODO: I think these methods should be extracted out to EntropySourceConfigBuilder. Both NodeBuilder
604+
// and KVStoreBuilder can directly take EntropySourceConfig as arg.
605+
/// Configures the builder instance to source its entropy from a seed file on disk.
606+
///
607+
/// If the given file does not exist a new random seed file will be generated and
608+
/// stored at the given location.
609+
pub fn set_entropy_seed_path(&mut self, seed_path: String) -> &mut Self {
610+
self.entropy_source_config = Some(EntropySourceConfig::SeedFile(seed_path));
611+
self
612+
}
613+
614+
/// Configures the builder instance to source its entropy from the given 64 seed bytes.
615+
pub fn set_entropy_seed_bytes(&mut self, seed_bytes: Vec<u8>) -> Result<&mut Self, BuildError> {
616+
if seed_bytes.len() != WALLET_KEYS_SEED_LEN {
617+
return Err(BuildError::InvalidSeedBytes);
618+
}
619+
let mut bytes = [0u8; WALLET_KEYS_SEED_LEN];
620+
bytes.copy_from_slice(&seed_bytes);
621+
self.entropy_source_config = Some(EntropySourceConfig::SeedBytes(bytes));
622+
Ok(self)
623+
}
624+
625+
/// Configures the builder instance to source its entropy from a [BIP 39] mnemonic.
626+
///
627+
/// [BIP 39]: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
628+
pub fn set_entropy_bip39_mnemonic(
629+
&mut self, mnemonic: Mnemonic, passphrase: Option<String>,
630+
) -> &mut Self {
631+
self.entropy_source_config =
632+
Some(EntropySourceConfig::Bip39Mnemonic { mnemonic, passphrase });
633+
self
634+
}
635+
636+
//TODO: Once we have KVStoreBuilder, we can have NodeBuilder directly take Arc<dyn KVStore> as arg.
637+
/// Builds a [`VssStore`] backend based implementation of [`KVStore`].
638+
pub fn build_vss_store(
639+
&self, vss_url: String, store_id: String, lnurl_auth_server_url: String,
640+
fixed_headers: HashMap<String, String>,
641+
) -> Result<VssStore, BuildError> {
642+
use bitcoin::key::Secp256k1;
643+
644+
let logger = setup_logger(&self.log_writer_config, &self.config)?;
645+
646+
let seed_bytes = seed_bytes_from_config(
647+
&self.config,
648+
self.entropy_source_config.as_ref(),
649+
Arc::clone(&logger),
650+
)?;
651+
652+
let config = Arc::new(self.config.clone());
653+
654+
let vss_xprv = derive_vss_xprv(config, &seed_bytes, Arc::clone(&logger))?;
655+
656+
let lnurl_auth_xprv = vss_xprv
657+
.derive_priv(&Secp256k1::new(), &[ChildNumber::Hardened { index: 138 }])
658+
.map_err(|e| {
659+
log_error!(logger, "Failed to derive VSS secret: {}", e);
660+
BuildError::KVStoreSetupFailed
661+
})?;
662+
663+
let lnurl_auth_jwt_provider =
664+
LnurlAuthToJwtProvider::new(lnurl_auth_xprv, lnurl_auth_server_url, fixed_headers)
665+
.map_err(|e| {
666+
log_error!(logger, "Failed to create LnurlAuthToJwtProvider: {}", e);
667+
BuildError::KVStoreSetupFailed
668+
})?;
669+
670+
let header_provider = Arc::new(lnurl_auth_jwt_provider);
671+
672+
self.build_vss_store_with_header_provider(vss_url, store_id, header_provider)
673+
}
674+
675+
/// Builds a [`VssStore`] backend based implementation of [`KVStore`].
676+
pub fn build_vss_store_with_header_provider(
677+
&self, vss_url: String, store_id: String, header_provider: Arc<dyn VssHeaderProvider>,
678+
) -> Result<VssStore, BuildError> {
679+
let logger = setup_logger(&self.log_writer_config, &self.config)?;
680+
681+
let seed_bytes = seed_bytes_from_config(
682+
&self.config,
683+
self.entropy_source_config.as_ref(),
684+
Arc::clone(&logger),
685+
)?;
686+
687+
let config = Arc::new(self.config.clone());
688+
689+
let vss_xprv = derive_vss_xprv(config.clone(), &seed_bytes, Arc::clone(&logger))?;
690+
691+
let vss_seed_bytes: [u8; 32] = vss_xprv.private_key.secret_bytes();
692+
693+
Ok(VssStore::new(vss_url, store_id, vss_seed_bytes, header_provider).map_err(|e| {
694+
log_error!(logger, "Failed to setup VssStore: {}", e);
695+
BuildError::KVStoreSetupFailed
696+
})?)
697+
}
698+
699+
/// Builds a [`FilesystemStore`] backend based implementation of [`KVStore`].
700+
pub fn build_fs_store(&self) -> Result<FilesystemStore, BuildError> {
701+
let mut storage_dir_path: PathBuf = self.config.storage_dir_path.clone().into();
702+
storage_dir_path.push("fs_store");
703+
704+
fs::create_dir_all(storage_dir_path.clone())
705+
.map_err(|_| BuildError::StoragePathAccessFailed)?;
706+
Ok(FilesystemStore::new(storage_dir_path))
707+
}
708+
709+
/// Builds a [`SqliteStore`] backend based implementation of [`KVStore`].
710+
pub fn build_sqlite_store(&self) -> Result<SqliteStore, BuildError> {
711+
let storage_dir_path = self.config.storage_dir_path.clone();
712+
fs::create_dir_all(storage_dir_path.clone())
713+
.map_err(|_| BuildError::StoragePathAccessFailed)?;
714+
715+
Ok(SqliteStore::new(
716+
storage_dir_path.into(),
717+
Some(io::sqlite_store::SQLITE_DB_FILE_NAME.to_string()),
718+
Some(io::sqlite_store::KV_TABLE_NAME.to_string()),
719+
)
720+
.map_err(|_| BuildError::KVStoreSetupFailed)?)
721+
}
722+
}
723+
582724
/// A builder for an [`Node`] instance, allowing to set some configuration and module choices from
583725
/// the getgo.
584726
///

0 commit comments

Comments
 (0)