Skip to content

Commit 30034d9

Browse files
authored
Merge pull request #324 from Alesfatalis/i323_automatic_wallet_unlock
add node wallet password environment variable
2 parents fa6f161 + 4a5b92c commit 30034d9

File tree

8 files changed

+94
-25
lines changed

8 files changed

+94
-25
lines changed

core/src/api.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,11 @@ async fn pool_status(oracle_pool: Arc<OraclePool>) -> Result<Json<serde_json::Va
128128
}
129129

130130
fn pool_status_sync(oracle_pool: Arc<OraclePool>) -> Result<Json<serde_json::Value>, ApiError> {
131-
let node_api = NodeApi::new(ORACLE_SECRETS.node_api_key.clone(), &ORACLE_CONFIG.node_url);
131+
let node_api = NodeApi::new(
132+
ORACLE_SECRETS.node_api_key.clone(),
133+
ORACLE_SECRETS.wallet_password.clone(),
134+
&ORACLE_CONFIG.node_url,
135+
);
132136
let current_height = node_api.node.current_block_height()? as u32;
133137
let pool_box = oracle_pool.get_pool_box_source().get_pool_box()?;
134138
let epoch_length = POOL_CONFIG
@@ -156,7 +160,11 @@ fn pool_status_sync(oracle_pool: Arc<OraclePool>) -> Result<Json<serde_json::Val
156160
/// Block height of the Ergo blockchain
157161
async fn block_height() -> Result<impl IntoResponse, ApiError> {
158162
let current_height = task::spawn_blocking(move || {
159-
let node_api = NodeApi::new(ORACLE_SECRETS.node_api_key.clone(), &ORACLE_CONFIG.node_url);
163+
let node_api = NodeApi::new(
164+
ORACLE_SECRETS.node_api_key.clone(),
165+
ORACLE_SECRETS.wallet_password.clone(),
166+
&ORACLE_CONFIG.node_url,
167+
);
160168
node_api.node.current_block_height()
161169
})
162170
.await
@@ -197,7 +205,11 @@ async fn oracle_health(oracle_pool: Arc<OraclePool>) -> impl IntoResponse {
197205
}
198206

199207
fn oracle_health_sync(oracle_pool: Arc<OraclePool>) -> Result<OracleHealth, ApiError> {
200-
let node_api = NodeApi::new(ORACLE_SECRETS.node_api_key.clone(), &ORACLE_CONFIG.node_url);
208+
let node_api = NodeApi::new(
209+
ORACLE_SECRETS.node_api_key.clone(),
210+
ORACLE_SECRETS.wallet_password.clone(),
211+
&ORACLE_CONFIG.node_url,
212+
);
201213
let current_height = (node_api.node.current_block_height()? as u32).into();
202214
let epoch_length = POOL_CONFIG
203215
.refresh_box_wrapper_inputs
@@ -239,7 +251,11 @@ async fn pool_health(oracle_pool: Arc<OraclePool>) -> impl IntoResponse {
239251
}
240252

241253
fn pool_health_sync(oracle_pool: Arc<OraclePool>) -> Result<PoolHealth, ApiError> {
242-
let node_api = NodeApi::new(ORACLE_SECRETS.node_api_key.clone(), &ORACLE_CONFIG.node_url);
254+
let node_api = NodeApi::new(
255+
ORACLE_SECRETS.node_api_key.clone(),
256+
ORACLE_SECRETS.wallet_password.clone(),
257+
&ORACLE_CONFIG.node_url,
258+
);
243259
let current_height = (node_api.node.current_block_height()? as u32).into();
244260
let pool_box = &oracle_pool.get_pool_box_source().get_pool_box()?;
245261
let pool_box_height = pool_box.get_box().creation_height.into();

core/src/cli_commands/bootstrap.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,8 @@ use crate::{
4343
},
4444
explorer_api::wait_for_txs_confirmation,
4545
node_interface::{
46-
assert_wallet_unlocked,
4746
node_api::{NodeApi, NodeApiError},
48-
SignTransactionWithInputs, SubmitTransaction,
47+
try_ensure_wallet_unlocked, SignTransactionWithInputs, SubmitTransaction,
4948
},
5049
oracle_config::{BASE_FEE, ORACLE_CONFIG, ORACLE_SECRETS},
5150
oracle_types::{BlockHeight, EpochCounter},
@@ -69,8 +68,12 @@ pub fn bootstrap(config_file_name: String) -> Result<(), anyhow::Error> {
6968
let s = std::fs::read_to_string(config_file_name)?;
7069
let config: BootstrapConfig = serde_yaml::from_str(&s)?;
7170

72-
let node_api = NodeApi::new(ORACLE_SECRETS.node_api_key.clone(), &oracle_config.node_url);
73-
assert_wallet_unlocked(&node_api.node);
71+
let node_api = NodeApi::new(
72+
ORACLE_SECRETS.node_api_key.clone(),
73+
ORACLE_SECRETS.wallet_password.clone(),
74+
&oracle_config.node_url,
75+
);
76+
try_ensure_wallet_unlocked(&node_api);
7477
let change_address = node_api.get_change_address()?;
7578
debug!("Change address: {:?}", change_address);
7679
let erg_value_per_box = config.oracle_contract_parameters.min_storage_rent;

core/src/main.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ use log::error;
6666
use log::LevelFilter;
6767
use metrics::start_metrics_server;
6868
use metrics::update_metrics;
69-
use node_interface::assert_wallet_unlocked;
7069
use node_interface::node_api::NodeApi;
70+
use node_interface::try_ensure_wallet_unlocked;
7171
use oracle_config::ORACLE_CONFIG;
7272
use oracle_config::ORACLE_SECRETS;
7373
use oracle_state::OraclePool;
@@ -282,8 +282,12 @@ fn main() {
282282
Arc::new(RwLock::new(ActionReportStorage::new()));
283283

284284
log_on_launch();
285-
let node_api = NodeApi::new(ORACLE_SECRETS.node_api_key.clone(), &ORACLE_CONFIG.node_url);
286-
assert_wallet_unlocked(&node_api.node);
285+
let node_api = NodeApi::new(
286+
ORACLE_SECRETS.node_api_key.clone(),
287+
ORACLE_SECRETS.wallet_password.clone(),
288+
&ORACLE_CONFIG.node_url,
289+
);
290+
try_ensure_wallet_unlocked(&node_api);
287291
wait_for_node_rescan(&node_api).unwrap();
288292

289293
let pool_config = &POOL_CONFIG;

core/src/metrics.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,11 @@ fn update_reward_tokens_in_buyback_box(oracle_pool: Arc<OraclePool>) {
271271
}
272272

273273
pub fn update_metrics(oracle_pool: Arc<OraclePool>) -> Result<(), anyhow::Error> {
274-
let node_api = NodeApi::new(ORACLE_SECRETS.node_api_key.clone(), &ORACLE_CONFIG.node_url);
274+
let node_api = NodeApi::new(
275+
ORACLE_SECRETS.node_api_key.clone(),
276+
ORACLE_SECRETS.wallet_password.clone(),
277+
&ORACLE_CONFIG.node_url,
278+
);
275279
let current_height = (node_api.node.current_block_height()? as u32).into();
276280
let network_prefix = node_api.get_change_address()?.network();
277281
let pool_box = &oracle_pool.get_pool_box_source().get_pool_box()?;

core/src/node_interface.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::node_interface::node_api::NodeApi;
12
use ergo_lib::{
23
chain::transaction::{unsigned::UnsignedTransaction, Transaction, TxId, TxIoVec},
34
ergotree_ir::chain::ergo_box::ErgoBox,
@@ -62,11 +63,19 @@ impl SignTransactionWithInputs for NodeInterface {
6263
}
6364
}
6465

65-
pub fn assert_wallet_unlocked(node: &NodeInterface) {
66-
let unlocked = node.wallet_status().unwrap().unlocked;
66+
pub fn try_ensure_wallet_unlocked(node: &NodeApi) {
67+
let unlocked = node.node.wallet_status().unwrap().unlocked;
68+
6769
if !unlocked {
68-
error!("Wallet must be unlocked for node operations");
69-
std::process::exit(exitcode::SOFTWARE);
70+
if let Some(wallet_pass) = &node.wallet_pass {
71+
if let Err(e) = node.wallet_unlock(wallet_pass) {
72+
error!("Failed to unlock wallet. Wallet must be unlocked for node operations. error: {:?}", e);
73+
std::process::exit(exitcode::SOFTWARE);
74+
}
75+
} else {
76+
error!("Wallet must be unlocked for node operations");
77+
std::process::exit(exitcode::SOFTWARE);
78+
}
7079
} else {
7180
debug!("Wallet unlocked");
7281
}

core/src/node_interface/node_api.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,13 @@ use crate::wallet::WalletDataSource;
1818

1919
pub struct NodeApi {
2020
pub node: NodeInterface,
21+
pub wallet_pass: Option<String>,
2122
}
2223

2324
impl NodeApi {
24-
pub fn new(api_key: String, node_url: &Url) -> Self {
25+
pub fn new(api_key: String, wallet_pass: Option<String>, node_url: &Url) -> Self {
2526
let node = NodeInterface::from_url(&api_key, node_url.clone());
26-
Self { node }
27+
Self { node, wallet_pass }
2728
}
2829

2930
pub fn get_change_address(&self) -> Result<NetworkAddress, NodeApiError> {
@@ -95,6 +96,25 @@ impl NodeApi {
9596
);
9697
Ok(self.node.submit_transaction(&signed_tx)?)
9798
}
99+
100+
/// Unlock wallet
101+
pub fn wallet_unlock(&self, password: &str) -> Result<bool, NodeApiError> {
102+
let endpoint = "/wallet/unlock";
103+
let body = json! ({
104+
"pass": password,
105+
});
106+
107+
let res = self.node.send_post_req(endpoint, body.to_string())?;
108+
109+
if res.status().is_success() {
110+
Ok(true)
111+
} else {
112+
let json = self.node.parse_response_to_json(Ok(res))?;
113+
Err(NodeApiError::NodeInterfaceError(NodeError::BadRequest(
114+
json["error"].to_string(),
115+
)))
116+
}
117+
}
98118
}
99119

100120
impl WalletDataSource for NodeApi {

core/src/oracle_config.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use ergo_lib::{
1616
},
1717
wallet::tx_builder::{self, SUGGESTED_TX_FEE},
1818
};
19-
use log::LevelFilter;
19+
use log::{warn, LevelFilter};
2020
use once_cell::sync;
2121
use reqwest::Url;
2222
use serde::{Deserialize, Serialize};
@@ -41,15 +41,24 @@ pub struct OracleConfig {
4141

4242
pub struct OracleSecrets {
4343
pub node_api_key: String,
44+
pub wallet_password: Option<String>,
4445
}
4546

4647
impl OracleSecrets {
4748
pub fn load() -> Self {
48-
std::env::var("ORACLE_NODE_API_KEY")
49-
.map(|node_api_key| Self { node_api_key })
50-
.unwrap_or_else(|_| {
51-
panic!("ORACLE_NODE_API_KEY environment variable for node API key is not set")
52-
})
49+
let api_key = std::env::var("ORACLE_NODE_API_KEY").unwrap_or_else(|_| {
50+
panic!("ORACLE_NODE_API_KEY environment variable for node API key is not set")
51+
});
52+
53+
let wallet_pass = std::env::var("ORACLE_NODE_WALLET_PASSWORD").ok();
54+
if wallet_pass.is_none() {
55+
warn!("ORACLE_NODE_WALLET_PASSWORD environment variable for automatic unlock of node wallet is not set");
56+
}
57+
58+
Self {
59+
node_api_key: api_key,
60+
wallet_password: wallet_pass,
61+
}
5362
}
5463
}
5564

core/src/scans.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,11 @@ pub trait NodeScanId {
4141

4242
pub trait ScanGetBoxes: NodeScanId {
4343
fn get_boxes(&self) -> Result<Vec<ErgoBox>, ScanError> {
44-
let node_api = NodeApi::new(ORACLE_SECRETS.node_api_key.clone(), &ORACLE_CONFIG.node_url);
44+
let node_api = NodeApi::new(
45+
ORACLE_SECRETS.node_api_key.clone(),
46+
ORACLE_SECRETS.wallet_password.clone(),
47+
&ORACLE_CONFIG.node_url,
48+
);
4549
let boxes = node_api.node.scan_boxes(self.scan_id())?;
4650
Ok(boxes)
4751
}

0 commit comments

Comments
 (0)