/
utxo.rs
93 lines (78 loc) · 2.52 KB
/
utxo.rs
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
use chain_addr::Discrimination;
use chain_impl_mockchain::transaction::{TransactionSignDataHash, Witness};
use jormungandr_lib::{
crypto::{
hash::Hash,
key::{self, Identifier},
},
interfaces::Address,
};
use rand_chacha::ChaChaRng;
use rand_core::{CryptoRng, RngCore, SeedableRng};
pub type SpendingKey = key::SigningKey<chain_crypto::Ed25519Extended>;
/// wallet for an account
#[derive(Debug, Clone)]
pub struct Wallet {
/// this is the root seed of the wallet, everytime we will require
/// the wallet to update we will update the rng, we keep the `seed`
/// so we may reproduce the steps of the wallet
#[allow(dead_code)]
seed: [u8; 32],
rng: ChaChaRng,
/// the spending key
signing_keys: Vec<SpendingKey>,
discrimination: Discrimination,
}
impl Wallet {
pub fn generate<RNG>(rng: &mut RNG, discrimination: Discrimination) -> Self
where
RNG: CryptoRng + RngCore,
{
let mut seed = [0; 32];
rng.fill_bytes(&mut seed);
let mut wallet = Self {
signing_keys: Vec::new(),
seed,
rng: ChaChaRng::from_seed(seed),
discrimination,
};
wallet.generate_new_signing_key();
wallet
}
pub fn generate_new_signing_key(&mut self) -> &SpendingKey {
let key = key::SigningKey::generate(&mut self.rng);
self.signing_keys.push(key);
self.last_signing_key()
}
pub fn address(&self) -> Address {
self.address_nth(0)
}
pub fn address_nth(&self, i: usize) -> Address {
self.signing_key(i)
.identifier()
.to_single_address(self.discrimination)
.into()
}
pub fn identifier(&self) -> Identifier<chain_crypto::Ed25519> {
self.last_signing_key().identifier()
}
pub fn signing_key(&self, i: usize) -> &SpendingKey {
self.signing_keys.get(i).expect("no signing key found")
}
pub fn last_signing_key(&self) -> &SpendingKey {
let index = self.signing_keys.len() - 1;
self.signing_keys.get(index).expect("no signing key found")
}
pub fn save_to<W: std::io::Write>(&self, mut w: W) -> std::io::Result<()> {
writeln!(w, "{}", self.last_signing_key().to_bech32_str())
}
pub fn mk_witness(
&self,
block0_hash: &Hash,
signing_data: &TransactionSignDataHash,
) -> Witness {
Witness::new_utxo(&(*block0_hash).into_hash(), signing_data, |d| {
self.last_signing_key().as_ref().sign(d)
})
}
}