Skip to content

Commit

Permalink
add node wallet password environment variable
Browse files Browse the repository at this point in the history
- automatically unlocks node wallet if password is set
  • Loading branch information
Alesfatalis committed Dec 28, 2023
1 parent 4ba5447 commit fd32d9a
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 21 deletions.
24 changes: 20 additions & 4 deletions core/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,11 @@ async fn pool_status(oracle_pool: Arc<OraclePool>) -> Result<Json<serde_json::Va
}

fn pool_status_sync(oracle_pool: Arc<OraclePool>) -> Result<Json<serde_json::Value>, ApiError> {
let node_api = NodeApi::new(ORACLE_SECRETS.node_api_key.clone(), &ORACLE_CONFIG.node_url);
let node_api = NodeApi::new(
ORACLE_SECRETS.node_api_key.clone(),
ORACLE_SECRETS.wallet_password.clone(),
&ORACLE_CONFIG.node_url,
);
let current_height = node_api.node.current_block_height()? as u32;
let pool_box = oracle_pool.get_pool_box_source().get_pool_box()?;
let epoch_length = POOL_CONFIG
Expand Down Expand Up @@ -156,7 +160,11 @@ fn pool_status_sync(oracle_pool: Arc<OraclePool>) -> Result<Json<serde_json::Val
/// Block height of the Ergo blockchain
async fn block_height() -> Result<impl IntoResponse, ApiError> {
let current_height = task::spawn_blocking(move || {
let node_api = NodeApi::new(ORACLE_SECRETS.node_api_key.clone(), &ORACLE_CONFIG.node_url);
let node_api = NodeApi::new(
ORACLE_SECRETS.node_api_key.clone(),
ORACLE_SECRETS.wallet_password.clone(),
&ORACLE_CONFIG.node_url,
);
node_api.node.current_block_height()
})
.await
Expand Down Expand Up @@ -197,7 +205,11 @@ async fn oracle_health(oracle_pool: Arc<OraclePool>) -> impl IntoResponse {
}

fn oracle_health_sync(oracle_pool: Arc<OraclePool>) -> Result<OracleHealth, ApiError> {
let node_api = NodeApi::new(ORACLE_SECRETS.node_api_key.clone(), &ORACLE_CONFIG.node_url);
let node_api = NodeApi::new(
ORACLE_SECRETS.node_api_key.clone(),
ORACLE_SECRETS.wallet_password.clone(),
&ORACLE_CONFIG.node_url,
);
let current_height = (node_api.node.current_block_height()? as u32).into();
let epoch_length = POOL_CONFIG
.refresh_box_wrapper_inputs
Expand Down Expand Up @@ -239,7 +251,11 @@ async fn pool_health(oracle_pool: Arc<OraclePool>) -> impl IntoResponse {
}

fn pool_health_sync(oracle_pool: Arc<OraclePool>) -> Result<PoolHealth, ApiError> {
let node_api = NodeApi::new(ORACLE_SECRETS.node_api_key.clone(), &ORACLE_CONFIG.node_url);
let node_api = NodeApi::new(
ORACLE_SECRETS.node_api_key.clone(),
ORACLE_SECRETS.wallet_password.clone(),
&ORACLE_CONFIG.node_url,
);
let current_height = (node_api.node.current_block_height()? as u32).into();
let pool_box = &oracle_pool.get_pool_box_source().get_pool_box()?;
let pool_box_height = pool_box.get_box().creation_height.into();
Expand Down
8 changes: 6 additions & 2 deletions core/src/cli_commands/bootstrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,12 @@ pub fn bootstrap(config_file_name: String) -> Result<(), anyhow::Error> {
let s = std::fs::read_to_string(config_file_name)?;
let config: BootstrapConfig = serde_yaml::from_str(&s)?;

let node_api = NodeApi::new(ORACLE_SECRETS.node_api_key.clone(), &oracle_config.node_url);
assert_wallet_unlocked(&node_api.node);
let node_api = NodeApi::new(
ORACLE_SECRETS.node_api_key.clone(),
ORACLE_SECRETS.wallet_password.clone(),
&oracle_config.node_url,
);
assert_wallet_unlocked(&node_api);
let change_address = node_api.get_change_address()?;
debug!("Change address: {:?}", change_address);
let erg_value_per_box = config.oracle_contract_parameters.min_storage_rent;
Expand Down
8 changes: 6 additions & 2 deletions core/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,12 @@ fn main() {
Arc::new(RwLock::new(ActionReportStorage::new()));

log_on_launch();
let node_api = NodeApi::new(ORACLE_SECRETS.node_api_key.clone(), &ORACLE_CONFIG.node_url);
assert_wallet_unlocked(&node_api.node);
let node_api = NodeApi::new(
ORACLE_SECRETS.node_api_key.clone(),
ORACLE_SECRETS.wallet_password.clone(),
&ORACLE_CONFIG.node_url,
);
assert_wallet_unlocked(&node_api);
wait_for_node_rescan(&node_api).unwrap();

let pool_config = &POOL_CONFIG;
Expand Down
6 changes: 5 additions & 1 deletion core/src/metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,11 @@ fn update_reward_tokens_in_buyback_box(oracle_pool: Arc<OraclePool>) {
}

pub fn update_metrics(oracle_pool: Arc<OraclePool>) -> Result<(), anyhow::Error> {
let node_api = NodeApi::new(ORACLE_SECRETS.node_api_key.clone(), &ORACLE_CONFIG.node_url);
let node_api = NodeApi::new(
ORACLE_SECRETS.node_api_key.clone(),
ORACLE_SECRETS.wallet_password.clone(),
&ORACLE_CONFIG.node_url,
);
let current_height = (node_api.node.current_block_height()? as u32).into();
let network_prefix = node_api.get_change_address()?.network();
let pool_box = &oracle_pool.get_pool_box_source().get_pool_box()?;
Expand Down
21 changes: 17 additions & 4 deletions core/src/node_interface.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::node_interface::node_api::NodeApi;
use ergo_lib::{
chain::transaction::{unsigned::UnsignedTransaction, Transaction, TxId, TxIoVec},
ergotree_ir::chain::ergo_box::ErgoBox,
Expand Down Expand Up @@ -62,11 +63,23 @@ impl SignTransactionWithInputs for NodeInterface {
}
}

pub fn assert_wallet_unlocked(node: &NodeInterface) {
let unlocked = node.wallet_status().unwrap().unlocked;
pub fn assert_wallet_unlocked(node: &NodeApi) {
let unlocked = node.node.wallet_status().unwrap().unlocked;

if !unlocked {
error!("Wallet must be unlocked for node operations");
std::process::exit(exitcode::SOFTWARE);
if node.wallet_pass.is_some() {
let unlock_res = node.wallet_unlock(&node.wallet_pass.clone().unwrap());
if unlock_res.is_err() {
error!(
"Failed to unlock wallet. Wallet must be unlocked for node operations. error: {:?}",
unlock_res.err()
);
std::process::exit(exitcode::SOFTWARE);
}
} else {
error!("Wallet must be unlocked for node operations");
std::process::exit(exitcode::SOFTWARE);
}
} else {
debug!("Wallet unlocked");
}
Expand Down
24 changes: 22 additions & 2 deletions core/src/node_interface/node_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ use crate::wallet::WalletDataSource;

pub struct NodeApi {
pub node: NodeInterface,
pub wallet_pass: Option<String>,
}

impl NodeApi {
pub fn new(api_key: String, node_url: &Url) -> Self {
pub fn new(api_key: String, wallet_pass: Option<String>, node_url: &Url) -> Self {
let node = NodeInterface::from_url(&api_key, node_url.clone());
Self { node }
Self { node, wallet_pass }
}

pub fn get_change_address(&self) -> Result<NetworkAddress, NodeApiError> {
Expand Down Expand Up @@ -95,6 +96,25 @@ impl NodeApi {
);
Ok(self.node.submit_transaction(&signed_tx)?)
}

/// Unlock wallet
pub fn wallet_unlock(&self, password: &str) -> Result<bool, NodeApiError> {
let endpoint = "/wallet/unlock";
let body = json! ({
"pass": password,
});

let res = self.node.send_post_req(endpoint, body.to_string())?;

if res.status().is_success() {
Ok(true)
} else {
let json = self.node.parse_response_to_json(Ok(res))?;
Err(NodeApiError::NodeInterfaceError(NodeError::BadRequest(
json["error"].to_string(),
)))
}
}
}

impl WalletDataSource for NodeApi {
Expand Down
21 changes: 16 additions & 5 deletions core/src/oracle_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use ergo_lib::{
},
wallet::tx_builder::{self, SUGGESTED_TX_FEE},
};
use log::LevelFilter;
use log::{warn, LevelFilter};
use once_cell::sync;
use reqwest::Url;
use serde::{Deserialize, Serialize};
Expand All @@ -41,15 +41,26 @@ pub struct OracleConfig {

pub struct OracleSecrets {
pub node_api_key: String,
pub wallet_password: Option<String>,
}

impl OracleSecrets {
pub fn load() -> Self {
std::env::var("ORACLE_NODE_API_KEY")
.map(|node_api_key| Self { node_api_key })
let api_key = std::env::var("ORACLE_NODE_API_KEY").unwrap_or_else(|_| {
panic!("ORACLE_NODE_API_KEY environment variable for node API key is not set")
});

let wallet_pass = std::env::var("ORACLE_NODE_WALLET_PASSWORD")
.map(Some)
.unwrap_or_else(|_| {
panic!("ORACLE_NODE_API_KEY environment variable for node API key is not set")
})
warn!("ORACLE_NODE_WALLET_PASSWORD environment variable for automatic unlock of node wallet is not set");
None
});

Self {
node_api_key: api_key,
wallet_password: wallet_pass,
}
}
}

Expand Down
6 changes: 5 additions & 1 deletion core/src/scans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ pub trait NodeScanId {

pub trait ScanGetBoxes: NodeScanId {
fn get_boxes(&self) -> Result<Vec<ErgoBox>, ScanError> {
let node_api = NodeApi::new(ORACLE_SECRETS.node_api_key.clone(), &ORACLE_CONFIG.node_url);
let node_api = NodeApi::new(
ORACLE_SECRETS.node_api_key.clone(),
ORACLE_SECRETS.wallet_password.clone(),
&ORACLE_CONFIG.node_url,
);
let boxes = node_api.node.scan_boxes(self.scan_id())?;
Ok(boxes)
}
Expand Down

0 comments on commit fd32d9a

Please sign in to comment.