Make flow computation deterministic.
This commit is contained in:
parent
7821daf532
commit
e06ce20a8f
3 changed files with 32 additions and 25 deletions
|
@ -49,7 +49,7 @@ impl<'a> Adjacencies<'a> {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|(_, cap)| *cap != U256::from(0))
|
.filter(|(_, cap)| *cap != U256::from(0))
|
||||||
.collect::<Vec<(Node, U256)>>();
|
.collect::<Vec<(Node, U256)>>();
|
||||||
result.sort_unstable_by_key(|(_, capacity)| Reverse(*capacity));
|
result.sort_unstable_by_key(|(addr, capacity)| (Reverse(*capacity), addr.clone()));
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -241,7 +241,9 @@ fn reduce_transfers(
|
||||||
if all_edges.clone().count() <= max_transfers as usize {
|
if all_edges.clone().count() <= max_transfers as usize {
|
||||||
return reduced_flow;
|
return reduced_flow;
|
||||||
}
|
}
|
||||||
let ((f, t), c) = all_edges.min_by_key(|(_, c)| *c).unwrap();
|
let ((f, t), c) = all_edges
|
||||||
|
.min_by_key(|(addr, c)| (*c, addr.clone()))
|
||||||
|
.unwrap();
|
||||||
reduced_flow += *c;
|
reduced_flow += *c;
|
||||||
prune_edge(used_edges, (&f, &t), *c);
|
prune_edge(used_edges, (&f, &t), *c);
|
||||||
}
|
}
|
||||||
|
@ -334,7 +336,7 @@ fn smallest_edge_in_set(
|
||||||
(a, b, capacity)
|
(a, b, capacity)
|
||||||
})
|
})
|
||||||
.filter(|(_, _, capacity)| capacity.is_some())
|
.filter(|(_, _, capacity)| capacity.is_some())
|
||||||
.min_by_key(|(_, _, capacity)| capacity.unwrap())
|
.min_by_key(|(a, b, capacity)| (capacity.unwrap(), *a, *b))
|
||||||
{
|
{
|
||||||
Some((a.clone(), b.clone()))
|
Some((a.clone(), b.clone()))
|
||||||
} else {
|
} else {
|
||||||
|
@ -348,9 +350,9 @@ fn smallest_edge_from(
|
||||||
) -> Option<(Node, U256)> {
|
) -> Option<(Node, U256)> {
|
||||||
used_edges.get(n).and_then(|out| {
|
used_edges.get(n).and_then(|out| {
|
||||||
out.iter()
|
out.iter()
|
||||||
.min_by_key(|(_, c)| {
|
.min_by_key(|(addr, c)| {
|
||||||
assert!(**c != U256::from(0));
|
assert!(**c != U256::from(0));
|
||||||
*c
|
(*c, *addr)
|
||||||
})
|
})
|
||||||
.map(|(t, c)| (t.clone(), *c))
|
.map(|(t, c)| (t.clone(), *c))
|
||||||
})
|
})
|
||||||
|
@ -364,9 +366,9 @@ fn smallest_edge_to(
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, out)| out.contains_key(n))
|
.filter(|(_, out)| out.contains_key(n))
|
||||||
.map(|(t, out)| (t, out[n]))
|
.map(|(t, out)| (t, out[n]))
|
||||||
.min_by_key(|(_, c)| {
|
.min_by_key(|(addr, c)| {
|
||||||
assert!(*c != U256::from(0));
|
assert!(*c != U256::from(0));
|
||||||
*c
|
(*c, *addr)
|
||||||
})
|
})
|
||||||
.map(|(t, c)| (t.clone(), c))
|
.map(|(t, c)| (t.clone(), c))
|
||||||
}
|
}
|
||||||
|
@ -433,7 +435,7 @@ fn extract_transfers(
|
||||||
mut used_edges: HashMap<Node, HashMap<Node, U256>>,
|
mut used_edges: HashMap<Node, HashMap<Node, U256>>,
|
||||||
) -> Vec<Edge> {
|
) -> Vec<Edge> {
|
||||||
let mut transfers: Vec<Edge> = Vec::new();
|
let mut transfers: Vec<Edge> = Vec::new();
|
||||||
let mut account_balances: HashMap<Address, U256> = HashMap::new();
|
let mut account_balances: BTreeMap<Address, U256> = BTreeMap::new();
|
||||||
account_balances.insert(*source, *amount);
|
account_balances.insert(*source, *amount);
|
||||||
|
|
||||||
while !account_balances.is_empty()
|
while !account_balances.is_empty()
|
||||||
|
@ -461,25 +463,30 @@ fn extract_transfers(
|
||||||
|
|
||||||
fn next_full_capacity_edge(
|
fn next_full_capacity_edge(
|
||||||
used_edges: &HashMap<Node, HashMap<Node, U256>>,
|
used_edges: &HashMap<Node, HashMap<Node, U256>>,
|
||||||
account_balances: &HashMap<Address, U256>,
|
account_balances: &BTreeMap<Address, U256>,
|
||||||
) -> Edge {
|
) -> Edge {
|
||||||
for (account, balance) in account_balances {
|
for (account, balance) in account_balances {
|
||||||
for intermediate in used_edges
|
let edge = used_edges
|
||||||
.get(&Node::Node(*account))
|
.get(&Node::Node(*account))
|
||||||
.unwrap_or(&HashMap::new())
|
.map(|v| {
|
||||||
.keys()
|
v.keys().flat_map(|intermediate| {
|
||||||
{
|
used_edges[intermediate]
|
||||||
for (trust_node, capacity) in &used_edges[intermediate] {
|
.iter()
|
||||||
let (to, token) = as_trust_node(trust_node);
|
.filter(|(_, capacity)| *balance >= **capacity)
|
||||||
if *balance >= *capacity {
|
.map(|(trust_node, capacity)| {
|
||||||
return Edge {
|
let (to, token) = as_trust_node(trust_node);
|
||||||
from: *account,
|
Edge {
|
||||||
to: *to,
|
from: *account,
|
||||||
token: *token,
|
to: *to,
|
||||||
capacity: *capacity,
|
token: *token,
|
||||||
};
|
capacity: *capacity,
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.and_then(|edges| edges.min());
|
||||||
|
if let Some(edge) = edge {
|
||||||
|
return edge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic!();
|
panic!();
|
||||||
|
|
|
@ -18,7 +18,7 @@ mod flow;
|
||||||
// C: if "token" is C's token (this is a "send to owner" edge): infinity or the sum of all incoming edges.
|
// C: if "token" is C's token (this is a "send to owner" edge): infinity or the sum of all incoming edges.
|
||||||
// otherwise: the max of all capacity-network edges of the form (*, token, to) or the trust limit of "to" for "token" tokens.
|
// otherwise: the max of all capacity-network edges of the form (*, token, to) or the trust limit of "to" for "token" tokens.
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
|
#[derive(Debug, Eq, PartialEq, Hash, Clone, PartialOrd, Ord)]
|
||||||
pub enum Node {
|
pub enum Node {
|
||||||
Node(Address),
|
Node(Address),
|
||||||
BalanceNode(Address, Address),
|
BalanceNode(Address, Address),
|
||||||
|
|
Loading…
Reference in a new issue