Skip to content

Commit

Permalink
generate cross node entropy and seed for PhantomKeysManager
Browse files Browse the repository at this point in the history
  • Loading branch information
johncantrell97 committed Oct 3, 2022
1 parent ef0c1e4 commit 57caf64
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 23 deletions.
68 changes: 68 additions & 0 deletions senseicore/src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,74 @@ impl SenseiDatabase {
}
}

pub async fn get_cross_node_entropy(&self, node_id: String) -> Result<Option<Vec<u8>>, Error> {
self.get_value(node_id, String::from("cross_node_entropy"))
.await
.map(|model| model.map(|model| model.v))
}

pub fn get_cross_node_entropy_sync(&self, node_id: String) -> Result<Option<Vec<u8>>, Error> {
tokio::task::block_in_place(move || {
self.runtime_handle
.block_on(async move { self.get_cross_node_entropy(node_id).await })
})
}

pub async fn set_cross_node_entropy(
&self,
node_id: String,
cross_node_entropy: Vec<u8>,
) -> Result<kv_store::Model, Error> {
self.set_value(
node_id,
String::from("cross_node_entropy"),
cross_node_entropy,
)
.await
}

pub fn set_cross_node_entropy_sync(
&self,
node_id: String,
cross_node_entropy: Vec<u8>,
) -> Result<kv_store::Model, Error> {
tokio::task::block_in_place(move || {
self.runtime_handle.block_on(async move {
self.set_cross_node_entropy(node_id, cross_node_entropy)
.await
})
})
}

pub async fn create_cross_node_entropy(
&self,
node_id: String,
cross_node_entropy: Vec<u8>,
) -> Result<kv_store::Model, Error> {
self.create_value(
node_id,
String::from("cross_node_entropy"),
cross_node_entropy,
)
.await
}

pub fn get_cross_node_entropy_active_model(
&self,
node_id: String,
cross_node_entropy: Vec<u8>,
) -> kv_store::ActiveModel {
let now = seconds_since_epoch();
kv_store::ActiveModel {
node_id: ActiveValue::Set(node_id),
k: ActiveValue::Set(String::from("cross_node_entropy")),
v: ActiveValue::Set(cross_node_entropy),
created_at: ActiveValue::Set(now),
updated_at: ActiveValue::Set(now),
..Default::default()
}
}

