kon-cli/src/wallet.rs

79 lines
2.2 KiB
Rust

use std::collections::HashMap;
use cryptoxide::hashing::blake2b_256;
use minicbor::encode;
use pallas_addresses::ShelleyPaymentPart;
use pallas_crypto::hash::{Hash, Hasher};
use pallas_crypto::key::ed25519::Signature;
use pallas_crypto::{self, key::ed25519::SecretKey};
use pallas_primitives::conway::{Tx, VKeyWitness};
use crate::tx::plutus::non_empty_set;
use crate::utils::v2a;
use rand::{rngs::OsRng, TryRngCore};
const PREFIX: &str = "wallet_";
pub struct Wallet {
pub skey: [u8; 32],
}
impl Wallet {
pub fn vkey(&self) -> [u8; 32] {
SecretKey::from(self.skey).public_key().into()
}
pub fn key_hash(&self) -> Hash<28> {
Hasher::<224>::hash(SecretKey::from(self.skey).public_key().as_ref())
}
pub fn payment_credential(&self) -> ShelleyPaymentPart {
ShelleyPaymentPart::Key(self.key_hash())
}
pub fn sign_hash(&self, h: &[u8; 32]) -> Signature {
SecretKey::from(self.skey).sign(h)
}
pub fn sign(&self, tx: &mut Tx) {
let mut msg = Vec::new();
encode(&tx.transaction_body, &mut msg).unwrap();
let tx_hash = blake2b_256(&msg);
let sig = self.sign_hash(&tx_hash);
tx.transaction_witness_set.vkeywitness = non_empty_set(vec![VKeyWitness {
vkey: self.vkey().to_vec().into(),
signature: sig.as_ref().to_vec().into(),
}])
}
}
pub fn from_env(env: &HashMap<String, String>) -> Wallet {
let wallet_env: HashMap<String, String> = env
.iter()
.filter_map(|(k, v)| k.strip_prefix(PREFIX).map(|k| (k.to_string(), v.clone())))
.collect();
let raw = wallet_env.get("key").expect("wallet key not found");
let skey = parse_raw_skey(raw);
Wallet { skey }
}
pub fn generate() -> [u8; 32] {
let mut key = [0u8; 32];
OsRng.try_fill_bytes(&mut key).unwrap();
key
}
fn parse_raw_skey(raw: &str) -> [u8; 32] {
// FIXME :: Not tested
if raw.len() == 64 {
// Assume hex
v2a(hex::decode(raw).expect("expected hex")).expect("wrong length")
} else if raw.len() == 70 {
// Assume Bech
v2a(bech32::decode(raw).unwrap().1).expect("wrong length")
} else {
panic!("Not supported")
}
}