1use std::collections::HashSet;
12
13use rand::Rng;
14
15use crate::utils::*;
16use crate::transaction::{Type, Transaction, Group};
17use crate::schema::Schema;
18use crate::state::{State, OrderCoinsMap};
19
20
21#[derive(Debug, Clone)]
23pub struct Pool {
24 groups: Vec<Group>,
25 senders: Vec<U256>,
26}
27
28
29impl Pool {
30 pub fn new() -> Self {
32 Self {
33 groups: Vec::new(),
34 senders: Vec::new(),
35 }
36 }
37
38 pub fn clear(&mut self) {
40 self.groups.clear();
41 self.senders.clear();
42 }
43
44 pub fn add(&mut self, group: Group, sender: U256) {
47 self.groups.push(group);
48 self.senders.push(sender);
49 }
50
51 pub fn update(&mut self, state: &State, schema: &Schema) {
55 let old_groups = self.groups.clone();
56 self.groups = Vec::new();
57 self.senders = Vec::new();
58 for old_group in old_groups.iter() {
59 let senders = Transaction::calc_senders(&old_group.transactions(),
60 state, schema);
61 if let Ok(group) = Group::new(old_group.transactions().to_vec(),
62 state, &senders) {
63 self.add(group, senders[0].clone());
64 }
65 }
66 }
67
68 pub fn prepare<R: Rng>(&self, rng: &mut R, state: &State, schema: &Schema,
71 validator_key: &U256, groups_max: Option<usize>) ->
72 (Vec<Transaction>, Vec<U256>) {
73 let mut transactions = Vec::new();
75 let mut senders = Vec::new();
76
77 let validator = schema.get_public(validator_key);
79
80 let mut validator_resource = state.get_coins(&validator).cloned()
82 .unwrap_or(OrderCoinsMap::new());
83
84 let mut coins_seen = HashSet::new();
86
87 let mut counter = 0;
89
90 for (group, sender) in self.groups.iter().zip(self.senders.iter()) {
92 if let Some(groups_max) = groups_max {
94 if counter >= groups_max {
95 break;
96 }
97 }
98
99 if group.transactions().iter()
101 .any(|tr| coins_seen.contains(&tr.coin)) {
102 continue;
103 }
104
105 for tr in group.transactions().iter() {
107 coins_seen.insert(tr.coin.clone());
108 }
109
110 let group_senders = vec![sender.clone(); group.len()];
112
113 let order = group.get_order(state, &group_senders);
115
116 let ext_trs: Option<Vec<Transaction>> = match group.get_type() {
118 Type::Transfer => Some(vec![]),
119 Type::Merge => [order].iter().map(|ord| {
120 let coin = Self::get_validator_coin(
121 ord, &mut validator_resource, &coins_seen
122 )?;
123 let counter = state.get_coin_counter(&coin);
124 coins_seen.insert(coin.clone());
125 Some(Transaction::build(rng, coin, sender.clone(),
126 validator_key, counter, schema))
127 }).collect(),
128 Type::Split => [order-1, order-2, order-2].iter().map(|ord| {
129 let coin = Self::get_validator_coin(
130 ord, &mut validator_resource, &coins_seen
131 )?;
132 let counter = state.get_coin_counter(&coin);
133 coins_seen.insert(coin.clone());
134 Some(Transaction::build(rng, coin, sender.clone(),
135 validator_key, counter, schema))
136 }).collect(),
137 _ => panic!("Invalid group type"),
138 };
139
140 if let Some(ext_trs) = ext_trs {
142 senders.extend(group_senders);
143 senders.extend(vec![validator.clone(); ext_trs.len()]);
144
145 transactions.extend(group.transactions().iter().cloned());
146 transactions.extend(ext_trs);
147
148 counter += 1;
149 }
150 }
151
152 (transactions, senders)
154 }
155
156 fn get_validator_coin(order: &u64, resource: &mut OrderCoinsMap,
158 ignore_coins: &HashSet<U256>) -> Option<U256> {
159 if let Some(set) = resource.get_mut(&order) {
160 let coin_opt = set.iter().filter(|c| !ignore_coins.contains(c))
161 .next().cloned();
162
163 if let Some(coin) = coin_opt {
164 set.remove(&coin);
165 return Some(coin);
166 }
167 }
168 None
169 }
170}