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
use std::collections::BTreeSet;
use std::collections::HashMap;
use std::fmt::Display;
use std::hash::Hash;
use std::iter::FromIterator;

use crate::token::Scope;

#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Origin {
    pub(crate) inner: BTreeSet<usize>,
}

impl Origin {
    pub fn insert(&mut self, i: usize) {
        self.inner.insert(i);
    }

    pub fn union(&self, other: &Self) -> Self {
        Origin {
            inner: self.inner.union(&other.inner).cloned().collect(),
        }
    }

    pub fn is_superset(&self, other: &Self) -> bool {
        self.inner.is_superset(&other.inner)
    }
}

impl<'a> Extend<&'a usize> for Origin {
    fn extend<T: IntoIterator<Item = &'a usize>>(&mut self, iter: T) {
        self.inner.extend(iter)
    }
}

impl Extend<usize> for Origin {
    fn extend<T: IntoIterator<Item = usize>>(&mut self, iter: T) {
        self.inner.extend(iter)
    }
}

impl<'a> FromIterator<&'a usize> for Origin {
    fn from_iter<T: IntoIterator<Item = &'a usize>>(iter: T) -> Self {
        Self {
            inner: iter.into_iter().cloned().collect(),
        }
    }
}

impl FromIterator<usize> for Origin {
    fn from_iter<T: IntoIterator<Item = usize>>(iter: T) -> Self {
        Self {
            inner: iter.into_iter().collect(),
        }
    }
}

impl Display for Origin {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let mut it = self.inner.iter();

        if let Some(i) = it.next() {
            if *i == usize::MAX {
                write!(f, "authorizer")?;
            } else {
                write!(f, "{i}")?;
            }
        }

        for i in it {
            if *i == usize::MAX {
                write!(f, ", authorizer")?;
            } else {
                write!(f, ", {i}")?;
            }
        }
        Ok(())
    }
}

/// This represents the sets of origins trusted by a rule
#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct TrustedOrigins(Origin);

impl TrustedOrigins {
    pub fn default() -> TrustedOrigins {
        let mut origins = Origin::default();
        origins.insert(usize::MAX);
        origins.insert(0);
        TrustedOrigins(origins)
    }

    pub fn from_scopes(
        rule_scopes: &[Scope],
        default_origins: &TrustedOrigins,
        current_block: usize,
        public_key_to_block_id: &HashMap<usize, Vec<usize>>,
    ) -> TrustedOrigins {
        if rule_scopes.is_empty() {
            let mut origins = default_origins.clone();
            origins.0.insert(current_block);
            origins.0.insert(usize::MAX);
            return origins;
        }

        let mut origins = Origin::default();
        origins.insert(usize::MAX);
        origins.insert(current_block);

        for scope in rule_scopes {
            match scope {
                Scope::Authority => {
                    origins.insert(0);
                }
                Scope::Previous => {
                    if current_block != usize::MAX {
                        origins.extend(0..current_block + 1)
                    }
                }
                Scope::PublicKey(key_id) => {
                    if let Some(block_ids) = public_key_to_block_id.get(&(*key_id as usize)) {
                        origins.extend(block_ids.iter())
                    }
                }
            }
        }

        TrustedOrigins(origins)
    }

    pub fn contains(&self, fact_origin: &Origin) -> bool {
        self.0.is_superset(fact_origin)
    }
}

impl FromIterator<usize> for TrustedOrigins {
    fn from_iter<T: IntoIterator<Item = usize>>(iter: T) -> Self {
        Self(iter.into_iter().collect())
    }
}

impl<'a> FromIterator<&'a usize> for TrustedOrigins {
    fn from_iter<T: IntoIterator<Item = &'a usize>>(iter: T) -> Self {
        Self(iter.into_iter().cloned().collect())
    }
}