Wallet: key fingerprint as string (#142)

* wallet key fingerprint as hex string
* use lowercase hex in util::to_hex for consistency with various crypto libs, add some tests for util::to_hex and util::from_hex
* filter wallet info based on ext_key fingerprint
* cleanup format for fingerprints and output status
This commit is contained in:
AntiochP 2017-09-27 19:03:59 -04:00 committed by Ignotus Peverell
parent 0b26a57ca6
commit 8800d1339d
4 changed files with 47 additions and 30 deletions

View file

@ -1,4 +1,4 @@
// Copyright 2016 The Grin Developers
// Copyright 2017 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -24,7 +24,7 @@ use std::num;
pub fn to_hex(bytes: Vec<u8>) -> String {
let mut s = String::new();
for byte in bytes {
write!(&mut s, "{:02X}", byte).expect("Unable to write");
write!(&mut s, "{:02x}", byte).expect("Unable to write");
}
s
}
@ -44,3 +44,22 @@ pub fn from_hex(hex_str: String) -> Result<Vec<u8>, num::ParseIntError> {
fn split_n(s: &str, n: usize) -> Vec<&str> {
(0 .. (s.len() - n + 1)/2 + 1).map(|i| &s[2*i .. 2*i + n]).collect()
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_to_hex() {
assert_eq!(to_hex(vec![0, 0, 0, 0]), "00000000");
assert_eq!(to_hex(vec![10, 11, 12, 13]), "0a0b0c0d");
assert_eq!(to_hex(vec![0, 0, 0, 255]), "000000ff");
}
#[test]
fn test_from_hex() {
assert_eq!(from_hex("00000000".to_string()).unwrap(), vec![0, 0, 0, 0]);
assert_eq!(from_hex("0a0b0c0d".to_string()).unwrap(), vec![10, 11, 12, 13]);
assert_eq!(from_hex("000000ff".to_string()).unwrap(), vec![0, 0, 0, 255]);
}
}

View file

@ -18,6 +18,8 @@
use std::{error, fmt};
use std::cmp::min;
use util;
use byteorder::{ByteOrder, BigEndian};
use blake2::blake2b::blake2b;
use secp::Secp256k1;
@ -54,8 +56,8 @@ impl error::Error for Error {
}
}
#[derive(Serialize, Deserialize, Clone)]
pub struct Fingerprint([u8; 4]);
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct Fingerprint(String);
impl Fingerprint {
fn from_bytes(bytes: &[u8]) -> Fingerprint {
@ -63,38 +65,20 @@ impl Fingerprint {
for i in 0..min(4, bytes.len()) {
fingerprint[i] = bytes[i];
}
Fingerprint(fingerprint)
Fingerprint(util::to_hex(fingerprint.to_vec()))
}
fn zero() -> Fingerprint {
Fingerprint([0; 4])
Fingerprint::from_bytes(&[0; 4])
}
}
impl PartialEq for Fingerprint {
fn eq(&self, other: &Self) -> bool {
self.0.as_ref() == other.0.as_ref()
impl fmt::Display for Fingerprint {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
f.write_str(&self.0)
}
}
impl ::std::fmt::Display for Fingerprint {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
for i in self.0.iter().cloned() {
try!(write!(f, "{:02x}", i));
}
write!(f, "")
}
}
impl ::std::fmt::Debug for Fingerprint {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
try!(write!(f, "{}(", stringify!(Fingerprint)));
for i in self.0.iter().cloned() {
try!(write!(f, "{:02x}", i));
}
write!(f, ")")
}
}
#[derive(Serialize, Deserialize, Clone)]
pub struct Identifier([u8; 20]);

View file

@ -27,11 +27,13 @@ pub fn show_info(config: &WalletConfig, ext_key: &ExtendedKey) {
println!("Outputs - ");
println!("fingerprint, n_child, height, lock_height, status, value");
println!("----------------------------------");
for out in &mut wallet_data.outputs {
for out in &mut wallet_data.outputs
.iter()
.filter(|o| o.fingerprint == ext_key.fingerprint ) {
let key = ext_key.derive(&secp, out.n_child).unwrap();
println!(
"{}, {}, {}, {}, {:?}, {}",
"{}, {}, {}, {}, {}, {}",
key.identifier().fingerprint(),
out.n_child,
out.height,

View file

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use std::{num, thread, time};
use std::{fmt, num, thread, time};
use std::convert::From;
use std::fs::{self, File, OpenOptions};
use std::io::Write;
@ -114,6 +114,18 @@ pub enum OutputStatus {
Spent,
}
impl fmt::Display for OutputStatus {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
OutputStatus::Unconfirmed => write!(f, "Unconfirmed"),
OutputStatus::Unspent => write!(f, "Unspent"),
OutputStatus::Immature => write!(f, "Immature"),
OutputStatus::Locked => write!(f, "Locked"),
OutputStatus::Spent => write!(f, "Spent"),
}
}
}
/// Information about an output that's being tracked by the wallet. Must be
/// enough to reconstruct the commitment associated with the ouput when the
/// root private key is known.