Skip to content

Commit 12bf10e

Browse files
committed
WIP
1 parent 4fb86d9 commit 12bf10e

File tree

30 files changed

+1310
-34
lines changed

30 files changed

+1310
-34
lines changed

catalyst-toolbox/src/bin/cli/advisor_reviews/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ impl Export {
8383
let reviews = read_vca_reviews_aggregated_file(&from)?;
8484
match format {
8585
OutputFormat::Csv => {
86-
utils::csv::dump_data_to_csv(&reviews, &to)?;
86+
utils::csv::dump_data_to_csv(reviews.iter(), &to)?;
8787
}
8888
OutputFormat::Json => {
8989
serde_json::to_writer(open_file_write(&Some(to))?, &reviews)?;

catalyst-toolbox/src/bin/cli/kedqr/decode/img.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,19 @@ use catalyst_toolbox::kedqr::KeyQrCode;
33
use catalyst_toolbox::kedqr::QrPin;
44
use chain_crypto::AsymmetricKey;
55
use chain_crypto::Ed25519Extended;
6+
use chain_crypto::SecretKey;
67
use std::error::Error;
78
use std::fs::File;
89
use std::io::Write;
10+
use std::path::Path;
911
use std::path::PathBuf;
1012

11-
pub fn secret_from_qr(
13+
pub fn save_secret_from_qr(
1214
qr: PathBuf,
1315
output: Option<PathBuf>,
1416
pin: QrPin,
1517
) -> Result<(), Box<dyn Error>> {
16-
let img = image::open(qr)?;
17-
let secret = KeyQrCode::decode(img, &pin.password)?;
18-
let sk = secret.first().unwrap().clone();
18+
let sk = secret_from_qr(&qr, pin)?;
1919
let hrp = Ed25519Extended::SECRET_BECH32_HRP;
2020
let secret_key = bech32::encode(hrp, sk.leak_secret().to_base32(), Variant::Bech32)?;
2121

@@ -32,3 +32,12 @@ pub fn secret_from_qr(
3232
};
3333
Ok(())
3434
}
35+
36+
pub fn secret_from_qr(
37+
qr: impl AsRef<Path>,
38+
pin: QrPin,
39+
) -> Result<SecretKey<Ed25519Extended>, catalyst_toolbox::kedqr::KeyQrCodeError> {
40+
let img = image::open(qr)?;
41+
let secret = KeyQrCode::decode(img, &pin.password)?;
42+
Ok(secret.first().unwrap().clone())
43+
}

catalyst-toolbox/src/bin/cli/kedqr/decode/mod.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
mod hash;
21
mod img;
2+
mod payload;
33

4-
use crate::cli::kedqr::encode::QrCodeOpts;
4+
use crate::cli::kedqr::QrCodeOpts;
55
use catalyst_toolbox::kedqr::QrPin;
6-
pub use hash::decode_hash;
7-
pub use img::secret_from_qr;
6+
pub use img::{save_secret_from_qr, secret_from_qr};
7+
pub use payload::{decode_payload, secret_from_payload};
88
use std::error::Error;
99
use std::path::PathBuf;
1010
use structopt::StructOpt;
@@ -13,7 +13,7 @@ use structopt::StructOpt;
1313
#[derive(Debug, PartialEq, StructOpt)]
1414
#[structopt(rename_all = "kebab-case")]
1515
pub struct DecodeQrCodeCmd {
16-
/// Path to file containing img or hash.
16+
/// Path to file containing img or payload.
1717
#[structopt(short, long, parse(from_os_str))]
1818
input: PathBuf,
1919
/// Path to file to save secret output, if not provided console output will be attempted.
@@ -30,8 +30,8 @@ pub struct DecodeQrCodeCmd {
3030
impl DecodeQrCodeCmd {
3131
pub fn exec(self) -> Result<(), Box<dyn Error>> {
3232
match self.opts {
33-
QrCodeOpts::Hash => decode_hash(self.input, self.output, self.pin),
34-
QrCodeOpts::Img => secret_from_qr(self.input, self.output, self.pin),
33+
QrCodeOpts::Payload => decode_payload(self.input, self.output, self.pin),
34+
QrCodeOpts::Img => save_secret_from_qr(self.input, self.output, self.pin),
3535
}
3636
}
3737
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
use bech32::{ToBase32, Variant};
2+
use catalyst_toolbox::kedqr::{decode, QrPin};
3+
use chain_crypto::{AsymmetricKey, Ed25519Extended, SecretKey};
4+
use std::{
5+
error::Error,
6+
fs::{File, OpenOptions},
7+
io::{BufRead, BufReader, Write},
8+
path::{Path, PathBuf},
9+
};
10+
11+
pub fn decode_payload(
12+
input: PathBuf,
13+
output: Option<PathBuf>,
14+
pin: QrPin,
15+
) -> Result<(), Box<dyn Error>> {
16+
// generate qrcode with key and parsed pin
17+
let secret = secret_from_payload(input, pin)?;
18+
let hrp = Ed25519Extended::SECRET_BECH32_HRP;
19+
let secret_key = bech32::encode(hrp, secret.leak_secret().to_base32(), Variant::Bech32)?;
20+
// process output
21+
match output {
22+
Some(path) => {
23+
// save qr code to file, or print to stdout if it fails
24+
let mut file = File::create(path)?;
25+
file.write_all(secret_key.as_bytes())?;
26+
}
27+
None => {
28+
// prints qr code to stdout when no path is specified
29+
println!("{}", secret_key);
30+
}
31+
}
32+
Ok(())
33+
}
34+
35+
pub fn secret_from_payload(
36+
input: impl AsRef<Path>,
37+
pin: QrPin,
38+
) -> Result<SecretKey<Ed25519Extended>, catalyst_toolbox::kedqr::KeyQrCodePayloadError> {
39+
let input = OpenOptions::new()
40+
.create(false)
41+
.read(true)
42+
.write(false)
43+
.append(false)
44+
.open(&input)
45+
.expect("Could not open input file.");
46+
47+
let mut reader = BufReader::new(input);
48+
let mut payload_str = String::new();
49+
let _len = reader
50+
.read_line(&mut payload_str)
51+
.expect("Could not read input file.");
52+
payload_str = payload_str.trim_end().to_string();
53+
54+
// use parsed pin from args
55+
let pwd = pin.password;
56+
// generate qrcode with key and parsed pin
57+
decode(payload_str, &pwd)
58+
}

catalyst-toolbox/src/bin/cli/kedqr/encode/mod.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
mod hash;
21
mod img;
2+
mod payload;
33

4+
use crate::cli::kedqr::QrCodeOpts;
45
use catalyst_toolbox::kedqr::QrPin;
5-
pub use hash::generate_hash;
66
pub use img::generate_qr;
7+
pub use payload::generate_payload;
78
use std::error::Error;
89
use std::path::PathBuf;
910
use structopt::StructOpt;
@@ -29,15 +30,8 @@ pub struct EncodeQrCodeCmd {
2930
impl EncodeQrCodeCmd {
3031
pub fn exec(self) -> Result<(), Box<dyn Error>> {
3132
match self.opts {
32-
QrCodeOpts::Hash => generate_hash(self.input, self.output, self.pin),
33+
QrCodeOpts::Payload => generate_payload(self.input, self.output, self.pin),
3334
QrCodeOpts::Img => generate_qr(self.input, self.output, self.pin),
3435
}
3536
}
3637
}
37-
38-
#[derive(Debug, PartialEq, StructOpt)]
39-
#[structopt(rename_all = "kebab-case")]
40-
pub enum QrCodeOpts {
41-
Img,
42-
Hash,
43-
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
use catalyst_toolbox::kedqr::generate;
2+
use catalyst_toolbox::kedqr::QrPin;
3+
use chain_crypto::bech32::Bech32;
4+
use chain_crypto::{Ed25519Extended, SecretKey};
5+
use std::fs::File;
6+
use std::io::Write;
7+
use std::{
8+
error::Error,
9+
fs::OpenOptions,
10+
io::{BufRead, BufReader},
11+
path::PathBuf,
12+
};
13+
14+
pub fn generate_payload(
15+
input: PathBuf,
16+
output: Option<PathBuf>,
17+
pin: QrPin,
18+
) -> Result<(), Box<dyn Error>> {
19+
// open input key and parse it
20+
let key_file = OpenOptions::new()
21+
.create(false)
22+
.read(true)
23+
.write(false)
24+
.append(false)
25+
.open(&input)
26+
.expect("Could not open input file.");
27+
28+
let mut reader = BufReader::new(key_file);
29+
let mut key_str = String::new();
30+
let _key_len = reader
31+
.read_line(&mut key_str)
32+
.expect("Could not read input file.");
33+
let sk = key_str.trim_end().to_string();
34+
35+
let secret_key: SecretKey<Ed25519Extended> =
36+
SecretKey::try_from_bech32_str(&sk).expect("Malformed secret key.");
37+
// use parsed pin from args
38+
let pwd = pin.password;
39+
// generate qrcode with key and parsed pin
40+
let qr = generate(secret_key, &pwd);
41+
// process output
42+
match output {
43+
Some(path) => {
44+
// save qr code to file, or print to stdout if it fails
45+
let mut file = File::create(path)?;
46+
file.write_all(qr.as_bytes())?;
47+
}
48+
None => {
49+
// prints qr code to stdout when no path is specified
50+
println!("{}", qr);
51+
}
52+
}
53+
Ok(())
54+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
use super::QrCodeOpts;
2+
use crate::cli::kedqr::decode::{secret_from_payload, secret_from_qr};
3+
use catalyst_toolbox::kedqr::QrPin;
4+
use chain_addr::{AddressReadable, Discrimination, Kind};
5+
use chain_core::{
6+
mempack::{ReadBuf, Readable},
7+
property::Deserialize,
8+
};
9+
use chain_crypto::{Ed25519Extended, SecretKey};
10+
use chain_impl_mockchain::block::Block;
11+
use jormungandr_lib::interfaces::{Block0Configuration, Initial};
12+
use std::io::BufReader;
13+
use std::path::{Path, PathBuf};
14+
use structopt::StructOpt;
15+
use url::Url;
16+
#[derive(StructOpt, Debug)]
17+
pub struct InfoForQrCodeCmd {
18+
/// Path to file containing img or payload.
19+
#[structopt(short, long, parse(from_os_str))]
20+
input: PathBuf,
21+
22+
/// Pin code. 4-digit number is used on Catalyst.
23+
#[structopt(short, long, parse(try_from_str))]
24+
pin: QrPin,
25+
26+
/// Blockchain block0. Can be either url of local file path
27+
#[structopt(long = "block0")]
28+
pub block0: Option<String>,
29+
30+
/// Set the discrimination type to testing (default is production).
31+
#[structopt(short, long)]
32+
pub testing: bool,
33+
34+
#[structopt(flatten)]
35+
opts: QrCodeOpts,
36+
}
37+
38+
impl InfoForQrCodeCmd {
39+
pub fn exec(self) -> Result<(), Box<dyn std::error::Error>> {
40+
let secret_key: SecretKey<Ed25519Extended> = {
41+
match self.opts {
42+
QrCodeOpts::Payload => secret_from_payload(&self.input, self.pin)?,
43+
QrCodeOpts::Img => secret_from_qr(&self.input, self.pin)?,
44+
}
45+
};
46+
let kind = Kind::Account(secret_key.to_public());
47+
let address = chain_addr::Address(test_discrimination(self.testing), kind);
48+
49+
if let Some(block0_path) = &self.block0 {
50+
let block = {
51+
if Path::new(block0_path).exists() {
52+
let reader = std::fs::OpenOptions::new()
53+
.create(false)
54+
.write(false)
55+
.read(true)
56+
.append(false)
57+
.open(block0_path)?;
58+
let reader = BufReader::new(reader);
59+
Block::deserialize(reader)?
60+
} else if Url::parse(block0_path).is_ok() {
61+
let response = reqwest::blocking::get(block0_path)?;
62+
let block0_bytes = response.bytes()?.to_vec();
63+
Block::read(&mut ReadBuf::from(&block0_bytes))?
64+
} else {
65+
panic!("invalid block0: should be either path to filesystem or url ");
66+
}
67+
};
68+
let genesis = Block0Configuration::from_block(&block)?;
69+
70+
for initial in genesis.initial.iter() {
71+
if let Initial::Fund(initial_utxos) = initial {
72+
if let Some(entry) = initial_utxos
73+
.iter()
74+
.find(|x| x.address == address.clone().into())
75+
{
76+
println!(
77+
"Address corresponding to input qr found in block0: '{}' with value: '{}'",
78+
AddressReadable::from_address(&test_prefix(self.testing),&address), entry.value);
79+
return Ok(());
80+
}
81+
}
82+
}
83+
eprintln!("Address corresponding to input qr not found in block0");
84+
} else {
85+
println!(
86+
"Address: {}",
87+
AddressReadable::from_address(&test_prefix(self.testing), &address)
88+
);
89+
}
90+
Ok(())
91+
}
92+
}
93+
94+
pub fn test_discrimination(testing: bool) -> Discrimination {
95+
match testing {
96+
false => Discrimination::Production,
97+
true => Discrimination::Test,
98+
}
99+
}
100+
101+
pub fn test_prefix(testing: bool) -> String {
102+
match test_discrimination(testing) {
103+
Discrimination::Production => "ca".to_string(),
104+
Discrimination::Test => "ta".to_string(),
105+
}
106+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,39 @@
11
mod decode;
22
mod encode;
3+
mod info;
4+
mod verify;
35

46
use std::error::Error;
57
use structopt::StructOpt;
8+
69
#[derive(StructOpt)]
710
#[structopt(rename_all = "kebab-case")]
811
pub enum QrCodeCmd {
912
/// Encode qr code
1013
Encode(encode::EncodeQrCodeCmd),
1114
/// Decode qr code
1215
Decode(decode::DecodeQrCodeCmd),
16+
/// Prints information for qr code
17+
Info(info::InfoForQrCodeCmd),
18+
/// Validates qr code
19+
Verify(verify::VerifyQrCodeCmd),
1320
}
1421

1522
impl QrCodeCmd {
1623
pub fn exec(self) -> Result<(), Box<dyn Error>> {
1724
match self {
1825
Self::Encode(encode) => encode.exec()?,
1926
Self::Decode(decode) => decode.exec()?,
27+
Self::Info(info) => info.exec()?,
28+
Self::Verify(verify) => verify.exec()?,
2029
};
2130
Ok(())
2231
}
2332
}
33+
34+
#[derive(Debug, PartialEq, StructOpt)]
35+
#[structopt(rename_all = "kebab-case")]
36+
pub enum QrCodeOpts {
37+
Img,
38+
Payload,
39+
}

0 commit comments

Comments
 (0)