Fix #321 Limit length of API utxo queries (#579)

* Limit url length #321

* Formatting with rustfmt

* Typo
This commit is contained in:
Quentin Le Sceller 2018-01-05 16:03:53 -05:00 committed by AntiochP
parent 26c2669fe8
commit 7212a0e743

View file

@ -50,7 +50,7 @@ fn mark_spent_output(out: &mut OutputData) {
} }
} }
/// Builds a single api query to retrieve the latest output data from the node. /// Builds multiple api queries to retrieve the latest output data from the node.
/// So we can refresh the local wallet outputs. /// So we can refresh the local wallet outputs.
pub fn refresh_outputs(config: &WalletConfig, keychain: &Keychain) -> Result<(), Error> { pub fn refresh_outputs(config: &WalletConfig, keychain: &Keychain) -> Result<(), Error> {
debug!(LOGGER, "Refreshing wallet outputs"); debug!(LOGGER, "Refreshing wallet outputs");
@ -66,7 +66,9 @@ pub fn refresh_outputs(config: &WalletConfig, keychain: &Keychain) -> Result<(),
.filter(|out| out.root_key_id == keychain.root_key_id()) .filter(|out| out.root_key_id == keychain.root_key_id())
.filter(|out| out.status != OutputStatus::Spent) .filter(|out| out.status != OutputStatus::Spent)
{ {
let commit = keychain.commit_with_key_index(out.value, out.n_child).unwrap(); let commit = keychain
.commit_with_key_index(out.value, out.n_child)
.unwrap();
commits.push(commit); commits.push(commit);
wallet_outputs.insert(commit, out.key_id.clone()); wallet_outputs.insert(commit, out.key_id.clone());
} }
@ -81,32 +83,49 @@ pub fn refresh_outputs(config: &WalletConfig, keychain: &Keychain) -> Result<(),
format!("id={}", id) format!("id={}", id)
}) })
.collect(); .collect();
let query_string = query_params.join("&");
let url = format!(
"{}/v1/chain/utxos/byids?{}",
config.check_node_api_http_addr,
query_string,
);
// build a map of api outputs by commit so we can look them up efficiently // build a map of api outputs by commit so we can look them up efficiently
let mut api_outputs: HashMap<pedersen::Commitment, api::Output> = HashMap::new(); let mut api_outputs: HashMap<pedersen::Commitment, api::Output> = HashMap::new();
// size of the batch size for the utxo query
let batch_query_size = 500;
let mut index_id = 0;
while index_id < query_params.len() {
let batch_query: Vec<String>;
if index_id + batch_query_size > query_params.len() {
batch_query = query_params[index_id..query_params.len()].to_vec();
index_id = query_params.len();
} else {
batch_query = query_params[index_id..index_id + batch_query_size].to_vec();
index_id = index_id + batch_query_size;
}
let query_string = batch_query.join("&");
let url = format!(
"{}/v1/chain/utxos/byids?{}",
config.check_node_api_http_addr, query_string,
);
match api::client::get::<Vec<api::Output>>(url.as_str()) { match api::client::get::<Vec<api::Output>>(url.as_str()) {
Ok(outputs) => for out in outputs { Ok(outputs) => for out in outputs {
api_outputs.insert(out.commit, out); api_outputs.insert(out.commit, out);
}, },
Err(e) => { Err(e) => {
// if we got anything other than 200 back from server, don't attempt to refresh the wallet // if we got anything other than 200 back from server, don't attempt to refresh
// data after // the wallet data after
return Err(Error::Node(e)); return Err(Error::Node(e));
} }
}; };
}
// now for each commit, find the output in the wallet and // now for each commit, find the output in the wallet and
// the corresponding api output (if it exists) // the corresponding api output (if it exists)
// and refresh it in-place in the wallet. // and refresh it in-place in the wallet.
// Note: minimizing the time we spend holding the wallet lock. // Note: minimizing the time we spend holding the wallet lock.
WalletData::with_wallet(&config.data_file_dir, |wallet_data| for commit in commits { WalletData::with_wallet(&config.data_file_dir, |wallet_data| {
for commit in commits {
let id = wallet_outputs.get(&commit).unwrap(); let id = wallet_outputs.get(&commit).unwrap();
if let Entry::Occupied(mut output) = wallet_data.outputs.entry(id.to_hex()) { if let Entry::Occupied(mut output) = wallet_data.outputs.entry(id.to_hex()) {
match api_outputs.get(&commit) { match api_outputs.get(&commit) {
@ -114,6 +133,7 @@ pub fn refresh_outputs(config: &WalletConfig, keychain: &Keychain) -> Result<(),
None => mark_spent_output(&mut output.get_mut()), None => mark_spent_output(&mut output.get_mut()),
}; };
} }
}
}) })
} }