wallet.rs (2002B)
1 use ed25519_dalek::{Signature, Signer, SigningKey}; 2 use sha2::{Digest, Sha256}; 3 4 use super::block::LeaderProofPayload; 5 use super::{ 6 LeaderProof, PUBLIC_KEY_BYTES, RevealBundle, RevealBundlePayload, decode_hex_array, hex_encode, 7 }; 8 9 const WALLET_SEED_DOMAIN: &str = "iuna-wallet-seed"; 10 11 #[derive(Clone, Debug, Eq, PartialEq)] 12 pub struct Wallet { 13 address: String, 14 secret: String, 15 } 16 17 impl Wallet { 18 pub fn from_seed(seed: &str) -> Self { 19 let seed_hash = Sha256::digest(format!("{WALLET_SEED_DOMAIN}:{seed}").as_bytes()); 20 let mut signing_seed = [0_u8; 32]; 21 signing_seed.copy_from_slice(&seed_hash); 22 let signing_key = SigningKey::from_bytes(&signing_seed); 23 let secret = hex_encode(signing_seed); 24 let address = hex_encode(signing_key.verifying_key().to_bytes()); 25 Self { address, secret } 26 } 27 28 pub fn address(&self) -> &str { 29 &self.address 30 } 31 32 pub(super) fn sign_payload(&self, payload: &str) -> String { 33 let seed = 34 decode_hex_array::<PUBLIC_KEY_BYTES>(&self.secret).expect("wallet secret is valid hex"); 35 let signing_key = SigningKey::from_bytes(&seed); 36 let signature: Signature = signing_key.sign(payload.as_bytes()); 37 hex_encode(signature.to_bytes()) 38 } 39 40 pub(super) fn leader_proof(&self, payload: &LeaderProofPayload) -> LeaderProof { 41 let signature = self.sign_payload(&payload.canonical()); 42 LeaderProof { 43 ticket_id: payload.ticket_id.clone(), 44 public_key: self.address.clone(), 45 signature, 46 } 47 } 48 49 pub(super) fn reveal_bundle(&self, payload: RevealBundlePayload) -> RevealBundle { 50 let signature = self.sign_payload(&payload.canonical()); 51 RevealBundle { 52 height: payload.height, 53 prev_hash: payload.prev_hash, 54 slot: payload.slot, 55 member: self.address.clone(), 56 reveals: payload.reveals, 57 signature, 58 } 59 } 60 }