slog-rs logging (#171)

* added global slog instance, changed all logging macro formats to include logger instance
* adding configuration to logging, allowing for multiple log outputs
* updates to test, changes to build docs
* rustfmt
* moving logging functions into util crate
This commit is contained in:
Yeastplume
2017-10-12 17:56:44 +01:00
committed by Ignotus Peverell
parent b85006ebe5
commit 8e382a7593
62 changed files with 973 additions and 1006 deletions
+6 -12
View File
@@ -20,7 +20,6 @@ use types::*;
use keychain::Keychain;
use util;
fn refresh_output(out: &mut OutputData, api_out: Option<api::Output>, tip: &api::Tip) {
if let Some(api_out) = api_out {
out.height = api_out.height;
@@ -40,26 +39,21 @@ fn refresh_output(out: &mut OutputData, api_out: Option<api::Output>, tip: &api:
/// Goes through the list of outputs that haven't been spent yet and check
/// with a node whether their status has changed.
pub fn refresh_outputs(
config: &WalletConfig,
keychain: &Keychain,
) -> Result<(), Error>{
pub fn refresh_outputs(config: &WalletConfig, keychain: &Keychain) -> Result<(), Error> {
let tip = get_tip_from_node(config)?;
WalletData::with_wallet(&config.data_file_dir, |wallet_data| {
// check each output that's not spent
for mut out in wallet_data.outputs
.values_mut()
.filter(|out| {
out.status != OutputStatus::Spent
})
{
for mut out in wallet_data
.outputs
.values_mut()
.filter(|out| out.status != OutputStatus::Spent) {
// TODO check the pool for unconfirmed
match get_output_from_node(config, keychain, out.value, out.n_child) {
Ok(api_out) => refresh_output(&mut out, api_out, &tip),
Err(_) => {
// TODO find error with connection and return
// error!("Error contacting server node at {}. Is it running?",
// error!(LOGGER, "Error contacting server node at {}. Is it running?",
// config.check_node_api_http_addr);
}
}
+3 -5
View File
@@ -16,10 +16,7 @@ use checker;
use keychain::Keychain;
use types::{WalletConfig, WalletData};
pub fn show_info(
config: &WalletConfig,
keychain: &Keychain,
) {
pub fn show_info(config: &WalletConfig, keychain: &Keychain) {
let fingerprint = keychain.clone().fingerprint();
let _ = checker::refresh_outputs(&config, &keychain);
@@ -30,7 +27,8 @@ pub fn show_info(
println!("identifier, height, lock_height, status, value");
println!("----------------------------------");
let mut outputs = wallet_data.outputs
let mut outputs = wallet_data
.outputs
.values()
.filter(|out| out.fingerprint == fingerprint)
.collect::<Vec<_>>();
+1 -1
View File
@@ -17,7 +17,7 @@
extern crate byteorder;
extern crate blake2_rfc as blake2;
#[macro_use]
extern crate log;
extern crate slog;
extern crate rand;
extern crate serde;
#[macro_use]
+70 -55
View File
@@ -56,6 +56,7 @@ use api::{self, ApiEndpoint, Operation, ApiResult};
use keychain::{BlindingFactor, Keychain};
use types::*;
use util;
use util::LOGGER;
/// Dummy wrapper for the hex-encoded serialized transaction.
#[derive(Serialize, Deserialize)]
@@ -66,11 +67,10 @@ pub struct TxWrapper {
/// Receive an already well formed JSON transaction issuance and finalize the
/// transaction, adding our receiving output, to broadcast to the rest of the
/// network.
pub fn receive_json_tx(
config: &WalletConfig,
keychain: &Keychain,
partial_tx_str: &str,
) -> Result<(), Error> {
pub fn receive_json_tx(config: &WalletConfig,
keychain: &Keychain,
partial_tx_str: &str)
-> Result<(), Error> {
let (amount, blinding, partial_tx) = partial_tx_from_json(keychain, partial_tx_str)?;
let final_tx = receive_transaction(config, keychain, amount, blinding, partial_tx)?;
let tx_hex = util::to_hex(ser::ser_vec(&final_tx).unwrap());
@@ -96,10 +96,8 @@ impl ApiEndpoint for WalletReceiver {
type OP_OUT = CbData;
fn operations(&self) -> Vec<Operation> {
vec![
Operation::Custom("coinbase".to_string()),
Operation::Custom("receive_json_tx".to_string()),
]
vec![Operation::Custom("coinbase".to_string()),
Operation::Custom("receive_json_tx".to_string())]
}
fn operation(&self, op: String, input: WalletReceiveRequest) -> ApiResult<CbData> {
@@ -107,29 +105,31 @@ impl ApiEndpoint for WalletReceiver {
"coinbase" => {
match input {
WalletReceiveRequest::Coinbase(cb_fees) => {
debug!("Operation {} with fees {:?}", op, cb_fees);
let (out, kern, block_fees) =
receive_coinbase(
&self.config,
&self.keychain,
&cb_fees,
).map_err(|e| {
debug!(LOGGER, "Operation {} with fees {:?}", op, cb_fees);
let (out, kern, block_fees) = receive_coinbase(
&self.config,
&self.keychain,
&cb_fees,
).map_err(|e| {
api::Error::Internal(format!("Error building coinbase: {:?}", e))
})?;
let out_bin =
ser::ser_vec(&out).map_err(|e| {
let out_bin = ser::ser_vec(&out)
.map_err(|e| {
api::Error::Internal(format!("Error serializing output: {:?}", e))
})?;
let kern_bin =
ser::ser_vec(&kern).map_err(|e| {
let kern_bin = ser::ser_vec(&kern)
.map_err(|e| {
api::Error::Internal(format!("Error serializing kernel: {:?}", e))
})?;
let pubkey_bin = match block_fees.pubkey {
Some(pubkey) => {
ser::ser_vec(&pubkey).map_err(|e| {
api::Error::Internal(format!("Error serializing kernel: {:?}", e))
})?
},
ser::ser_vec(&pubkey)
.map_err(|e| {
api::Error::Internal(
format!("Error serializing kernel: {:?}", e),
)
})?
}
None => vec![],
};
@@ -139,29 +139,34 @@ impl ApiEndpoint for WalletReceiver {
pubkey: util::to_hex(pubkey_bin),
})
}
_ => Err(api::Error::Argument(
format!("Incorrect request data: {}", op),
)),
_ => Err(api::Error::Argument(format!("Incorrect request data: {}", op))),
}
}
"receive_json_tx" => {
match input {
WalletReceiveRequest::PartialTransaction(partial_tx_str) => {
debug!("Operation {} with transaction {}", op, &partial_tx_str);
receive_json_tx(&self.config, &self.keychain, &partial_tx_str).map_err(|e| {
api::Error::Internal(format!("Error processing partial transaction: {:?}", e))
}).unwrap();
debug!(
LOGGER,
"Operation {} with transaction {}",
op,
&partial_tx_str
);
receive_json_tx(&self.config, &self.keychain, &partial_tx_str)
.map_err(|e| {
api::Error::Internal(
format!("Error processing partial transaction: {:?}", e),
)
})
.unwrap();
//TODO: Return emptiness for now, should be a proper enum return type
// TODO: Return emptiness for now, should be a proper enum return type
Ok(CbData {
output: String::from(""),
kernel: String::from(""),
pubkey: String::from(""),
})
}
_ => Err(api::Error::Argument(
format!("Incorrect request data: {}", op),
)),
_ => Err(api::Error::Argument(format!("Incorrect request data: {}", op))),
}
}
_ => Err(api::Error::Argument(format!("Unknown operation: {}", op))),
@@ -170,11 +175,10 @@ impl ApiEndpoint for WalletReceiver {
}
/// Build a coinbase output and the corresponding kernel
fn receive_coinbase(
config: &WalletConfig,
keychain: &Keychain,
block_fees: &BlockFees,
) -> Result<(Output, TxKernel, BlockFees), Error> {
fn receive_coinbase(config: &WalletConfig,
keychain: &Keychain,
block_fees: &BlockFees)
-> Result<(Output, TxKernel, BlockFees), Error> {
let fingerprint = keychain.fingerprint();
// operate within a lock on wallet data
@@ -184,7 +188,7 @@ fn receive_coinbase(
Some(pubkey) => {
let derivation = keychain.derivation_from_pubkey(&pubkey)?;
(pubkey.clone(), derivation)
},
}
None => {
let derivation = wallet_data.next_child(fingerprint.clone());
let pubkey = keychain.derive_pubkey(derivation)?;
@@ -203,15 +207,20 @@ fn receive_coinbase(
lock_height: 0,
});
debug!("Received coinbase and built candidate output - {}, {}, {}",
fingerprint.clone(), pubkey.fingerprint(), derivation);
debug!(
LOGGER,
"Received coinbase and built candidate output - {}, {}, {}",
fingerprint.clone(),
pubkey.fingerprint(),
derivation
);
debug!("block_fees - {:?}", block_fees);
debug!(LOGGER, "block_fees - {:?}", block_fees);
let mut block_fees = block_fees.clone();
block_fees.pubkey = Some(pubkey.clone());
debug!("block_fees updated - {:?}", block_fees);
debug!(LOGGER, "block_fees updated - {:?}", block_fees);
let (out, kern) = Block::reward_output(
&keychain,
@@ -246,14 +255,16 @@ fn receive_transaction(
let fee_amount = tx_fee(partial.inputs.len(), partial.outputs.len() + 1, None);
let out_amount = amount - fee_amount;
let (tx_final, _) = build::transaction(vec![
build::initial_tx(partial),
build::with_excess(blinding),
build::output(out_amount, pubkey.clone()),
build::with_fee(fee_amount),
], keychain)?;
let (tx_final, _) = build::transaction(
vec![build::initial_tx(partial),
build::with_excess(blinding),
build::output(out_amount, pubkey.clone()),
build::with_fee(fee_amount)],
keychain,
)?;
// make sure the resulting transaction is valid (could have been lied to on excess)
// make sure the resulting transaction is valid (could have been lied to on
// excess)
tx_final.validate(&keychain.secp())?;
// track the new output and return the finalized transaction to broadcast
@@ -266,9 +277,13 @@ fn receive_transaction(
height: 0,
lock_height: 0,
});
debug!("Received txn and built output - {}, {}, {}",
fingerprint.clone(), pubkey.fingerprint(), derivation);
debug!(
LOGGER,
"Received txn and built output - {}, {}, {}",
fingerprint.clone(),
pubkey.fingerprint(),
derivation
);
Ok(tx_final)
})?
}
+9 -11
View File
@@ -19,12 +19,14 @@ use core::ser;
use keychain::{BlindingFactor, Keychain, Fingerprint, Identifier};
use receiver::TxWrapper;
use types::*;
use util::LOGGER;
use util;
/// Issue a new transaction to the provided sender by spending some of our
/// wallet
/// UTXOs. The destination can be "stdout" (for command line) or a URL to the
/// recipients wallet receiver (to be implemented).
pub fn issue_send_tx(
config: &WalletConfig,
keychain: &Keychain,
@@ -43,10 +45,12 @@ pub fn issue_send_tx(
println!("{}", json_tx);
} else if &dest[..4] == "http" {
let url = format!("{}/v1/receive/receive_json_tx", &dest);
debug!("Posting partial transaction to {}", url);
debug!(LOGGER, "Posting partial transaction to {}", url);
let request = WalletReceiveRequest::PartialTransaction(json_tx);
let _: CbData = api::client::post(url.as_str(), &request)
.expect(&format!("Wallet receiver at {} unreachable, could not send transaction. Is it running?", url));
let _: CbData = api::client::post(url.as_str(), &request).expect(&format!(
"Wallet receiver at {} unreachable, could not send transaction. Is it running?",
url
));
} else {
panic!("dest not in expected format: {}", dest);
}
@@ -175,15 +179,9 @@ mod test {
let keychain = Keychain::from_random_seed().unwrap();
let pk1 = keychain.derive_pubkey(1).unwrap();
let (tx, _) = transaction(
vec![output(105, pk1.clone())],
&keychain,
).unwrap();
let (tx, _) = transaction(vec![output(105, pk1.clone())], &keychain).unwrap();
let (tx2, _) = transaction(
vec![input(105, pk1.clone())],
&keychain,
).unwrap();
let (tx2, _) = transaction(vec![input(105, pk1.clone())], &keychain).unwrap();
assert_eq!(tx.outputs[0].commitment(), tx2.inputs[0].commitment());
}
+34 -37
View File
@@ -28,6 +28,7 @@ use core::core::{Transaction, transaction};
use core::ser;
use keychain;
use util;
use util::LOGGER;
const DAT_FILE: &'static str = "wallet.dat";
const LOCK_FILE: &'static str = "wallet.lock";
@@ -195,12 +196,11 @@ impl WalletData {
/// across operating systems, this just creates a lock file with a "should
/// not exist" option.
pub fn with_wallet<T, F>(data_file_dir: &str, f: F) -> Result<T, Error>
where
F: FnOnce(&mut WalletData) -> T,
where F: FnOnce(&mut WalletData) -> T
{
// create directory if it doesn't exist
fs::create_dir_all(data_file_dir).unwrap_or_else(|why| {
info!("! {:?}", why.kind());
info!(LOGGER, "! {:?}", why.kind());
});
let data_file_path = &format!("{}{}{}", data_file_dir, MAIN_SEPARATOR, DAT_FILE);
@@ -229,6 +229,7 @@ impl WalletData {
return Err(e);
}
debug!(
LOGGER,
"failed to obtain wallet.lock, retries - {}, sleeping",
retries
);
@@ -266,25 +267,25 @@ impl WalletData {
/// Read the wallet data from disk.
fn read(data_file_path: &str) -> Result<WalletData, Error> {
let data_file = File::open(data_file_path).map_err(|e| {
Error::WalletData(format!("Could not open {}: {}", data_file_path, e))
})?;
serde_json::from_reader(data_file).map_err(|e| {
Error::WalletData(format!("Error reading {}: {}", data_file_path, e))
})
let data_file =
File::open(data_file_path)
.map_err(|e| Error::WalletData(format!("Could not open {}: {}", data_file_path, e)))?;
serde_json::from_reader(data_file)
.map_err(|e| Error::WalletData(format!("Error reading {}: {}", data_file_path, e)))
}
/// Write the wallet data to disk.
fn write(&self, data_file_path: &str) -> Result<(), Error> {
let mut data_file = File::create(data_file_path).map_err(|e| {
Error::WalletData(format!("Could not create {}: {}", data_file_path, e))
})?;
let res_json = serde_json::to_vec_pretty(self).map_err(|e| {
Error::WalletData(format!("Error serializing wallet data: {}", e))
})?;
data_file.write_all(res_json.as_slice()).map_err(|e| {
Error::WalletData(format!("Error writing {}: {}", data_file_path, e))
})
let mut data_file =
File::create(data_file_path)
.map_err(|e| {
Error::WalletData(format!("Could not create {}: {}", data_file_path, e))
})?;
let res_json = serde_json::to_vec_pretty(self)
.map_err(|e| Error::WalletData(format!("Error serializing wallet data: {}", e)))?;
data_file
.write_all(res_json.as_slice())
.map_err(|e| Error::WalletData(format!("Error writing {}: {}", data_file_path, e)))
}
/// Append a new output data to the wallet data.
@@ -306,11 +307,10 @@ impl WalletData {
/// Select a subset of unspent outputs to spend in a transaction
/// transferring the provided amount.
pub fn select(
&self,
fingerprint: keychain::Fingerprint,
amount: u64,
) -> (Vec<OutputData>, i64) {
pub fn select(&self,
fingerprint: keychain::Fingerprint,
amount: u64)
-> (Vec<OutputData>, i64) {
let mut to_spend = vec![];
let mut input_total = 0;
@@ -352,11 +352,10 @@ struct JSONPartialTx {
/// Encodes the information for a partial transaction (not yet completed by the
/// receiver) into JSON.
pub fn partial_tx_to_json(
receive_amount: u64,
blind_sum: keychain::BlindingFactor,
tx: Transaction,
) -> String {
pub fn partial_tx_to_json(receive_amount: u64,
blind_sum: keychain::BlindingFactor,
tx: Transaction)
-> String {
let partial_tx = JSONPartialTx {
amount: receive_amount,
blind_sum: util::to_hex(blind_sum.secret_key().as_ref().to_vec()),
@@ -367,10 +366,9 @@ pub fn partial_tx_to_json(
/// Reads a partial transaction encoded as JSON into the amount, sum of blinding
/// factors and the transaction itself.
pub fn partial_tx_from_json(
keychain: &keychain::Keychain,
json_str: &str,
) -> Result<(u64, keychain::BlindingFactor, Transaction), Error> {
pub fn partial_tx_from_json(keychain: &keychain::Keychain,
json_str: &str)
-> Result<(u64, keychain::BlindingFactor, Transaction), Error> {
let partial_tx: JSONPartialTx = serde_json::from_str(json_str)?;
let blind_bin = util::from_hex(partial_tx.blind_sum)?;
@@ -380,11 +378,10 @@ pub fn partial_tx_from_json(
let blinding = keychain::BlindingFactor::from_slice(keychain.secp(), &blind_bin[..])?;
let tx_bin = util::from_hex(partial_tx.tx)?;
let tx = ser::deserialize(&mut &tx_bin[..]).map_err(|_| {
Error::Format(
"Could not deserialize transaction, invalid format.".to_string(),
)
})?;
let tx = ser::deserialize(&mut &tx_bin[..])
.map_err(|_| {
Error::Format("Could not deserialize transaction, invalid format.".to_string())
})?;
Ok((partial_tx.amount, blinding, tx))
}