pub async fn insert_kv_store(
&self,
entity: kv_store::ActiveModel,
Expand Down
5 changes: 3 additions & 2 deletions senseicore/src/event_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ use bitcoin::{secp256k1::Secp256k1, Network};
use bitcoin_bech32::WitnessProgram;
use entity::sea_orm::ActiveValue;
use lightning::chain::chaininterface::{BroadcasterInterface, FeeEstimator};
use lightning::chain::keysinterface::PhantomKeysManager;
use lightning::{
chain::{chaininterface::ConfirmationTarget, keysinterface::KeysManager},
chain::chaininterface::ConfirmationTarget,
util::events::{Event, EventHandler, PaymentPurpose},
};
use rand::{thread_rng, Rng};
Expand All @@ -36,7 +37,7 @@ pub struct LightningNodeEventHandler {
pub config: Arc<SenseiConfig>,
pub wallet: Arc<Mutex<bdk::Wallet<WalletDatabase>>>,
pub channel_manager: Arc<ChannelManager>,
pub keys_manager: Arc<KeysManager>,
pub keys_manager: Arc<PhantomKeysManager>,
pub database: Arc<SenseiDatabase>,
pub chain_manager: Arc<SenseiChainManager>,
pub tokio_handle: Handle,
Expand Down
63 changes: 48 additions & 15 deletions senseicore/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ use bitcoin::secp256k1::{PublicKey, Secp256k1};
use bitcoin::util::bip32::{ChildNumber, DerivationPath, ExtendedPrivKey};
use bitcoin::BlockHash;
use lightning::chain::chainmonitor;
use lightning::chain::keysinterface::{InMemorySigner, KeysInterface, KeysManager, Recipient};
use lightning::chain::keysinterface::{
InMemorySigner, KeysInterface, KeysManager, PhantomKeysManager, Recipient,
};
use lightning::chain::Watch;
use lightning::chain::{self, Filter};
use lightning::ln::channelmanager::{self, ChannelDetails, ChannelManager as LdkChannelManager};
Expand Down Expand Up @@ -307,7 +309,7 @@ pub type ChainMonitor = chainmonitor::ChainMonitor<
trait MustSized: Sized {}

pub type SimpleArcChannelManager<M, T, F, L> =
LdkChannelManager<InMemorySigner, Arc<M>, Arc<T>, Arc<KeysManager>, Arc<F>, Arc<L>>;
LdkChannelManager<InMemorySigner, Arc<M>, Arc<T>, Arc<PhantomKeysManager>, Arc<F>, Arc<L>>;

pub type SimpleArcPeerManager<SD, M, T, F, L> = LdkPeerManager<
SD,
Expand Down Expand Up @@ -419,7 +421,7 @@ pub struct LightningNode {
pub chain_manager: Arc<SenseiChainManager>,
pub peer_manager: Arc<PeerManager>,
pub p2p: Arc<SenseiP2P>,
pub keys_manager: Arc<KeysManager>,
pub keys_manager: Arc<PhantomKeysManager>,
pub logger: Arc<FilesystemLogger>,
pub invoice_payer: Arc<InvoicePayer>,
pub stop_listen: Arc<AtomicBool>,
Expand Down Expand Up @@ -462,6 +464,28 @@ impl LightningNode {
}
}

async fn get_cross_node_entropy_for_node(
node_id: String,
passphrase: String,
database: Arc<SenseiDatabase>,
) -> Result<[u8; 32], Error> {
let cryptor = RingCryptor::new();
let mut entropy: [u8; 32] = [0; 32];
match database.get_cross_node_entropy(node_id.clone()).await? {
Some(encrypted_entropy) => {
let decrypted_entropy =
cryptor.open(passphrase.as_bytes(), encrypted_entropy.as_slice())?;

if decrypted_entropy.len() != 32 {
return Err(Error::InvalidEntropyLength);
}
entropy.copy_from_slice(decrypted_entropy.as_slice());
Ok(entropy)
}
None => Err(Error::EntropyNotFound),
}
}

pub fn generate_macaroon(seed: &[u8], pubkey: String) -> Result<(Macaroon, String), Error> {
let id = uuid::Uuid::new_v4().to_string();
let macaroon_data = MacaroonSession {
Expand Down Expand Up @@ -572,22 +596,18 @@ impl LightningNode {
) -> Result<(Self, Vec<JoinHandle<()>>, BackgroundProcessor), Error> {
let network = config.network;

let seed =
let entropy =
LightningNode::get_entropy_for_node(id.clone(), passphrase.clone(), database.clone())
.await?;

let xprivkey = ExtendedPrivKey::new_master(network, &seed).unwrap();

let ldk_seed: [u8; 32] = xprivkey.private_key.secret_bytes();
let cur = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap();
let keys_manager = Arc::new(KeysManager::new(
&ldk_seed,
cur.as_secs(),
cur.subsec_nanos(),
));
let cross_node_entropy = LightningNode::get_cross_node_entropy_for_node(
id.clone(),
passphrase.clone(),
database.clone(),
)
.await?;

let xprivkey = ExtendedPrivKey::new_master(network, &entropy).unwrap();
let xkey = ExtendedKey::from(xprivkey);
let native_segwit_base_path = "m/84";
let account_number = 0;
Expand Down Expand Up @@ -615,6 +635,19 @@ impl LightningNode {

let logger = Arc::new(FilesystemLogger::new(data_dir.clone(), config.network));

let seed = LightningNode::get_seed_from_entropy(network, &entropy);
let cross_node_seed = LightningNode::get_seed_from_entropy(network, &cross_node_entropy);

let cur = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap();
let keys_manager = Arc::new(PhantomKeysManager::new(
&seed,
cur.as_secs(),
cur.subsec_nanos(),
&cross_node_seed,
));

let broadcaster = Arc::new(SenseiBroadcaster::new(
id.clone(),
chain_manager.broadcaster.clone(),
Expand Down
32 changes: 26 additions & 6 deletions senseicore/src/services/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -699,20 +699,27 @@ impl AdminService {

let mut nodes_with_macaroons = Vec::with_capacity(built_nodes.len());
let mut db_nodes = Vec::with_capacity(built_nodes.len());
let mut db_seeds = Vec::with_capacity(built_nodes.len());
let mut db_entropys = Vec::with_capacity(built_nodes.len());
let mut db_cross_node_entropys = Vec::with_capacity(built_nodes.len());
let mut db_macaroons = Vec::with_capacity(built_nodes.len());

for (node, macaroon, db_node, db_seed, db_macaroon) in built_nodes.drain(..) {
for (node, macaroon, db_node, db_entropy, db_cross_node_entropy, db_macaroon) in
built_nodes.drain(..)
{
nodes_with_macaroons.push((node, macaroon));
db_nodes.push(db_node);
db_seeds.push(db_seed);
db_entropys.push(db_entropy);
db_cross_node_entropys.push(db_cross_node_entropy);
db_macaroons.push(db_macaroon);
}

entity::node::Entity::insert_many(db_nodes)
.exec(self.database.get_connection())
.await?;
entity::kv_store::Entity::insert_many(db_seeds)
entity::kv_store::Entity::insert_many(db_entropys)
.exec(self.database.get_connection())
.await?;
entity::kv_store::Entity::insert_many(db_cross_node_entropys)
.exec(self.database.get_connection())
.await?;
entity::macaroon::Entity::insert_many(db_macaroons)
Expand All @@ -734,6 +741,7 @@ impl AdminService {
Macaroon,
entity::node::ActiveModel,
entity::kv_store::ActiveModel,
entity::kv_store::ActiveModel,
entity::macaroon::ActiveModel,
),
crate::error::Error,
Expand All @@ -757,12 +765,20 @@ impl AdminService {

// NODE ENTROPY
let entropy = LightningNode::generate_entropy();
let cross_node_entropy = LightningNode::generate_entropy();

let encrypted_entropy = LightningNode::encrypt_entropy(&entropy, passphrase.as_bytes())?;
let encrypted_cross_node_entropy =
LightningNode::encrypt_entropy(&cross_node_entropy, passphrase.as_bytes())?;

let entropy_active_model = self
.database
.get_entropy_active_model(node_id.clone(), encrypted_entropy);

let cross_node_entropy_active_model = self
.database
.get_cross_node_entropy_active_model(node_id.clone(), encrypted_cross_node_entropy);

let seed = LightningNode::get_seed_from_entropy(self.config.network, &entropy);

// NODE PUBKEY
Expand Down Expand Up @@ -818,6 +834,7 @@ impl AdminService {
macaroon,
active_node,
entropy_active_model,
cross_node_entropy_active_model,
db_macaroon,
))
}
Expand All @@ -829,10 +846,13 @@ impl AdminService {
passphrase: String,
role: node::NodeRole,
) -> Result<(node::Model, Macaroon), crate::error::Error> {
let (node, macaroon, db_node, db_seed, db_macaroon) =
let (node, macaroon, db_node, db_entropy, db_cross_node_entropy, db_macaroon) =
self.build_node(username, alias, passphrase, role).await?;

db_seed.insert(self.database.get_connection()).await?;
db_entropy.insert(self.database.get_connection()).await?;
db_cross_node_entropy
.insert(self.database.get_connection())
.await?;
db_macaroon.insert(self.database.get_connection()).await?;
db_node.insert(self.database.get_connection()).await?;

Expand Down

0 comments on commit 57caf64

Please sign in to comment.