1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
use std::fmt; use std::rc::Rc; use chrono::Utc; use ed25519_dalek::Keypair; use ed25519_dalek::PublicKey; use rand::rngs::OsRng; use cryptonote_base58::{from_base58, to_base58}; use leb128; use tiny_keccak::keccak256; pub struct Address { prefix: u64, data: Rc<String>, spend: PublicKey, view: PublicKey, } pub struct Account { spend: Keypair, view: Keypair, address: Address, timestamp: u64, } pub fn unix_timestamp() -> u64 { return Utc::now().timestamp() as u64; } impl Address { pub fn new(prefix: u64, spend: PublicKey, view: PublicKey) -> Address { Address { prefix, spend, view, data: Rc::new(Address::to(prefix, spend, view)), } } pub fn get(&self) -> &String { &*self.data } pub fn get_prefix(&self) -> u64 { self.prefix } pub fn from(prefix: u64, address: &String) -> Address { let addr = address.to_string(); let bytes = from_base58(addr).expect("Fail to decode base58!"); let (given, checksum) = bytes.split_at(bytes.len() - 4); let new_checksum = &keccak256(given)[..4]; if new_checksum != checksum { panic!( "Checksum error: expected: {:x?}, got: {:x?}!", checksum, new_checksum ); } let (mut new_prefix_bytes, keys) = given.split_at(given.len() - 64); let new_prefix = leb128::read::unsigned(&mut new_prefix_bytes).expect("Fail to read prefix!"); if prefix != new_prefix { panic!( "Prefix not match: expected: {}, got: {}!", prefix, new_prefix ); } let (spend_bytes, view_bytes) = keys.split_at(32); let spend: PublicKey = PublicKey::from_bytes(spend_bytes).unwrap(); let view: PublicKey = PublicKey::from_bytes(view_bytes).unwrap(); Address { prefix, spend, view, data: Rc::new(address.to_string()), } } pub fn to(prefix: u64, spend: PublicKey, view: PublicKey) -> String { let mut tag = vec![]; leb128::write::unsigned(&mut tag, prefix).expect("Fail to write prefix!"); let spend_array: Vec<u8> = spend.to_bytes().to_vec(); let view_array: Vec<u8> = view.to_bytes().to_vec(); let temp = tag.as_slice(); let given = [&temp, spend_array.as_slice(), view_array.as_slice()].concat(); let checksum = &keccak256(given.as_slice())[..4]; let temp2 = tag.as_slice(); let pre_base58 = [ &temp2, spend_array.as_slice(), view_array.as_slice(), checksum, ] .concat(); let base58 = to_base58(pre_base58).expect("Fail to encode base58!"); base58 } } impl fmt::Display for Address { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "\nAdderess: \n spend key: {:x?},\n view key: {:x?}", self.spend.to_bytes(), self.view.to_bytes() ) } } impl Account { pub fn get_address(&self) -> &String { return self.address.get(); } pub fn new(prefix: u64) -> Account { let mut spend_rng: OsRng = OsRng::new().unwrap(); let mut view_rng: OsRng = OsRng::new().unwrap(); let spend: Keypair = Keypair::generate(&mut spend_rng); let view: Keypair = Keypair::generate(&mut view_rng); let address: Address = Address::new(prefix, spend.public, view.public); Account { address, spend, view, timestamp: unix_timestamp(), } } } #[cfg(test)] mod tests { use super::*; #[test] fn should_get_current_time() { let now1: u64 = unix_timestamp(); assert!(now1 > 10000); } #[test] fn should_create_account() { let prefix = 0x3d; let acc: Account = Account::new(prefix); let now1: u64 = unix_timestamp(); assert!(acc.address.prefix == prefix); assert!(acc.address.get_prefix() == prefix); assert!(acc.timestamp - now1 < 10); println!("{:?}\n", acc.get_address()); println!("{:?}\n", acc.get_address()); Address::from(prefix, acc.get_address()); println!("{}\n", acc.address); println!("spend: \n {:x?}\n", acc.address.spend.to_bytes()); println!("view: \n {:x?}\n", acc.address.view.to_bytes()); } #[test] fn should_create_account1() { let prefix = 0x3d23; let acc: Account = Account::new(prefix); let now1: u64 = unix_timestamp(); assert!(acc.address.prefix == prefix); assert!(acc.address.get_prefix() == prefix); assert!(acc.timestamp - now1 < 10); println!("{:?}\n", acc.get_address()); println!("{:?}\n", acc.get_address()); Address::from(prefix, acc.get_address()); println!("{}\n", acc.address); println!("spend: \n {:x?}\n", acc.address.spend.to_bytes()); println!("view: \n {:x?}\n", acc.address.view.to_bytes()); } }